@gajae-code/coding-agent 0.11.1 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/dist/types/cli/config-cli.d.ts +11 -1
  3. package/dist/types/cli/launch-disposition.d.ts +23 -0
  4. package/dist/types/cli/notify-cli.d.ts +1 -0
  5. package/dist/types/cli/session-picker.d.ts +2 -1
  6. package/dist/types/cli/setup-cli.d.ts +1 -1
  7. package/dist/types/commands/mcp-serve.d.ts +33 -0
  8. package/dist/types/commands/mcp.d.ts +1 -1
  9. package/dist/types/commands/notify.d.ts +0 -2
  10. package/dist/types/commands/sdk.d.ts +1 -1
  11. package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
  12. package/dist/types/config/file-lock.d.ts +14 -4
  13. package/dist/types/config/keybindings.d.ts +42 -1
  14. package/dist/types/config/model-auth.d.ts +3 -0
  15. package/dist/types/config/model-bindings-applier.d.ts +13 -0
  16. package/dist/types/config/model-discovery-manager.d.ts +49 -0
  17. package/dist/types/config/model-equivalence.d.ts +20 -0
  18. package/dist/types/config/model-registry.d.ts +16 -15
  19. package/dist/types/config/model-resolver.d.ts +28 -18
  20. package/dist/types/config/models-config-schema.d.ts +11 -0
  21. package/dist/types/config/settings-schema.d.ts +141 -11
  22. package/dist/types/config/settings.d.ts +14 -11
  23. package/dist/types/coordinator-mcp/policy.d.ts +5 -0
  24. package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
  25. package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
  26. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  27. package/dist/types/discovery/helpers.d.ts +0 -6
  28. package/dist/types/edit/index.d.ts +3 -0
  29. package/dist/types/eval/py/env.d.ts +9 -0
  30. package/dist/types/extensibility/extensions/loader.d.ts +2 -1
  31. package/dist/types/extensibility/extensions/runner.d.ts +2 -2
  32. package/dist/types/extensibility/extensions/types.d.ts +34 -3
  33. package/dist/types/extensibility/hooks/runner.d.ts +1 -1
  34. package/dist/types/extensibility/shared-events.d.ts +2 -0
  35. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
  36. package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
  37. package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
  38. package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
  39. package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
  40. package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
  41. package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
  42. package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
  43. package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
  44. package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
  45. package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
  46. package/dist/types/gjc-runtime/team-store.d.ts +160 -0
  47. package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
  48. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
  49. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
  50. package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
  51. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
  52. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
  53. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
  54. package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
  55. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
  56. package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
  57. package/dist/types/goals/runtime.d.ts +1 -0
  58. package/dist/types/goals/state.d.ts +8 -0
  59. package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
  60. package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
  61. package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
  62. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  63. package/dist/types/hindsight/state.d.ts +11 -4
  64. package/dist/types/lsp/lspmux.d.ts +5 -3
  65. package/dist/types/lsp/path-trust.d.ts +1 -0
  66. package/dist/types/main.d.ts +4 -2
  67. package/dist/types/memories/storage.d.ts +1 -0
  68. package/dist/types/modes/action-registry.d.ts +29 -0
  69. package/dist/types/modes/components/chrome.d.ts +14 -0
  70. package/dist/types/modes/components/command-palette.d.ts +27 -0
  71. package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
  72. package/dist/types/modes/components/index.d.ts +2 -1
  73. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  74. package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
  75. package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
  76. package/dist/types/modes/components/queue-pane.d.ts +12 -0
  77. package/dist/types/modes/components/read-tool-group.d.ts +6 -0
  78. package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
  79. package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
  80. package/dist/types/modes/components/settings-selector.d.ts +1 -1
  81. package/dist/types/modes/components/show-images-selector.d.ts +1 -1
  82. package/dist/types/modes/components/status-line/types.d.ts +1 -1
  83. package/dist/types/modes/components/status-line.d.ts +1 -94
  84. package/dist/types/modes/components/tasks-pane.d.ts +15 -0
  85. package/dist/types/modes/components/theme-selector.d.ts +1 -1
  86. package/dist/types/modes/components/tool-execution.d.ts +15 -0
  87. package/dist/types/modes/components/tool-status-header.d.ts +111 -0
  88. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
  89. package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
  90. package/dist/types/modes/controllers/input-controller.d.ts +8 -1
  91. package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
  92. package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
  93. package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
  94. package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
  95. package/dist/types/modes/interactive-mode.d.ts +19 -17
  96. package/dist/types/modes/jobs-observer.d.ts +2 -0
  97. package/dist/types/modes/prompt-action-autocomplete.d.ts +4 -0
  98. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
  99. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +20 -2
  100. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
  101. package/dist/types/modes/tasks-aggregator.d.ts +39 -0
  102. package/dist/types/modes/transcript-item-registry.d.ts +60 -0
  103. package/dist/types/modes/types.d.ts +20 -13
  104. package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
  105. package/dist/types/runtime-mcp/manager.d.ts +1 -1
  106. package/dist/types/sdk/broker/broker.d.ts +78 -12
  107. package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
  108. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
  109. package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
  110. package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
  111. package/dist/types/sdk/broker/session-index.d.ts +0 -1
  112. package/dist/types/sdk/broker/state-version.d.ts +2 -0
  113. package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
  114. package/dist/types/sdk/bus/config-commands.d.ts +1 -1
  115. package/dist/types/sdk/bus/config.d.ts +11 -0
  116. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  117. package/dist/types/sdk/bus/html-format.d.ts +3 -2
  118. package/dist/types/sdk/bus/index.d.ts +29 -0
  119. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  120. package/dist/types/sdk/bus/notification-service.d.ts +20 -0
  121. package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
  122. package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
  123. package/dist/types/sdk/bus/rich-document.d.ts +7 -0
  124. package/dist/types/sdk/bus/rich-render.d.ts +18 -41
  125. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
  126. package/dist/types/sdk/bus/telegram-daemon.d.ts +46 -3
  127. package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
  128. package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
  129. package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
  130. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  131. package/dist/types/sdk/host/host.d.ts +2 -0
  132. package/dist/types/sdk/index.d.ts +1 -0
  133. package/dist/types/sdk/session-directory.d.ts +56 -0
  134. package/dist/types/sdk/session.d.ts +2 -0
  135. package/dist/types/session/agent-session.d.ts +82 -47
  136. package/dist/types/session/agent-storage.d.ts +7 -0
  137. package/dist/types/session/fallback-chain-controller.d.ts +10 -2
  138. package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
  139. package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
  140. package/dist/types/session/messages.d.ts +16 -0
  141. package/dist/types/session/session-manager-internal.d.ts +14 -0
  142. package/dist/types/session/session-manager.d.ts +82 -12
  143. package/dist/types/session/session-storage.d.ts +43 -3
  144. package/dist/types/session/volatile-context-pruning.d.ts +15 -0
  145. package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
  146. package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
  147. package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
  148. package/dist/types/system-prompt.d.ts +2 -11
  149. package/dist/types/task/executor.d.ts +3 -1
  150. package/dist/types/thinking.d.ts +7 -0
  151. package/dist/types/tool-discovery/tool-index.d.ts +1 -50
  152. package/dist/types/tools/ask.d.ts +64 -2
  153. package/dist/types/tools/bash.d.ts +3 -0
  154. package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
  155. package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
  156. package/dist/types/tools/cron.d.ts +2 -0
  157. package/dist/types/tools/fetch.d.ts +1 -0
  158. package/dist/types/tools/index.d.ts +30 -15
  159. package/dist/types/tools/output-meta.d.ts +1 -0
  160. package/dist/types/tools/read.d.ts +5 -0
  161. package/dist/types/tools/search-tool-bm25.d.ts +3 -4
  162. package/dist/types/tools/subagent.d.ts +1 -0
  163. package/dist/types/utils/event-bus.d.ts +1 -1
  164. package/dist/types/utils/file-mentions.d.ts +3 -3
  165. package/dist/types/web/search/index.d.ts +3 -1
  166. package/package.json +21 -9
  167. package/scripts/build-sdk-package-smoke.ts +34 -1
  168. package/scripts/generate-hotkeys-docs.ts +74 -0
  169. package/scripts/generate-sdk-operation-inventory.ts +64 -20
  170. package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
  171. package/src/async/job-manager.ts +49 -6
  172. package/src/cli/config-cli.ts +75 -2
  173. package/src/cli/launch-disposition.ts +42 -0
  174. package/src/cli/notify-cli.ts +92 -26
  175. package/src/cli/session-picker.ts +20 -3
  176. package/src/cli/setup-cli.ts +1 -1
  177. package/src/cli.ts +1 -1
  178. package/src/commands/config.ts +1 -1
  179. package/src/commands/harness.ts +34 -106
  180. package/src/commands/launch.ts +6 -4
  181. package/src/commands/mcp-serve.ts +85 -8
  182. package/src/commands/mcp.ts +2 -2
  183. package/src/commands/notify.ts +8 -4
  184. package/src/commands/sdk.ts +61 -40
  185. package/src/commands/ultragoal.ts +4 -1
  186. package/src/config/atomic-yaml-patch.ts +80 -13
  187. package/src/config/file-lock.ts +105 -43
  188. package/src/config/keybindings.ts +64 -20
  189. package/src/config/model-auth.ts +9 -0
  190. package/src/config/model-bindings-applier.ts +139 -0
  191. package/src/config/model-discovery-manager.ts +224 -0
  192. package/src/config/model-equivalence.ts +66 -0
  193. package/src/config/model-registry.ts +169 -302
  194. package/src/config/model-resolver.ts +361 -369
  195. package/src/config/models-config-schema.ts +5 -4
  196. package/src/config/settings-schema.ts +214 -12
  197. package/src/config/settings.ts +458 -482
  198. package/src/coordinator-mcp/policy.ts +76 -11
  199. package/src/coordinator-mcp/question-gate-codec.ts +274 -0
  200. package/src/coordinator-mcp/question-state.ts +778 -0
  201. package/src/coordinator-mcp/server.ts +1702 -238
  202. package/src/debug/index.ts +1 -1
  203. package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
  204. package/src/defaults/gjc/skills/team/SKILL.md +16 -0
  205. package/src/discovery/helpers.ts +1 -50
  206. package/src/edit/index.ts +64 -0
  207. package/src/eval/py/env.ts +26 -0
  208. package/src/eval/py/kernel.ts +5 -3
  209. package/src/extensibility/extensions/loader.ts +9 -1
  210. package/src/extensibility/extensions/runner.ts +12 -3
  211. package/src/extensibility/extensions/types.ts +39 -1
  212. package/src/extensibility/gjc-plugins/installer.ts +16 -16
  213. package/src/extensibility/hooks/runner.ts +2 -2
  214. package/src/extensibility/runtime-skill-discovery.ts +33 -13
  215. package/src/extensibility/shared-events.ts +2 -0
  216. package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
  217. package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
  218. package/src/gjc-runtime/deep-interview-state.ts +317 -5
  219. package/src/gjc-runtime/goal-mode-request.ts +55 -8
  220. package/src/gjc-runtime/launch-tmux.ts +2 -5
  221. package/src/gjc-runtime/launch-worktree.ts +5 -5
  222. package/src/gjc-runtime/linux-proc.ts +71 -0
  223. package/src/gjc-runtime/ralplan-runtime.ts +74 -90
  224. package/src/gjc-runtime/session-resolution.ts +18 -3
  225. package/src/gjc-runtime/session-state-sidecar.ts +6 -107
  226. package/src/gjc-runtime/state-migrations.ts +1 -1
  227. package/src/gjc-runtime/state-runtime.ts +327 -249
  228. package/src/gjc-runtime/state-writer.ts +36 -40
  229. package/src/gjc-runtime/team-launch.ts +319 -0
  230. package/src/gjc-runtime/team-notify.ts +326 -0
  231. package/src/gjc-runtime/team-runtime.ts +1099 -1482
  232. package/src/gjc-runtime/team-store.ts +828 -0
  233. package/src/gjc-runtime/team-workers.ts +962 -0
  234. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
  235. package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
  236. package/src/gjc-runtime/tmux-sessions.ts +4 -21
  237. package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
  238. package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
  239. package/src/gjc-runtime/ultragoal-guard.ts +29 -5
  240. package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
  241. package/src/gjc-runtime/ultragoal-runtime.ts +84 -1311
  242. package/src/gjc-runtime/workflow-cli-common.ts +30 -0
  243. package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
  244. package/src/gjc-runtime/workflow-manifest.ts +18 -0
  245. package/src/goals/continuation-timeout-guard.ts +79 -0
  246. package/src/goals/runtime.ts +7 -5
  247. package/src/goals/state.ts +18 -0
  248. package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
  249. package/src/harness-control-plane/phase-rollup.ts +4 -7
  250. package/src/harness-control-plane/receipt-ingest.ts +5 -0
  251. package/src/harness-control-plane/receipt-spool.ts +51 -7
  252. package/src/harness-control-plane/session-lease.ts +12 -130
  253. package/src/hindsight/backend.ts +26 -27
  254. package/src/hindsight/state.ts +101 -32
  255. package/src/hooks/skill-state.ts +17 -11
  256. package/src/internal-urls/docs-index.generated.ts +21 -18
  257. package/src/lsp/client.ts +1 -1
  258. package/src/lsp/config.ts +145 -26
  259. package/src/lsp/index.ts +1 -1
  260. package/src/lsp/lspmux.ts +39 -10
  261. package/src/lsp/path-trust.ts +81 -0
  262. package/src/main.ts +127 -30
  263. package/src/memories/index.ts +1 -0
  264. package/src/memories/storage.ts +6 -2
  265. package/src/modes/action-registry.ts +165 -0
  266. package/src/modes/components/chrome.ts +40 -0
  267. package/src/modes/components/command-palette.ts +168 -0
  268. package/src/modes/components/custom-editor.ts +1 -1
  269. package/src/modes/components/custom-provider-wizard.ts +51 -14
  270. package/src/modes/components/index.ts +2 -1
  271. package/src/modes/components/pet-selector.ts +11 -17
  272. package/src/modes/components/plan-preview-overlay.ts +295 -0
  273. package/src/modes/components/queue-mode-selector.ts +10 -27
  274. package/src/modes/components/queue-pane.ts +79 -0
  275. package/src/modes/components/read-tool-group.ts +13 -0
  276. package/src/modes/components/session-observer-overlay.ts +207 -772
  277. package/src/modes/components/sessions-dashboard.ts +181 -0
  278. package/src/modes/components/settings-selector.ts +1 -1
  279. package/src/modes/components/show-images-selector.ts +10 -24
  280. package/src/modes/components/status-line/types.ts +1 -1
  281. package/src/modes/components/status-line.ts +1 -969
  282. package/src/modes/components/tasks-pane.ts +73 -0
  283. package/src/modes/components/theme-selector.ts +11 -31
  284. package/src/modes/components/tool-execution.ts +22 -0
  285. package/src/modes/components/tool-status-header.ts +1056 -0
  286. package/src/modes/components/transcript-viewer-overlay.ts +384 -0
  287. package/src/modes/controllers/btw-controller.ts +1 -0
  288. package/src/modes/controllers/event-controller.ts +3 -2
  289. package/src/modes/controllers/extension-ui-controller.ts +24 -1
  290. package/src/modes/controllers/goal-mode-controller.ts +474 -0
  291. package/src/modes/controllers/input-controller.ts +764 -229
  292. package/src/modes/controllers/mode-gate.ts +24 -0
  293. package/src/modes/controllers/plan-mode-controller.ts +517 -0
  294. package/src/modes/controllers/selector-controller.ts +225 -10
  295. package/src/modes/controllers/stt-controller.ts +125 -0
  296. package/src/modes/interactive-mode.ts +289 -1150
  297. package/src/modes/jobs-observer.ts +3 -0
  298. package/src/modes/prompt-action-autocomplete.ts +7 -0
  299. package/src/modes/runtime-init.ts +8 -0
  300. package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
  301. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +71 -16
  302. package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
  303. package/src/modes/tasks-aggregator.ts +199 -0
  304. package/src/modes/transcript-item-registry.ts +229 -0
  305. package/src/modes/types.ts +45 -18
  306. package/src/modes/utils/ui-helpers.ts +17 -9
  307. package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
  308. package/src/prompts/agent-fragments/restricted-bash.md +1 -0
  309. package/src/prompts/agents/architect.md +2 -8
  310. package/src/prompts/agents/critic.md +2 -8
  311. package/src/prompts/agents/executor.md +3 -0
  312. package/src/prompts/agents/planner.md +4 -12
  313. package/src/prompts/system/custom-system-prompt.md +1 -23
  314. package/src/prompts/system/plan-mode-approved.md +8 -0
  315. package/src/prompts/system/system-prompt.md +17 -96
  316. package/src/prompts/tools/bash.md +4 -4
  317. package/src/prompts/tools/browser.md +15 -52
  318. package/src/prompts/tools/find.md +2 -2
  319. package/src/prompts/tools/hashline.md +13 -55
  320. package/src/prompts/tools/read.md +3 -6
  321. package/src/prompts/tools/search-tool-bm25.md +0 -2
  322. package/src/prompts/tools/search.md +2 -4
  323. package/src/prompts/tools/skill-discovery.md +1 -2
  324. package/src/prompts/tools/task.md +1 -1
  325. package/src/runtime-mcp/manager.ts +1 -1
  326. package/src/sdk/broker/broker.ts +206 -78
  327. package/src/sdk/broker/discovery.ts +1 -1
  328. package/src/sdk/broker/ensure.ts +3 -1
  329. package/src/sdk/broker/lifecycle-codec.ts +11 -0
  330. package/src/sdk/broker/lifecycle-ledger.ts +371 -74
  331. package/src/sdk/broker/lifecycle.ts +1399 -142
  332. package/src/sdk/broker/process-incarnation.ts +5 -13
  333. package/src/sdk/broker/session-index.ts +145 -56
  334. package/src/sdk/broker/state-version.ts +21 -0
  335. package/src/sdk/broker/transport.ts +1 -1
  336. package/src/sdk/bus/chat-daemon-cli.ts +2 -0
  337. package/src/sdk/bus/chat-daemon-control.ts +8 -28
  338. package/src/sdk/bus/chat-effect-journal.ts +10 -2
  339. package/src/sdk/bus/config-commands.ts +5 -4
  340. package/src/sdk/bus/config.ts +98 -0
  341. package/src/sdk/bus/conversation-store.ts +5 -29
  342. package/src/sdk/bus/daemon-paths.ts +2 -0
  343. package/src/sdk/bus/html-format.ts +20 -3
  344. package/src/sdk/bus/index.ts +782 -94
  345. package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
  346. package/src/sdk/bus/natives-augment.d.ts +26 -1
  347. package/src/sdk/bus/notification-service.ts +168 -20
  348. package/src/sdk/bus/rate-limit-pool.ts +58 -14
  349. package/src/sdk/bus/recent-activity.ts +188 -74
  350. package/src/sdk/bus/rich-document.ts +258 -0
  351. package/src/sdk/bus/rich-render.ts +62 -70
  352. package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
  353. package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
  354. package/src/sdk/bus/telegram-daemon.ts +1389 -237
  355. package/src/sdk/bus/threaded-inbound.ts +8 -3
  356. package/src/sdk/bus/threaded-render.ts +57 -1
  357. package/src/sdk/bus/topic-registry.ts +120 -13
  358. package/src/sdk/host/control/dispatch.ts +14 -2
  359. package/src/sdk/host/control/operations.ts +6 -1
  360. package/src/sdk/host/host.ts +44 -2
  361. package/src/sdk/host/query/handlers.ts +20 -22
  362. package/src/sdk/host/query/revision-store.ts +80 -57
  363. package/src/sdk/index.ts +1 -0
  364. package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
  365. package/src/sdk/session-directory.ts +141 -0
  366. package/src/sdk/session.ts +462 -480
  367. package/src/session/agent-session.ts +1700 -583
  368. package/src/session/agent-storage.ts +18 -0
  369. package/src/session/cache-economics.ts +25 -8
  370. package/src/session/fallback-chain-controller.ts +53 -3
  371. package/src/session/internal/managed-session-scope.ts +2226 -0
  372. package/src/session/internal/managed-session-storage.ts +453 -0
  373. package/src/session/messages.ts +91 -2
  374. package/src/session/session-manager-internal.ts +33 -0
  375. package/src/session/session-manager.ts +1112 -333
  376. package/src/session/session-storage.ts +444 -39
  377. package/src/session/volatile-context-pruning.ts +78 -0
  378. package/src/setup/credential-auto-import.ts +2 -1
  379. package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
  380. package/src/setup/provider-onboarding.ts +36 -61
  381. package/src/setup/provider-presets.json +5 -0
  382. package/src/skill-state/active-state.ts +3 -13
  383. package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
  384. package/src/skill-state/workflow-state-contract.ts +6 -41
  385. package/src/slash-commands/builtin-registry.ts +46 -11
  386. package/src/system-prompt.ts +37 -44
  387. package/src/task/agents.ts +19 -1
  388. package/src/task/executor.ts +90 -6
  389. package/src/task/index.ts +36 -21
  390. package/src/thinking.ts +21 -6
  391. package/src/tool-discovery/tool-index.ts +2 -134
  392. package/src/tools/ask.ts +157 -21
  393. package/src/tools/ast-edit.ts +1 -1
  394. package/src/tools/bash.ts +38 -0
  395. package/src/tools/browser/dead-tab-recovery.ts +78 -0
  396. package/src/tools/browser/tab-supervisor.ts +282 -36
  397. package/src/tools/computer.ts +10 -3
  398. package/src/tools/cron.ts +30 -16
  399. package/src/tools/eval.ts +1 -2
  400. package/src/tools/fetch.ts +11 -4
  401. package/src/tools/index.ts +76 -24
  402. package/src/tools/output-meta.ts +19 -7
  403. package/src/tools/read.ts +219 -64
  404. package/src/tools/resource-gc.ts +2 -2
  405. package/src/tools/search-tool-bm25.ts +11 -74
  406. package/src/tools/subagent.ts +43 -2
  407. package/src/utils/event-bus.ts +9 -4
  408. package/src/utils/file-mentions.ts +4 -4
  409. package/src/web/search/index.ts +3 -3
  410. package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
  411. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
  412. package/src/discovery/plugin-dir-roots.ts +0 -28
  413. package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
@@ -9,6 +9,8 @@ const packageName = "@gajae-code/coding-agent";
9
9
  const aiPackageDir = path.resolve(packageDir, "../ai");
10
10
  const bridgeClientPackageDir = path.resolve(packageDir, "../bridge-client");
11
11
  const tuiPackageDir = path.resolve(packageDir, "../tui");
12
+ const nativesPackageDir = path.resolve(packageDir, "../natives");
13
+ const linuxX64PackageDir = path.resolve(packageDir, "../natives-linux-x64");
12
14
  const manifestsDir = path.join(packageDir, "test/manifests");
13
15
  const baselinePath = path.join(manifestsDir, "sdk-public-surface-v1.json");
14
16
  const generatedPath = path.join(manifestsDir, "sdk-public-surface.generated.json");
@@ -30,18 +32,35 @@ function assertExport(module: Record<string, unknown>, name: string, subpath: st
30
32
  async function runSmoke(): Promise<Surface> {
31
33
  const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "gjc-sdk-package-smoke-"));
32
34
  try {
35
+ const stagedLinuxX64Dir = path.join(tempDir, "natives-linux-x64");
36
+ await fs.cp(linuxX64PackageDir, stagedLinuxX64Dir, { recursive: true });
37
+ const stagedNativeDir = path.join(stagedLinuxX64Dir, "native");
38
+ await fs.mkdir(stagedNativeDir, { recursive: true });
39
+ for (const entry of await fs.readdir(path.join(nativesPackageDir, "native"))) {
40
+ if (entry.startsWith("pi_natives.linux-x64") && entry.endsWith(".node")) {
41
+ await fs.copyFile(path.join(nativesPackageDir, "native", entry), path.join(stagedNativeDir, entry));
42
+ }
43
+ }
33
44
  const aiTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], aiPackageDir);
34
45
  const bridgeClientTarball = run(
35
46
  ["bun", "pm", "pack", "--destination", tempDir, "--quiet"],
36
47
  bridgeClientPackageDir,
37
48
  );
38
49
  const tuiTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], tuiPackageDir);
50
+ const nativesTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], nativesPackageDir);
51
+ const linuxX64Tarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], stagedLinuxX64Dir);
39
52
  const codingAgentTarball = run(["bun", "pm", "pack", "--destination", tempDir, "--quiet"], packageDir);
40
53
  const aiTarballPath = path.isAbsolute(aiTarball) ? aiTarball : path.join(aiPackageDir, aiTarball);
41
54
  const bridgeClientTarballPath = path.isAbsolute(bridgeClientTarball)
42
55
  ? bridgeClientTarball
43
56
  : path.join(bridgeClientPackageDir, bridgeClientTarball);
44
57
  const tuiTarballPath = path.isAbsolute(tuiTarball) ? tuiTarball : path.join(tuiPackageDir, tuiTarball);
58
+ const nativesTarballPath = path.isAbsolute(nativesTarball)
59
+ ? nativesTarball
60
+ : path.join(nativesPackageDir, nativesTarball);
61
+ const linuxX64TarballPath = path.isAbsolute(linuxX64Tarball)
62
+ ? linuxX64Tarball
63
+ : path.join(stagedLinuxX64Dir, linuxX64Tarball);
45
64
  const codingAgentTarballPath = path.isAbsolute(codingAgentTarball)
46
65
  ? codingAgentTarball
47
66
  : path.join(packageDir, codingAgentTarball);
@@ -56,11 +75,15 @@ async function runSmoke(): Promise<Surface> {
56
75
  "@gajae-code/bridge-client": `file:${bridgeClientTarballPath}`,
57
76
  [packageName]: `file:${codingAgentTarballPath}`,
58
77
  "@gajae-code/tui": `file:${tuiTarballPath}`,
78
+ "@gajae-code/natives": `file:${nativesTarballPath}`,
79
+ "@gajae-code/natives-linux-x64": `file:${linuxX64TarballPath}`,
59
80
  },
60
81
  overrides: {
61
82
  "@gajae-code/ai": `file:${aiTarballPath}`,
62
83
  "@gajae-code/bridge-client": `file:${bridgeClientTarballPath}`,
63
84
  "@gajae-code/tui": `file:${tuiTarballPath}`,
85
+ "@gajae-code/natives": `file:${nativesTarballPath}`,
86
+ "@gajae-code/natives-linux-x64": `file:${linuxX64TarballPath}`,
64
87
  },
65
88
  },
66
89
  null,
@@ -70,10 +93,20 @@ async function runSmoke(): Promise<Surface> {
70
93
  // Install the matching packed workspace artifacts so the smoke test exercises the
71
94
  // release dependency boundary without falling back to an older registry package.
72
95
  run(["bun", "install", "--ignore-scripts"], tempDir);
96
+ const installedPackage = JSON.parse(
97
+ await fs.readFile(path.join(tempDir, "node_modules", packageName, "package.json"), "utf8"),
98
+ ) as { exports?: Record<string, unknown> };
99
+ if (installedPackage.exports?.["./session/internal/*"] !== null) {
100
+ throw new Error("packed package must explicitly block ./session/internal/*");
101
+ }
73
102
  const probePath = path.join(tempDir, "probe.ts");
74
103
  await fs.writeFile(
75
104
  probePath,
76
- `import * as root from ${JSON.stringify(packageName)};\nimport * as sdk from ${JSON.stringify(`${packageName}/sdk`)};\nimport * as bus from ${JSON.stringify(`${packageName}/sdk/bus`)};\nimport * as bridgeClient from "@gajae-code/bridge-client";\nconst required = [[root, "createAgentSession", "root"], [sdk, "createAgentSession", "sdk"], [bus, "createNotificationsExtension", "sdk/bus"], [sdk, "SdkClient", "sdk"], [bridgeClient, "SdkClient", "bridge-client"]] as const;\nfor (const [module, name, subpath] of required) if (!(name in module)) throw new Error(subpath + " missing " + name);\nif (sdk.SdkClient !== bridgeClient.SdkClient) throw new Error("SdkClient class identity differs between sdk and bridge-client");\nprocess.stdout.write(JSON.stringify({ root: Object.keys(root).sort(), sdk: Object.keys(sdk).sort() }));\n`,
105
+ `import * as fs from "node:fs/promises";\nimport * as path from "node:path";\nimport * as root from ${JSON.stringify(packageName)};\nimport * as sdk from ${JSON.stringify(`${packageName}/sdk`)};\nimport * as bus from ${JSON.stringify(`${packageName}/sdk/bus`)};\nconst required = [[root, "createAgentSession", "root"], [root, "SESSION_DIRECTORY_API_VERSION", "root"], [root, "resolveManagedSessionScope", "root"], [root, "listManagedSessionCandidates", "root"], [sdk, "createAgentSession", "sdk"], [bus, "createNotificationsExtension", "sdk/bus"], [sdk, "SdkClient", "sdk"], [sdk, "SESSION_DIRECTORY_API_VERSION", "sdk"], [sdk, "resolveManagedSessionScope", "sdk"], [sdk, "listManagedSessionCandidates", "sdk"]] as const;\nfor (const [module, name, subpath] of required) if (!(name in module)) throw new Error(subpath + " missing " + name);\nconst sandbox = path.join(process.cwd(), "managed-listing-smoke");\nconst cwd = path.join(sandbox, "workspace", "a-b", "c");\nconst agentDir = path.join(sandbox, "agent");\nconst sessionsRoot = path.join(agentDir, "sessions");\nawait fs.mkdir(cwd, { recursive: true });\nconst resolved = await sdk.resolveManagedSessionScope({ cwd, agentDir, sessionsRoot });\nif (resolved.kind !== "resolved") throw new Error("packed resolver failed: " + resolved.message);\nawait fs.mkdir(resolved.scope.directoryPath, { recursive: true, mode: 0o700 });\nawait fs.chmod(sessionsRoot, 0o700);\nawait fs.chmod(resolved.scope.directoryPath, 0o700);\nawait fs.writeFile(path.join(resolved.scope.directoryPath, ".gjc-managed-session-scope.v2.json"), JSON.stringify({ schemaVersion: 1, layoutVersion: 2, identityVersion: 1, platform: process.platform === "win32" ? "win32" : "posix", canonicalPath: resolved.scope.canonicalCwd, identityDigest: resolved.scope.directoryName.slice(3) }) + "\\n", { mode: 0o600 });\nconst transcriptPath = path.join(resolved.scope.directoryPath, "packed-session.jsonl");\nawait fs.writeFile(transcriptPath, JSON.stringify({ type: "session", id: "packed-session", cwd }) + "\\n", { mode: 0o600 });\nconst snapshot = async () => Promise.all((await fs.readdir(sandbox, { recursive: true })).sort().map(async name => { const pathname = path.join(sandbox, name); const stat = await fs.lstat(pathname); return [name, stat.mode, stat.size, stat.mtimeMs, stat.isFile() ? await fs.readFile(pathname, "utf8") : null]; }));\nconst before = JSON.stringify(await snapshot());\nconst listing = await sdk.listManagedSessionCandidates({ scope: resolved.scope });\nif (listing.kind !== "complete" || listing.owned.length !== 1 || listing.owned[0]?.sessionId !== "packed-session") throw new Error("packed readonly listing failed: " + JSON.stringify(listing));\nconst after = JSON.stringify(await snapshot());\nif (after !== before) throw new Error("packed readonly listing mutated the filesystem");\nconst privateSubpath = ${JSON.stringify(`${packageName}/session/internal/managed-session-scope`)};\ntry { await import(privateSubpath); throw new Error("private managed-session scope subpath resolved"); } catch (error) {\n\tif (error instanceof Error && error.message === "private managed-session scope subpath resolved") throw error;\n\tconst message = String(error);\n\tconst exportsRejected = /Package subpath .* is not defined by "exports"/.test(message);\n\tconst bunRejected = message.startsWith("ResolveMessage: Cannot find module '" + privateSubpath + "' from '") && message.endsWith("/probe.ts'");\n\tif (!exportsRejected && !bunRejected) throw new Error("private managed-session scope failed for an unexpected reason: " + message);\n}\nprocess.stdout.write(JSON.stringify({ root: Object.keys(root).sort(), sdk: Object.keys(sdk).sort() }));\n`,
106
+ );
107
+ await fs.appendFile(
108
+ probePath,
109
+ `\nconst rootBefore = JSON.stringify(await snapshot());\nconst rootListing = await root.listManagedSessionCandidates({ scope: resolved.scope });\nif (rootListing.kind !== "complete" || rootListing.owned.length !== listing.owned.length || rootListing.owned[0]?.sessionId !== listing.owned[0]?.sessionId || rootListing.owned[0]?.path !== listing.owned[0]?.path) throw new Error("packed root readonly listing diverged from SDK listing");\nconst rootAfter = JSON.stringify(await snapshot());\nif (rootAfter !== rootBefore) throw new Error("packed root readonly listing mutated the filesystem");\nconst bridgeClient = await import("@gajae-code/bridge-client");\nif (sdk.SdkClient !== bridgeClient.SdkClient) throw new Error("SdkClient class identity differs between sdk and bridge-client");\n`,
77
110
  );
78
111
  const surface = JSON.parse(run(["bun", "run", probePath], tempDir)) as Surface;
79
112
  assertExport(Object.fromEntries(surface.root.map(name => [name, true])), "createAgentSession", "root");
@@ -0,0 +1,74 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import * as path from "node:path";
3
+ import {
4
+ defaultClipboardPasteImageKeysForPlatform,
5
+ defaultMessageQueueKeysForPlatform,
6
+ KEYBINDINGS,
7
+ } from "../src/config/keybindings";
8
+
9
+ import { APP_ACTION_METADATA } from "../src/modes/action-registry";
10
+
11
+ const DOC_PATH = path.resolve(import.meta.dir, "../../../docs/keybindings.md");
12
+ const SECTION_START = "### Application context (`app.*`)";
13
+ const SECTION_END = "### Global engine context (`tui.global.*`)";
14
+
15
+ const DOCUMENTATION_PLATFORMS = ["darwin", "win32", "linux"] as const;
16
+
17
+ function defaultKeys(
18
+ value: (typeof KEYBINDINGS)[keyof typeof KEYBINDINGS],
19
+ bindingId: keyof typeof KEYBINDINGS,
20
+ ): string {
21
+ const defaultsByPlatform = DOCUMENTATION_PLATFORMS.map(platform => {
22
+ switch (bindingId) {
23
+ case "app.message.queue":
24
+ return defaultMessageQueueKeysForPlatform(platform);
25
+ case "app.clipboard.pasteImage":
26
+ return defaultClipboardPasteImageKeysForPlatform(platform);
27
+ default: {
28
+ const keys = value.defaultKeys;
29
+ return (Array.isArray(keys) ? keys : [keys]).join(", ") || "_(none)_";
30
+ }
31
+ }
32
+ });
33
+ const groups = new Map<string, string[]>();
34
+ for (const [index, keys] of defaultsByPlatform.entries()) {
35
+ const platform = DOCUMENTATION_PLATFORMS[index]!;
36
+ groups.set(keys, [...(groups.get(keys) ?? []), platform]);
37
+ }
38
+ return groups.size === 1
39
+ ? defaultsByPlatform[0]!
40
+ : [...groups].map(([keys, platforms]) => `${keys} (${platforms.join("/")})`).join(" / ");
41
+ }
42
+
43
+ /** Canonical application-action table shared by docs and drift tests. */
44
+ export function generateHotkeysDocsTable(): string {
45
+ return [
46
+ "| Action ID | Default | Domains |",
47
+ "| --- | --- | --- |",
48
+ ...APP_ACTION_METADATA.map(action => {
49
+ const binding = KEYBINDINGS[action.bindingId ?? action.id];
50
+ return `| \`${action.id}\` | ${defaultKeys(binding, action.bindingId ?? action.id)} | ${action.domains.join(", ")} |`;
51
+ }),
52
+ ].join("\n");
53
+ }
54
+
55
+ export function generateKeybindingsDocument(source = readFileSync(DOC_PATH, "utf8")): string {
56
+ const start = source.indexOf(SECTION_START);
57
+ const end = source.indexOf(SECTION_END);
58
+ if (start < 0 || end < 0 || end <= start) throw new Error("Application keybinding section not found");
59
+ return `${source.slice(0, start)}${SECTION_START}\n\n${generateHotkeysDocsTable()}\n\n${source.slice(end)}`;
60
+ }
61
+
62
+ if (import.meta.main) {
63
+ const expected = generateKeybindingsDocument();
64
+ if (process.argv.includes("--check")) {
65
+ if (readFileSync(DOC_PATH, "utf8") !== expected) {
66
+ console.error(
67
+ `${path.relative(process.cwd(), DOC_PATH)} is out of date; run bun scripts/generate-hotkeys-docs.ts`,
68
+ );
69
+ process.exitCode = 1;
70
+ }
71
+ } else {
72
+ writeFileSync(DOC_PATH, expected);
73
+ }
74
+ }
@@ -32,6 +32,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
32
32
  "slash_command:notify":
33
33
  "interactive diagnostics command; session on/off delegate to the notifications extension, not an SDK ingress seam",
34
34
  "slash_command:pet": "visual/local-only command, not a user-facing SDK control seam",
35
+ "slash_command:transcript": "visual/local-only transcript viewer, not a user-facing SDK control seam",
36
+ "slash_command:sessions": "visual/local-only sessions dashboard, not a user-facing SDK control seam",
35
37
  "agent_session:constructor": "internal accessor/plumbing, not a user-facing control seam",
36
38
  "agent_session:nextToolChoice": "internal accessor/plumbing, not a user-facing control seam",
37
39
  "agent_session:setForcedToolChoice": "internal accessor/plumbing, not a user-facing control seam",
@@ -50,6 +52,9 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
50
52
  "agent_session:estimateMidRunContextTokensForTests": "test-only estimator seam, not a user-facing SDK control seam",
51
53
  "agent_session:activeMidRunBarrierCountForTests": "read-only test seam, not a user-facing SDK control seam",
52
54
  "agent_session:activeMidRunMaintenanceCountForTests": "read-only test seam, not a user-facing SDK control seam",
55
+ "agent_session:getPendingNextTurnMessagesForTests": "read-only test seam, not a user-facing SDK control seam",
56
+ "agent_session:setCancelAndSubmitAbortOutcomeProviderForTests":
57
+ "test-only cancellation seam, not a user-facing SDK control seam",
53
58
  "agent_session:getAgentId": "internal accessor/plumbing, not a user-facing control seam",
54
59
  "agent_session:emitNotice": "internal accessor/plumbing, not a user-facing control seam",
55
60
  "agent_session:subscribe": "internal accessor/plumbing, not a user-facing control seam",
@@ -57,6 +62,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
57
62
  "agent_session:closeWriterStrict": "internal ACP lifecycle teardown plumbing, not a user-facing control seam",
58
63
  "agent_session:disposeChildSubprocesses": "internal accessor/plumbing, not a user-facing control seam",
59
64
  "agent_session:waitForIdle": "internal accessor/plumbing, not a user-facing control seam",
65
+ "agent_session:awaitPendingContextTransformations":
66
+ "internal context-transformation lifecycle barrier, not a user-facing SDK control seam",
60
67
  "agent_session:drainAsyncJobDeliveriesForAcp": "internal accessor/plumbing, not a user-facing control seam",
61
68
  "agent_session:getAsyncDeliveryStateForAcp":
62
69
  "internal ACP lifecycle quiescence plumbing, not a user-facing control seam",
@@ -66,10 +73,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
66
73
  "agent_session:hasForegroundBashBackgroundRequestHandler":
67
74
  "internal accessor/plumbing, not a user-facing control seam",
68
75
  "agent_session:requestForegroundBashBackground": "internal accessor/plumbing, not a user-facing control seam",
69
- "agent_session:isMCPDiscoveryEnabled": "internal accessor/plumbing, not a user-facing control seam",
70
- "agent_session:getDiscoverableMCPSearchIndex": "internal accessor/plumbing, not a user-facing control seam",
71
76
  "agent_session:getSelectedMCPToolNames": "internal accessor/plumbing, not a user-facing control seam",
72
- "agent_session:activateDiscoveredMCPTools": "internal accessor/plumbing, not a user-facing control seam",
73
77
  "agent_session:isToolDiscoveryEnabled": "internal accessor/plumbing, not a user-facing control seam",
74
78
  "agent_session:getDiscoverableToolSearchIndex": "internal accessor/plumbing, not a user-facing control seam",
75
79
  "agent_session:getSelectedDiscoveredToolNames": "internal accessor/plumbing, not a user-facing control seam",
@@ -85,6 +89,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
85
89
  "agent_session:setPlanModeState": "internal accessor/plumbing, not a user-facing control seam",
86
90
  "agent_session:getGoalModeState": "internal accessor/plumbing, not a user-facing control seam",
87
91
  "agent_session:setGoalModeState": "internal accessor/plumbing, not a user-facing control seam",
92
+ "agent_session:setSdkPlanModeHandler": "internal host lifecycle plumbing for mode.plan.set",
88
93
  "agent_session:getWorkflowGateEmitter": "internal accessor/plumbing, not a user-facing control seam",
89
94
  "agent_session:getAskAnswerSource": "internal accessor/plumbing, not a user-facing control seam",
90
95
  "agent_session:setWorkflowGateEmitter": "internal accessor/plumbing, not a user-facing control seam",
@@ -105,6 +110,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
105
110
  "agent_session:purgeQueuedCustomMessages": "internal accessor/plumbing, not a user-facing control seam",
106
111
  "agent_session:clearQueue": "internal accessor/plumbing, not a user-facing control seam",
107
112
  "agent_session:popLastQueuedMessage": "internal accessor/plumbing, not a user-facing control seam",
113
+ "agent_session:cancelAndSubmit": "interactive queue transaction plumbing, not an independent SDK control seam",
108
114
  "agent_session:applyCompactionPostAppendForTests": "internal accessor/plumbing, not a user-facing control seam",
109
115
  "agent_session:continuePersistedHistory": "internal startup lifecycle plumbing, not a user-facing control seam",
110
116
  "agent_session:setActiveModelProfile": "internal accessor/plumbing, not a user-facing control seam",
@@ -126,6 +132,7 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
126
132
  "agent_session:fetchUsageReportsForControl":
127
133
  "internal Telegram control wrapper over the reviewed usage.get seam, not an independent public SDK operation",
128
134
  "agent_session:cycleRoleModels": "internal accessor/plumbing, not a user-facing control seam",
135
+ "agent_session:getRoleModelCycleCandidateCount": "internal role-model display accessor, not a user-facing SDK seam",
129
136
  "agent_session:isFastModeEnabled": "internal accessor/plumbing, not a user-facing control seam",
130
137
  "agent_session:isFastForProvider": "internal accessor/plumbing, not a user-facing control seam",
131
138
  "agent_session:isFastForSubagentProvider": "internal accessor/plumbing, not a user-facing control seam",
@@ -221,7 +228,6 @@ const SEAM_TO_SDK: Readonly<Record<string, string>> = {
221
228
  "agent_session:setTodoPhases": "todo.replace",
222
229
  "agent_session:getQueuedMessageEntries": "queue.messages.list",
223
230
  "agent_session:getAllToolNames": "tools.list",
224
- "agent_session:getDiscoverableMCPTools": "tools.list",
225
231
  "agent_session:getDiscoverableTools": "tools.list",
226
232
  "agent_session:sendUserMessage": "turn.steer",
227
233
  "agent_session:reload": "runtime.reload",
@@ -270,17 +276,30 @@ export interface SourceSeam {
270
276
  sourceFile: string;
271
277
  sourceKind: SourceKind;
272
278
  }
273
- interface InventoryRecord {
279
+ interface IncludedInventoryRecord {
274
280
  sourceId: string;
275
281
  sourceFile: string;
276
282
  sourceKind: SourceKind;
277
- decision: "include" | "exclude";
278
- rationale?: string;
279
- sdkId?: string;
283
+ decision: "include";
284
+ sdkId: string;
280
285
  adapterMappings: Operation["adapterDispositions"];
281
286
  testIds: string[];
282
287
  }
283
288
 
289
+ interface ExcludedInventoryRecord {
290
+ sourceId: string;
291
+ sourceFile: string;
292
+ sourceKind: SourceKind;
293
+ decision: "exclude";
294
+ rationale: string;
295
+ exclusionMetadata: {
296
+ adapterMappings: "not_applicable";
297
+ testIds: "not_applicable";
298
+ };
299
+ }
300
+
301
+ type InventoryRecord = IncludedInventoryRecord | ExcludedInventoryRecord;
302
+
284
303
  function repoPath(file: string): string {
285
304
  return path.relative(repoRoot, file).split(path.sep).join("/");
286
305
  }
@@ -291,7 +310,10 @@ function collectCaseSeams(source: string, prefix: string): string[] {
291
310
  }
292
311
 
293
312
  export function scanSlashCommands(sourceText: string): string[] {
294
- const builtinRegistry = sourceText.slice(sourceText.indexOf("const BUILTIN_SLASH_COMMAND_REGISTRY"));
313
+ const anchor = "const BUILTIN_SLASH_COMMAND_REGISTRY";
314
+ const anchorIndex = sourceText.indexOf(anchor);
315
+ if (anchorIndex === -1) throw new Error(`SDK operation inventory scanner: required anchor ${anchor} was not found.`);
316
+ const builtinRegistry = sourceText.slice(anchorIndex);
295
317
  return [...builtinRegistry.matchAll(/^\t\tname:\s*["']([^"']+)["']/gm)].map(match => `slash_command:${match[1]}`);
296
318
  }
297
319
 
@@ -664,14 +686,17 @@ export function scanAgentSessionMethods(sourceText: string): string[] {
664
686
  for (let bodyIndex = index + 2; bodyIndex < tokens.length; bodyIndex++) {
665
687
  if (tokens[bodyIndex]!.text === "<") angleDepth++;
666
688
  else if (tokens[bodyIndex]!.text === ">" && angleDepth > 0) angleDepth--;
689
+ else if (tokens[bodyIndex]!.text === ";" && angleDepth === 0) break;
667
690
  else if (tokens[bodyIndex]!.text === "{" && angleDepth === 0) {
668
691
  bodyStart = bodyIndex;
669
692
  break;
670
693
  }
671
694
  }
672
- if (bodyStart === undefined) return [];
695
+ if (bodyStart === undefined)
696
+ throw new Error("SDK operation inventory scanner: AgentSession class is missing its opening body delimiter.");
673
697
  const bodyEnd = matchingToken(tokens, bodyStart, "{", "}");
674
- if (bodyEnd === undefined) return [];
698
+ if (bodyEnd === undefined)
699
+ throw new Error("SDK operation inventory scanner: AgentSession class body is unbalanced.");
675
700
 
676
701
  const methods: string[] = [];
677
702
  for (let memberStart = bodyStart + 1; memberStart < bodyEnd; ) {
@@ -685,7 +710,7 @@ export function scanAgentSessionMethods(sourceText: string): string[] {
685
710
  }
686
711
  return methods;
687
712
  }
688
- return [];
713
+ throw new Error("SDK operation inventory scanner: required AgentSession class declaration was not found.");
689
714
  }
690
715
 
691
716
  export function scanAcpMethods(sourceText: string): string[] {
@@ -776,14 +801,24 @@ function generatedRecords(seams: Awaited<ReturnType<typeof scanSeams>>): Invento
776
801
  const sdkId = SEAM_TO_SDK[seam.sourceId];
777
802
  const rationale = lockedExclusion(seam.sourceId);
778
803
  if (!sdkId && !rationale) continue;
779
- const operation = sdkId ? OPERATIONS.find(candidate => candidate.sdkId === sdkId) : undefined;
780
- if (sdkId && !operation) throw new Error(`SEAM_TO_SDK maps ${seam.sourceId} to unknown SDK ID: ${sdkId}`);
804
+ if (!sdkId) {
805
+ if (!rationale) continue;
806
+ records.push({
807
+ ...seam,
808
+ decision: "exclude",
809
+ rationale,
810
+ exclusionMetadata: { adapterMappings: "not_applicable", testIds: "not_applicable" },
811
+ });
812
+ continue;
813
+ }
814
+ const operation = OPERATIONS.find(candidate => candidate.sdkId === sdkId);
815
+ if (!operation) throw new Error(`SEAM_TO_SDK maps ${seam.sourceId} to unknown SDK ID: ${sdkId}`);
781
816
  records.push({
782
817
  ...seam,
783
- decision: (sdkId ? "include" : "exclude") as "include" | "exclude",
784
- ...(sdkId ? { sdkId } : { rationale }),
785
- adapterMappings: operation?.adapterDispositions ?? OPERATIONS[0]!.adapterDispositions,
786
- testIds: operation?.testIds ?? ["packages/coding-agent/test/sdk-operation-inventory.test.ts"],
818
+ decision: "include",
819
+ sdkId,
820
+ adapterMappings: operation.adapterDispositions,
821
+ testIds: operation.testIds,
787
822
  });
788
823
  }
789
824
  return records;
@@ -804,8 +839,17 @@ function validateRegistry(records: InventoryRecord[]): string[] {
804
839
  if (operation.testIds.length === 0) errors.push(`${operation.id} is missing test IDs.`);
805
840
  }
806
841
  for (const record of records) {
807
- if (record.decision === "exclude" && !record.rationale)
808
- errors.push(`${record.sourceId} exclusion lacks a locked rationale.`);
842
+ if (record.decision === "exclude") {
843
+ if (!record.rationale) errors.push(`${record.sourceId} exclusion lacks a locked rationale.`);
844
+ if (
845
+ record.exclusionMetadata.adapterMappings !== "not_applicable" ||
846
+ record.exclusionMetadata.testIds !== "not_applicable"
847
+ )
848
+ errors.push(
849
+ `${record.sourceId} exclusion metadata must mark adapter mappings and test IDs as not applicable.`,
850
+ );
851
+ continue;
852
+ }
809
853
  if (ADAPTERS.some(adapter => !record.adapterMappings[adapter]))
810
854
  errors.push(`${record.sourceId} is missing adapter mappings.`);
811
855
  if (record.testIds.length === 0) errors.push(`${record.sourceId} is missing test IDs.`);
@@ -981,6 +981,7 @@ function isSource(file: string): boolean {
981
981
  }
982
982
 
983
983
  const teamRuntimeTmuxPath = "packages/coding-agent/src/gjc-runtime/team-runtime.ts";
984
+ const teamWorkersTmuxPath = "packages/coding-agent/src/gjc-runtime/team-workers.ts";
984
985
 
985
986
  const coordinatorMcpRoot = "packages/coding-agent/src/coordinator-mcp/server.ts";
986
987
  function isPublishedGjcSessionShellHelper(file: string): boolean {
@@ -1427,6 +1428,16 @@ function exactTeamRuntimeSendKeysRanges(contents: string): ShellRange[] {
1427
1428
  /Bun\.spawnSync\(\s*\[\s*config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-l["']\s*,\s*["']-t["']\s*,\s*paneId\s*,\s*workerCommand\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
1428
1429
  ),
1429
1430
  ];
1431
+ const continuationPromptMatches = [
1432
+ ...contents.matchAll(
1433
+ /(?:const\s+GJC_TEAM_CONTINUATION_PROMPT\s*=\s*["']Continue only your current claimed GJC team task\. Re-read current GJC team state; do not replay prior output; report status\.["']\s*;|import\s*\{[\s\S]{0,1000}?\bGJC_TEAM_CONTINUATION_PROMPT\b[\s\S]{0,1000}?\}\s*from\s*["']\.\/team-workers["']\s*;)/g,
1434
+ ),
1435
+ ];
1436
+ const continuationMatches = [
1437
+ ...contents.matchAll(
1438
+ /const\s+args\s*=\s*Object\.freeze\(\s*\[\s*["']send-keys["']\s*,\s*["']-l["']\s*,\s*["']-t["']\s*,\s*worker\.pane_id\s*,\s*GJC_TEAM_CONTINUATION_PROMPT\s*,\s*["'];["']\s*,\s*["']send-keys["']\s*,\s*["']-t["']\s*,\s*worker\.pane_id\s*,\s*["']Enter["']\s*,?\s*\]\s*\)\s*;\s*const\s+dispatch\s*=\s*gjcTeamRuntimeTestSeams\?\.continuationTmuxDispatch\s*\?\s*gjcTeamRuntimeTestSeams\.continuationTmuxDispatch\(config\.tmux_command\s*,\s*args\)\s*:\s*Bun\.spawnSync\(\[config\.tmux_command\s*,\s*\.\.\.args\]\s*,\s*\{\s*stdout\s*:\s*["']ignore["']\s*,\s*stderr\s*:\s*["']ignore["']\s*,\s*timeout\s*:\s*GJC_TEAM_CONTINUATION_DISPATCH_TIMEOUT_MS\s*,?\s*\}\s*\)\s*;/g,
1439
+ ),
1440
+ ];
1430
1441
  const enterMatches = [
1431
1442
  ...contents.matchAll(
1432
1443
  /const\s+sendKeys\s*=\s*Bun\.spawnSync\(\s*\[\s*config\.tmux_command\s*,\s*["']send-keys["']\s*,\s*["']-t["']\s*,\s*paneId\s*,\s*["']Enter["']\s*\]\s*,\s*\{[\s\S]{0,200}?stdout\s*:\s*["']ignore["'][\s\S]{0,200}?stderr\s*:\s*["']ignore["'][\s\S]{0,100}?\}\s*\)\s*;/g,
@@ -1449,6 +1460,8 @@ function exactTeamRuntimeSendKeysRanges(contents: string): ShellRange[] {
1449
1460
  guardMatches.length !== 1 ||
1450
1461
  payloadMatches.length !== 1 ||
1451
1462
  enterMatches.length !== 1 ||
1463
+ continuationPromptMatches.length !== 1 ||
1464
+ continuationMatches.length !== 1 ||
1452
1465
  fallbackPredicateMatches.length !== 1 ||
1453
1466
  useFallbackMatches.length !== 1 ||
1454
1467
  splitWorkerCommandMatches.length !== 1
@@ -1468,18 +1481,43 @@ function exactTeamRuntimeSendKeysRanges(contents: string): ShellRange[] {
1468
1481
  const guard = guardMatches[0];
1469
1482
  const openingBrace = (guard.index ?? 0) + guard[0].lastIndexOf("{");
1470
1483
  const range = braceBlockRange(contents, openingBrace);
1471
- if (!range) return [];
1484
+ const continuationFunction =
1485
+ /async\s+function\s+continueStalledGjcTeamWorkers\s*\([^)]*\)\s*:\s*Promise<void>\s*\{/.exec(contents);
1486
+ const monitorFence = /await\s+withGjcTeamTaskMutation\([\s\S]{0,500}?async\s+capability\s*=>\s*\{/.exec(contents);
1487
+ if (!range || !continuationFunction || !monitorFence) return [];
1488
+ const continuationOpeningBrace = (continuationFunction.index ?? 0) + continuationFunction[0].lastIndexOf("{");
1489
+ const continuationRange = braceBlockRange(contents, continuationOpeningBrace);
1490
+ const monitorOpeningBrace = (monitorFence.index ?? 0) + monitorFence[0].lastIndexOf("{");
1491
+ const monitorRange = braceBlockRange(contents, monitorOpeningBrace);
1492
+ if (!continuationRange || !monitorRange) return [];
1493
+ const monitorBody = contents.slice(monitorRange.start, monitorRange.end);
1494
+ const continuationCall = /await\s+continueStalledGjcTeamWorkers\s*\(/.exec(monitorBody);
1495
+ const reconciliationCall = /await\s+reconcileGjcTeamStaleClaimsUnlocked\s*\(/.exec(monitorBody);
1496
+ const continuationStart = continuationMatches[0].index ?? 0;
1497
+ const finalValidationStart = contents.lastIndexOf("const revalidationReason =", continuationStart);
1498
+ const skippedBranch = finalValidationStart === -1 ? "" : contents.slice(finalValidationStart, continuationStart);
1472
1499
  if (
1473
1500
  payloadStart < range.start ||
1474
1501
  payloadStart >= range.end ||
1475
1502
  enterStart < range.start ||
1476
1503
  enterStart >= range.end ||
1477
- contents.indexOf("void sendKeys.exitCode;", enterStart) >= range.end
1504
+ contents.indexOf("void sendKeys.exitCode;", enterStart) >= range.end ||
1505
+ continuationStart < continuationRange.start ||
1506
+ continuationStart >= continuationRange.end ||
1507
+ finalValidationStart < continuationRange.start ||
1508
+ !continuationCall ||
1509
+ !reconciliationCall ||
1510
+ (continuationCall.index ?? 0) >= (reconciliationCall.index ?? 0) ||
1511
+ !/if\s*\(\s*revalidationReason\s*\)[\s\S]*?return\s*;/.test(skippedBranch)
1478
1512
  )
1479
1513
  return [];
1480
1514
  return [
1481
1515
  { start: payloadStart, end: payloadStart + payloadMatches[0][0].length },
1482
1516
  { start: enterStart, end: enterStart + enterMatches[0][0].length },
1517
+ {
1518
+ start: continuationMatches[0].index ?? 0,
1519
+ end: (continuationMatches[0].index ?? 0) + continuationMatches[0][0].length,
1520
+ },
1483
1521
  ];
1484
1522
  }
1485
1523
 
@@ -1504,6 +1542,7 @@ function isTypeOnlyTmuxPrimitiveOccurrence(contents: string, occurrence: TmuxPri
1504
1542
  }
1505
1543
 
1506
1544
  function tmuxMachineBusViolations(file: string, contents: string): string[] {
1545
+ if (isGeneratedDocumentationIndex(file)) return [];
1507
1546
  const allowedTeamFallbackRanges = file === teamRuntimeTmuxPath ? exactTeamRuntimeSendKeysRanges(contents) : [];
1508
1547
  const violations: string[] = [];
1509
1548
  for (const occurrence of tmuxPrimitiveOccurrences(contents)) {
@@ -1890,6 +1929,15 @@ async function scan(): Promise<string[]> {
1890
1929
  } else {
1891
1930
  violations.push(...tmuxMachineBusViolations(file, contents));
1892
1931
  }
1932
+ if (
1933
+ file === teamWorkersTmuxPath &&
1934
+ !/^export const GJC_TEAM_CONTINUATION_PROMPT =\n\t"Continue only your current claimed GJC team task\. Re-read current GJC team state; do not replay prior output; report status\.";$/m.test(
1935
+ contents,
1936
+ )
1937
+ )
1938
+ violations.push(
1939
+ `${file}: stalled-worker continuation prompt must remain the exact source-controlled literal`,
1940
+ );
1893
1941
  }
1894
1942
  if (file === coordinatorMcpRoot) {
1895
1943
  for (const pattern of coordinatorDirectAuthorityPatterns) {
@@ -3067,6 +3115,9 @@ fi
3067
3115
  "tmux send-keys content injection is outside sanctioned process lifecycle",
3068
3116
  );
3069
3117
  const canonicalTeamRuntimeSendKeysFixture = `
3118
+ async function continueStalledGjcTeamWorkers(): Promise<void> {
3119
+ const revalidationReason = null;
3120
+ if (revalidationReason) return;
3070
3121
  function shouldDispatchWorkerWithSendKeys(tmuxCommand: string, platform: NodeJS.Platform = process.platform): boolean {
3071
3122
  return platform === "win32" || path.basename(tmuxCommand).toLowerCase() === "psmux";
3072
3123
  }
@@ -3083,11 +3134,100 @@ if (useSendKeysFallback) {
3083
3134
  });
3084
3135
  void sendKeys.exitCode;
3085
3136
  }
3137
+ const GJC_TEAM_CONTINUATION_PROMPT = "Continue only your current claimed GJC team task. Re-read current GJC team state; do not replay prior output; report status.";
3138
+ const GJC_TEAM_CONTINUATION_DISPATCH_TIMEOUT_MS = 5_000;
3139
+ const args = Object.freeze([
3140
+ "send-keys",
3141
+ "-l",
3142
+ "-t",
3143
+ worker.pane_id,
3144
+ GJC_TEAM_CONTINUATION_PROMPT,
3145
+ ";",
3146
+ "send-keys",
3147
+ "-t",
3148
+ worker.pane_id,
3149
+ "Enter",
3150
+ ]);
3151
+
3152
+ const dispatch = gjcTeamRuntimeTestSeams?.continuationTmuxDispatch
3153
+ ? gjcTeamRuntimeTestSeams.continuationTmuxDispatch(config.tmux_command, args)
3154
+ : Bun.spawnSync([config.tmux_command, ...args], {
3155
+ stdout: "ignore",
3156
+ stderr: "ignore",
3157
+ timeout: GJC_TEAM_CONTINUATION_DISPATCH_TIMEOUT_MS,
3158
+ });
3159
+ }
3160
+ async function monitorGjcTeam(): Promise<void> {
3161
+ await withGjcTeamTaskMutation(taskStore(dir), async capability => {
3162
+ await continueStalledGjcTeamWorkers();
3163
+ await reconcileGjcTeamStaleClaimsUnlocked(workerOrchestrationRuntime, teamName, dir, config, env, capability);
3164
+ });
3165
+ }
3086
3166
  `;
3087
3167
  await runSelfTestFixture(
3088
3168
  { "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture },
3089
3169
  0,
3090
3170
  );
3171
+ await runSelfTestFixture(
3172
+ {
3173
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3174
+ "async function continueStalledGjcTeamWorkers(): Promise<void>",
3175
+ "async function relocatedContinuation(): Promise<void>",
3176
+ ),
3177
+ },
3178
+ 1,
3179
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3180
+ );
3181
+ await runSelfTestFixture(
3182
+ {
3183
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3184
+ "if (revalidationReason) return;",
3185
+ "if (revalidationReason) {}",
3186
+ ),
3187
+ },
3188
+ 1,
3189
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3190
+ );
3191
+ await runSelfTestFixture(
3192
+ {
3193
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3194
+ "await continueStalledGjcTeamWorkers();",
3195
+ "",
3196
+ ),
3197
+ },
3198
+ 1,
3199
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3200
+ );
3201
+ await runSelfTestFixture(
3202
+ {
3203
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3204
+ "await continueStalledGjcTeamWorkers();\n\t\tawait reconcileGjcTeamStaleClaimsUnlocked(workerOrchestrationRuntime, teamName, dir, config, env, capability);",
3205
+ "await reconcileGjcTeamStaleClaimsUnlocked(workerOrchestrationRuntime, teamName, dir, config, env, capability);\n\t\tawait continueStalledGjcTeamWorkers();",
3206
+ ),
3207
+ },
3208
+ 1,
3209
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3210
+ );
3211
+ await runSelfTestFixture(
3212
+ {
3213
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3214
+ "const dispatch =",
3215
+ 'args.push("forged");\nconst dispatch =',
3216
+ ),
3217
+ },
3218
+ 1,
3219
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3220
+ );
3221
+ await runSelfTestFixture(
3222
+ {
3223
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3224
+ "report status.",
3225
+ "report injected status.",
3226
+ ),
3227
+ },
3228
+ 1,
3229
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3230
+ );
3091
3231
  await runSelfTestFixture(
3092
3232
  {
3093
3233
  "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
@@ -3115,6 +3255,46 @@ if (useSendKeysFallback) {
3115
3255
  1,
3116
3256
  "tmux send-keys content injection is outside sanctioned process lifecycle",
3117
3257
  );
3258
+ await runSelfTestFixture(
3259
+ {
3260
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replaceAll(
3261
+ "worker.pane_id",
3262
+ '"%99"',
3263
+ ),
3264
+ },
3265
+ 1,
3266
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3267
+ );
3268
+ await runSelfTestFixture(
3269
+ {
3270
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3271
+ 'GJC_TEAM_CONTINUATION_PROMPT,\n\t";",',
3272
+ "`$" + "{GJC_TEAM_CONTINUATION_PROMPT}" + '`,\n\t";",',
3273
+ ),
3274
+ },
3275
+ 1,
3276
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3277
+ );
3278
+ await runSelfTestFixture(
3279
+ {
3280
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3281
+ '"send-keys",\n\t"-l",\n\t"-t",\n\tworker.pane_id,\n\tGJC_TEAM_CONTINUATION_PROMPT,\n\t";",\n\t"send-keys",\n\t"-t",\n\tworker.pane_id,\n\t"Enter",',
3282
+ '"send-keys", "-t", worker.pane_id, "Enter", ";", "send-keys", "-l", "-t", worker.pane_id, GJC_TEAM_CONTINUATION_PROMPT,',
3283
+ ),
3284
+ },
3285
+ 1,
3286
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3287
+ );
3288
+ await runSelfTestFixture(
3289
+ {
3290
+ "packages/coding-agent/src/gjc-runtime/team-runtime.ts": canonicalTeamRuntimeSendKeysFixture.replace(
3291
+ "Bun.spawnSync([config.tmux_command, ...args]",
3292
+ 'Bun.spawnSync([config.tmux_command, "run-shell", ...args]',
3293
+ ),
3294
+ },
3295
+ 1,
3296
+ "tmux send-keys content injection is outside sanctioned process lifecycle",
3297
+ );
3118
3298
  await runSelfTestFixture(
3119
3299
  {
3120
3300
  "packages/coding-agent/src/coordinator-mcp/server.ts":