@gajae-code/coding-agent 0.11.1 → 0.11.2

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 (404) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/types/cli/config-cli.d.ts +11 -1
  3. package/dist/types/cli/notify-cli.d.ts +1 -0
  4. package/dist/types/cli/session-picker.d.ts +2 -1
  5. package/dist/types/cli/setup-cli.d.ts +1 -1
  6. package/dist/types/commands/mcp-serve.d.ts +33 -0
  7. package/dist/types/commands/mcp.d.ts +1 -1
  8. package/dist/types/commands/notify.d.ts +0 -2
  9. package/dist/types/commands/sdk.d.ts +1 -1
  10. package/dist/types/config/atomic-yaml-patch.d.ts +18 -0
  11. package/dist/types/config/file-lock.d.ts +14 -4
  12. package/dist/types/config/keybindings.d.ts +42 -1
  13. package/dist/types/config/model-auth.d.ts +3 -0
  14. package/dist/types/config/model-bindings-applier.d.ts +13 -0
  15. package/dist/types/config/model-discovery-manager.d.ts +49 -0
  16. package/dist/types/config/model-equivalence.d.ts +20 -0
  17. package/dist/types/config/model-registry.d.ts +16 -15
  18. package/dist/types/config/model-resolver.d.ts +28 -18
  19. package/dist/types/config/models-config-schema.d.ts +11 -0
  20. package/dist/types/config/settings-schema.d.ts +56 -1
  21. package/dist/types/config/settings.d.ts +14 -11
  22. package/dist/types/coordinator-mcp/policy.d.ts +5 -0
  23. package/dist/types/coordinator-mcp/question-gate-codec.d.ts +129 -0
  24. package/dist/types/coordinator-mcp/question-state.d.ts +356 -0
  25. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  26. package/dist/types/discovery/helpers.d.ts +0 -6
  27. package/dist/types/edit/index.d.ts +3 -0
  28. package/dist/types/eval/py/env.d.ts +9 -0
  29. package/dist/types/extensibility/extensions/loader.d.ts +2 -1
  30. package/dist/types/extensibility/extensions/runner.d.ts +2 -2
  31. package/dist/types/extensibility/extensions/types.d.ts +34 -3
  32. package/dist/types/extensibility/hooks/runner.d.ts +1 -1
  33. package/dist/types/extensibility/shared-events.d.ts +2 -0
  34. package/dist/types/gjc-runtime/deep-interview-recorder.d.ts +10 -1
  35. package/dist/types/gjc-runtime/deep-interview-state.d.ts +44 -0
  36. package/dist/types/gjc-runtime/goal-mode-request.d.ts +11 -1
  37. package/dist/types/gjc-runtime/launch-worktree.d.ts +4 -2
  38. package/dist/types/gjc-runtime/linux-proc.d.ts +29 -0
  39. package/dist/types/gjc-runtime/session-resolution.d.ts +2 -2
  40. package/dist/types/gjc-runtime/state-migrations.d.ts +1 -1
  41. package/dist/types/gjc-runtime/state-writer.d.ts +2 -1
  42. package/dist/types/gjc-runtime/team-launch.d.ts +59 -0
  43. package/dist/types/gjc-runtime/team-notify.d.ts +45 -0
  44. package/dist/types/gjc-runtime/team-runtime.d.ts +29 -121
  45. package/dist/types/gjc-runtime/team-store.d.ts +160 -0
  46. package/dist/types/gjc-runtime/team-workers.d.ts +78 -0
  47. package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +8 -0
  48. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +13 -0
  49. package/dist/types/gjc-runtime/ultragoal-evidence.d.ts +38 -0
  50. package/dist/types/gjc-runtime/ultragoal-guard.d.ts +7 -0
  51. package/dist/types/gjc-runtime/ultragoal-pipeline.d.ts +23 -0
  52. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +55 -33
  53. package/dist/types/gjc-runtime/workflow-cli-common.d.ts +8 -0
  54. package/dist/types/gjc-runtime/workflow-manifest.d.ts +3 -0
  55. package/dist/types/goals/continuation-timeout-guard.d.ts +22 -0
  56. package/dist/types/goals/runtime.d.ts +1 -0
  57. package/dist/types/goals/state.d.ts +8 -0
  58. package/dist/types/harness-control-plane/lifecycle-reconciliation.d.ts +17 -0
  59. package/dist/types/harness-control-plane/phase-rollup.d.ts +4 -7
  60. package/dist/types/harness-control-plane/receipt-ingest.d.ts +5 -0
  61. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  62. package/dist/types/hindsight/state.d.ts +11 -4
  63. package/dist/types/lsp/lspmux.d.ts +5 -3
  64. package/dist/types/lsp/path-trust.d.ts +1 -0
  65. package/dist/types/main.d.ts +3 -2
  66. package/dist/types/memories/storage.d.ts +1 -0
  67. package/dist/types/modes/action-registry.d.ts +29 -0
  68. package/dist/types/modes/components/chrome.d.ts +14 -0
  69. package/dist/types/modes/components/command-palette.d.ts +27 -0
  70. package/dist/types/modes/components/custom-provider-wizard.d.ts +1 -0
  71. package/dist/types/modes/components/index.d.ts +2 -1
  72. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  73. package/dist/types/modes/components/plan-preview-overlay.d.ts +43 -0
  74. package/dist/types/modes/components/queue-mode-selector.d.ts +1 -1
  75. package/dist/types/modes/components/queue-pane.d.ts +12 -0
  76. package/dist/types/modes/components/read-tool-group.d.ts +6 -0
  77. package/dist/types/modes/components/session-observer-overlay.d.ts +3 -4
  78. package/dist/types/modes/components/sessions-dashboard.d.ts +32 -0
  79. package/dist/types/modes/components/settings-selector.d.ts +1 -1
  80. package/dist/types/modes/components/show-images-selector.d.ts +1 -1
  81. package/dist/types/modes/components/status-line/types.d.ts +1 -1
  82. package/dist/types/modes/components/status-line.d.ts +1 -94
  83. package/dist/types/modes/components/tasks-pane.d.ts +15 -0
  84. package/dist/types/modes/components/theme-selector.d.ts +1 -1
  85. package/dist/types/modes/components/tool-execution.d.ts +15 -0
  86. package/dist/types/modes/components/tool-status-header.d.ts +111 -0
  87. package/dist/types/modes/components/transcript-viewer-overlay.d.ts +42 -0
  88. package/dist/types/modes/controllers/goal-mode-controller.d.ts +62 -0
  89. package/dist/types/modes/controllers/input-controller.d.ts +8 -1
  90. package/dist/types/modes/controllers/mode-gate.d.ts +8 -0
  91. package/dist/types/modes/controllers/plan-mode-controller.d.ts +65 -0
  92. package/dist/types/modes/controllers/selector-controller.d.ts +15 -3
  93. package/dist/types/modes/controllers/stt-controller.d.ts +26 -0
  94. package/dist/types/modes/interactive-mode.d.ts +19 -17
  95. package/dist/types/modes/jobs-observer.d.ts +2 -0
  96. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -11
  97. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +20 -2
  98. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +31 -0
  99. package/dist/types/modes/tasks-aggregator.d.ts +39 -0
  100. package/dist/types/modes/transcript-item-registry.d.ts +60 -0
  101. package/dist/types/modes/types.d.ts +20 -13
  102. package/dist/types/modes/utils/ui-helpers.d.ts +2 -2
  103. package/dist/types/runtime-mcp/manager.d.ts +1 -1
  104. package/dist/types/sdk/broker/broker.d.ts +78 -12
  105. package/dist/types/sdk/broker/lifecycle-codec.d.ts +4 -0
  106. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +15 -1
  107. package/dist/types/sdk/broker/lifecycle.d.ts +6 -2
  108. package/dist/types/sdk/broker/process-incarnation.d.ts +2 -0
  109. package/dist/types/sdk/broker/session-index.d.ts +0 -1
  110. package/dist/types/sdk/broker/state-version.d.ts +2 -0
  111. package/dist/types/sdk/bus/chat-effect-journal.d.ts +1 -0
  112. package/dist/types/sdk/bus/config-commands.d.ts +1 -1
  113. package/dist/types/sdk/bus/config.d.ts +11 -0
  114. package/dist/types/sdk/bus/daemon-paths.d.ts +1 -0
  115. package/dist/types/sdk/bus/html-format.d.ts +3 -2
  116. package/dist/types/sdk/bus/index.d.ts +27 -0
  117. package/dist/types/sdk/bus/lifecycle-control-runtime.d.ts +4 -0
  118. package/dist/types/sdk/bus/notification-service.d.ts +20 -0
  119. package/dist/types/sdk/bus/rate-limit-pool.d.ts +13 -2
  120. package/dist/types/sdk/bus/recent-activity.d.ts +21 -12
  121. package/dist/types/sdk/bus/rich-document.d.ts +7 -0
  122. package/dist/types/sdk/bus/rich-render.d.ts +18 -41
  123. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
  124. package/dist/types/sdk/bus/telegram-daemon.d.ts +46 -3
  125. package/dist/types/sdk/bus/threaded-inbound.d.ts +1 -1
  126. package/dist/types/sdk/bus/threaded-render.d.ts +13 -0
  127. package/dist/types/sdk/bus/topic-registry.d.ts +24 -2
  128. package/dist/types/sdk/host/control/operations.d.ts +1 -1
  129. package/dist/types/sdk/host/host.d.ts +2 -0
  130. package/dist/types/sdk/index.d.ts +1 -0
  131. package/dist/types/sdk/session-directory.d.ts +56 -0
  132. package/dist/types/session/agent-session.d.ts +82 -47
  133. package/dist/types/session/agent-storage.d.ts +7 -0
  134. package/dist/types/session/fallback-chain-controller.d.ts +10 -2
  135. package/dist/types/session/internal/managed-session-scope.d.ts +102 -0
  136. package/dist/types/session/internal/managed-session-storage.d.ts +38 -0
  137. package/dist/types/session/messages.d.ts +16 -0
  138. package/dist/types/session/session-manager-internal.d.ts +14 -0
  139. package/dist/types/session/session-manager.d.ts +82 -12
  140. package/dist/types/session/session-storage.d.ts +43 -3
  141. package/dist/types/session/volatile-context-pruning.d.ts +15 -0
  142. package/dist/types/skill-state/{deep-interview-mutation-guard.d.ts → workflow-mutation-guard.d.ts} +24 -8
  143. package/dist/types/skill-state/workflow-state-contract.d.ts +1 -3
  144. package/dist/types/slash-commands/builtin-registry.d.ts +4 -1
  145. package/dist/types/system-prompt.d.ts +2 -11
  146. package/dist/types/task/executor.d.ts +3 -1
  147. package/dist/types/thinking.d.ts +7 -0
  148. package/dist/types/tool-discovery/tool-index.d.ts +1 -50
  149. package/dist/types/tools/ask.d.ts +64 -2
  150. package/dist/types/tools/bash.d.ts +3 -0
  151. package/dist/types/tools/browser/dead-tab-recovery.d.ts +24 -0
  152. package/dist/types/tools/browser/tab-supervisor.d.ts +21 -0
  153. package/dist/types/tools/cron.d.ts +2 -0
  154. package/dist/types/tools/fetch.d.ts +1 -0
  155. package/dist/types/tools/index.d.ts +30 -15
  156. package/dist/types/tools/output-meta.d.ts +1 -0
  157. package/dist/types/tools/read.d.ts +3 -0
  158. package/dist/types/tools/search-tool-bm25.d.ts +3 -4
  159. package/dist/types/utils/event-bus.d.ts +1 -1
  160. package/dist/types/web/search/index.d.ts +3 -1
  161. package/package.json +21 -9
  162. package/scripts/build-sdk-package-smoke.ts +34 -1
  163. package/scripts/generate-hotkeys-docs.ts +74 -0
  164. package/scripts/generate-sdk-operation-inventory.ts +64 -20
  165. package/scripts/verify-gjc-sdk-canonicalization.ts +182 -2
  166. package/src/async/job-manager.ts +49 -6
  167. package/src/cli/config-cli.ts +75 -2
  168. package/src/cli/notify-cli.ts +92 -26
  169. package/src/cli/session-picker.ts +20 -3
  170. package/src/cli/setup-cli.ts +1 -1
  171. package/src/cli.ts +1 -1
  172. package/src/commands/config.ts +1 -1
  173. package/src/commands/harness.ts +34 -106
  174. package/src/commands/launch.ts +6 -4
  175. package/src/commands/mcp-serve.ts +85 -8
  176. package/src/commands/mcp.ts +2 -2
  177. package/src/commands/notify.ts +8 -4
  178. package/src/commands/sdk.ts +61 -40
  179. package/src/commands/ultragoal.ts +4 -1
  180. package/src/config/atomic-yaml-patch.ts +80 -13
  181. package/src/config/file-lock.ts +105 -43
  182. package/src/config/keybindings.ts +64 -20
  183. package/src/config/model-auth.ts +9 -0
  184. package/src/config/model-bindings-applier.ts +139 -0
  185. package/src/config/model-discovery-manager.ts +224 -0
  186. package/src/config/model-equivalence.ts +66 -0
  187. package/src/config/model-registry.ts +169 -302
  188. package/src/config/model-resolver.ts +361 -369
  189. package/src/config/models-config-schema.ts +5 -4
  190. package/src/config/settings-schema.ts +159 -2
  191. package/src/config/settings.ts +458 -482
  192. package/src/coordinator-mcp/policy.ts +76 -11
  193. package/src/coordinator-mcp/question-gate-codec.ts +274 -0
  194. package/src/coordinator-mcp/question-state.ts +778 -0
  195. package/src/coordinator-mcp/server.ts +1702 -238
  196. package/src/debug/index.ts +1 -1
  197. package/src/defaults/gjc/skills/deep-interview/SKILL.md +13 -1
  198. package/src/defaults/gjc/skills/team/SKILL.md +16 -0
  199. package/src/discovery/helpers.ts +1 -50
  200. package/src/edit/index.ts +64 -0
  201. package/src/eval/py/env.ts +26 -0
  202. package/src/eval/py/kernel.ts +5 -3
  203. package/src/extensibility/extensions/loader.ts +9 -1
  204. package/src/extensibility/extensions/runner.ts +12 -3
  205. package/src/extensibility/extensions/types.ts +39 -1
  206. package/src/extensibility/gjc-plugins/installer.ts +16 -16
  207. package/src/extensibility/hooks/runner.ts +2 -2
  208. package/src/extensibility/runtime-skill-discovery.ts +33 -13
  209. package/src/extensibility/shared-events.ts +2 -0
  210. package/src/gjc-runtime/deep-interview-recorder.ts +63 -3
  211. package/src/gjc-runtime/deep-interview-runtime.ts +76 -27
  212. package/src/gjc-runtime/deep-interview-state.ts +317 -5
  213. package/src/gjc-runtime/goal-mode-request.ts +55 -8
  214. package/src/gjc-runtime/launch-tmux.ts +2 -5
  215. package/src/gjc-runtime/launch-worktree.ts +5 -5
  216. package/src/gjc-runtime/linux-proc.ts +71 -0
  217. package/src/gjc-runtime/ralplan-runtime.ts +74 -90
  218. package/src/gjc-runtime/session-resolution.ts +18 -3
  219. package/src/gjc-runtime/session-state-sidecar.ts +6 -107
  220. package/src/gjc-runtime/state-migrations.ts +1 -1
  221. package/src/gjc-runtime/state-runtime.ts +320 -249
  222. package/src/gjc-runtime/state-writer.ts +36 -40
  223. package/src/gjc-runtime/team-launch.ts +319 -0
  224. package/src/gjc-runtime/team-notify.ts +326 -0
  225. package/src/gjc-runtime/team-runtime.ts +1099 -1482
  226. package/src/gjc-runtime/team-store.ts +828 -0
  227. package/src/gjc-runtime/team-workers.ts +962 -0
  228. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +2 -11
  229. package/src/gjc-runtime/tmux-owner-isolation.ts +14 -9
  230. package/src/gjc-runtime/tmux-sessions.ts +4 -21
  231. package/src/gjc-runtime/ultragoal-change-set.ts +172 -0
  232. package/src/gjc-runtime/ultragoal-evidence.ts +874 -0
  233. package/src/gjc-runtime/ultragoal-guard.ts +29 -5
  234. package/src/gjc-runtime/ultragoal-pipeline.ts +306 -0
  235. package/src/gjc-runtime/ultragoal-runtime.ts +84 -1311
  236. package/src/gjc-runtime/workflow-cli-common.ts +30 -0
  237. package/src/gjc-runtime/workflow-manifest.generated.json +58 -0
  238. package/src/gjc-runtime/workflow-manifest.ts +18 -0
  239. package/src/goals/continuation-timeout-guard.ts +79 -0
  240. package/src/goals/runtime.ts +7 -5
  241. package/src/goals/state.ts +18 -0
  242. package/src/harness-control-plane/lifecycle-reconciliation.ts +64 -0
  243. package/src/harness-control-plane/phase-rollup.ts +4 -7
  244. package/src/harness-control-plane/receipt-ingest.ts +5 -0
  245. package/src/harness-control-plane/receipt-spool.ts +51 -7
  246. package/src/harness-control-plane/session-lease.ts +12 -130
  247. package/src/hindsight/backend.ts +26 -27
  248. package/src/hindsight/state.ts +101 -32
  249. package/src/hooks/skill-state.ts +17 -11
  250. package/src/internal-urls/docs-index.generated.ts +21 -18
  251. package/src/lsp/client.ts +1 -1
  252. package/src/lsp/config.ts +145 -26
  253. package/src/lsp/index.ts +1 -1
  254. package/src/lsp/lspmux.ts +39 -10
  255. package/src/lsp/path-trust.ts +81 -0
  256. package/src/main.ts +28 -8
  257. package/src/memories/index.ts +1 -0
  258. package/src/memories/storage.ts +6 -2
  259. package/src/modes/action-registry.ts +165 -0
  260. package/src/modes/components/chrome.ts +40 -0
  261. package/src/modes/components/command-palette.ts +168 -0
  262. package/src/modes/components/custom-editor.ts +1 -1
  263. package/src/modes/components/custom-provider-wizard.ts +51 -14
  264. package/src/modes/components/index.ts +2 -1
  265. package/src/modes/components/pet-selector.ts +11 -17
  266. package/src/modes/components/plan-preview-overlay.ts +295 -0
  267. package/src/modes/components/queue-mode-selector.ts +10 -27
  268. package/src/modes/components/queue-pane.ts +79 -0
  269. package/src/modes/components/read-tool-group.ts +13 -0
  270. package/src/modes/components/session-observer-overlay.ts +207 -772
  271. package/src/modes/components/sessions-dashboard.ts +181 -0
  272. package/src/modes/components/settings-selector.ts +1 -1
  273. package/src/modes/components/show-images-selector.ts +10 -24
  274. package/src/modes/components/status-line/types.ts +1 -1
  275. package/src/modes/components/status-line.ts +1 -969
  276. package/src/modes/components/tasks-pane.ts +73 -0
  277. package/src/modes/components/theme-selector.ts +11 -31
  278. package/src/modes/components/tool-execution.ts +22 -0
  279. package/src/modes/components/tool-status-header.ts +1056 -0
  280. package/src/modes/components/transcript-viewer-overlay.ts +384 -0
  281. package/src/modes/controllers/btw-controller.ts +1 -0
  282. package/src/modes/controllers/event-controller.ts +3 -2
  283. package/src/modes/controllers/extension-ui-controller.ts +24 -1
  284. package/src/modes/controllers/goal-mode-controller.ts +474 -0
  285. package/src/modes/controllers/input-controller.ts +764 -229
  286. package/src/modes/controllers/mode-gate.ts +24 -0
  287. package/src/modes/controllers/plan-mode-controller.ts +517 -0
  288. package/src/modes/controllers/selector-controller.ts +225 -10
  289. package/src/modes/controllers/stt-controller.ts +125 -0
  290. package/src/modes/interactive-mode.ts +289 -1150
  291. package/src/modes/jobs-observer.ts +3 -0
  292. package/src/modes/runtime-init.ts +8 -0
  293. package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -106
  294. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +71 -16
  295. package/src/modes/shared/agent-wire/workflow-gate-types.ts +177 -0
  296. package/src/modes/tasks-aggregator.ts +199 -0
  297. package/src/modes/transcript-item-registry.ts +229 -0
  298. package/src/modes/types.ts +45 -18
  299. package/src/modes/utils/ui-helpers.ts +17 -9
  300. package/src/prompts/agent-fragments/ralplan-persistence.md +6 -0
  301. package/src/prompts/agent-fragments/restricted-bash.md +1 -0
  302. package/src/prompts/agents/architect.md +2 -8
  303. package/src/prompts/agents/critic.md +2 -8
  304. package/src/prompts/agents/executor.md +3 -0
  305. package/src/prompts/agents/planner.md +4 -12
  306. package/src/prompts/system/custom-system-prompt.md +1 -23
  307. package/src/prompts/system/plan-mode-approved.md +8 -0
  308. package/src/prompts/system/system-prompt.md +17 -96
  309. package/src/prompts/tools/bash.md +4 -4
  310. package/src/prompts/tools/browser.md +15 -52
  311. package/src/prompts/tools/find.md +2 -2
  312. package/src/prompts/tools/hashline.md +13 -55
  313. package/src/prompts/tools/read.md +3 -6
  314. package/src/prompts/tools/search-tool-bm25.md +0 -2
  315. package/src/prompts/tools/search.md +2 -4
  316. package/src/prompts/tools/skill-discovery.md +1 -2
  317. package/src/prompts/tools/task.md +1 -1
  318. package/src/runtime-mcp/manager.ts +1 -1
  319. package/src/sdk/broker/broker.ts +206 -78
  320. package/src/sdk/broker/discovery.ts +1 -1
  321. package/src/sdk/broker/ensure.ts +3 -1
  322. package/src/sdk/broker/lifecycle-codec.ts +11 -0
  323. package/src/sdk/broker/lifecycle-ledger.ts +371 -74
  324. package/src/sdk/broker/lifecycle.ts +1399 -142
  325. package/src/sdk/broker/process-incarnation.ts +5 -13
  326. package/src/sdk/broker/session-index.ts +145 -56
  327. package/src/sdk/broker/state-version.ts +21 -0
  328. package/src/sdk/broker/transport.ts +1 -1
  329. package/src/sdk/bus/chat-daemon-cli.ts +2 -0
  330. package/src/sdk/bus/chat-daemon-control.ts +8 -28
  331. package/src/sdk/bus/chat-effect-journal.ts +10 -2
  332. package/src/sdk/bus/config-commands.ts +5 -4
  333. package/src/sdk/bus/config.ts +98 -0
  334. package/src/sdk/bus/conversation-store.ts +5 -29
  335. package/src/sdk/bus/daemon-paths.ts +2 -0
  336. package/src/sdk/bus/html-format.ts +20 -3
  337. package/src/sdk/bus/index.ts +778 -93
  338. package/src/sdk/bus/lifecycle-control-runtime.ts +91 -33
  339. package/src/sdk/bus/natives-augment.d.ts +26 -1
  340. package/src/sdk/bus/notification-service.ts +168 -20
  341. package/src/sdk/bus/rate-limit-pool.ts +58 -14
  342. package/src/sdk/bus/recent-activity.ts +188 -74
  343. package/src/sdk/bus/rich-document.ts +258 -0
  344. package/src/sdk/bus/rich-render.ts +62 -70
  345. package/src/sdk/bus/telegram-daemon-cli.ts +15 -59
  346. package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
  347. package/src/sdk/bus/telegram-daemon.ts +1389 -237
  348. package/src/sdk/bus/threaded-inbound.ts +8 -3
  349. package/src/sdk/bus/threaded-render.ts +57 -1
  350. package/src/sdk/bus/topic-registry.ts +120 -13
  351. package/src/sdk/host/control/dispatch.ts +14 -2
  352. package/src/sdk/host/control/operations.ts +6 -1
  353. package/src/sdk/host/host.ts +31 -1
  354. package/src/sdk/host/query/handlers.ts +20 -22
  355. package/src/sdk/host/query/revision-store.ts +80 -57
  356. package/src/sdk/index.ts +1 -0
  357. package/src/sdk/protocol/operation-inventory.generated.json +943 -1907
  358. package/src/sdk/session-directory.ts +141 -0
  359. package/src/sdk/session.ts +458 -479
  360. package/src/session/agent-session.ts +1700 -583
  361. package/src/session/agent-storage.ts +18 -0
  362. package/src/session/cache-economics.ts +25 -8
  363. package/src/session/fallback-chain-controller.ts +53 -3
  364. package/src/session/internal/managed-session-scope.ts +2226 -0
  365. package/src/session/internal/managed-session-storage.ts +453 -0
  366. package/src/session/messages.ts +91 -2
  367. package/src/session/session-manager-internal.ts +33 -0
  368. package/src/session/session-manager.ts +1112 -333
  369. package/src/session/session-storage.ts +444 -39
  370. package/src/session/volatile-context-pruning.ts +78 -0
  371. package/src/setup/credential-auto-import.ts +2 -1
  372. package/src/setup/hermes/templates/operator-instructions.v1.md +1 -1
  373. package/src/setup/provider-onboarding.ts +36 -61
  374. package/src/setup/provider-presets.json +5 -0
  375. package/src/skill-state/active-state.ts +3 -13
  376. package/src/skill-state/{deep-interview-mutation-guard.ts → workflow-mutation-guard.ts} +47 -29
  377. package/src/skill-state/workflow-state-contract.ts +6 -41
  378. package/src/slash-commands/builtin-registry.ts +46 -11
  379. package/src/system-prompt.ts +37 -44
  380. package/src/task/agents.ts +19 -1
  381. package/src/task/executor.ts +90 -6
  382. package/src/task/index.ts +36 -21
  383. package/src/thinking.ts +21 -6
  384. package/src/tool-discovery/tool-index.ts +2 -134
  385. package/src/tools/ask.ts +157 -21
  386. package/src/tools/ast-edit.ts +1 -1
  387. package/src/tools/bash.ts +38 -0
  388. package/src/tools/browser/dead-tab-recovery.ts +78 -0
  389. package/src/tools/browser/tab-supervisor.ts +282 -36
  390. package/src/tools/computer.ts +10 -3
  391. package/src/tools/cron.ts +30 -16
  392. package/src/tools/eval.ts +1 -2
  393. package/src/tools/fetch.ts +11 -4
  394. package/src/tools/index.ts +76 -24
  395. package/src/tools/output-meta.ts +13 -5
  396. package/src/tools/read.ts +37 -1
  397. package/src/tools/resource-gc.ts +2 -2
  398. package/src/tools/search-tool-bm25.ts +11 -74
  399. package/src/utils/event-bus.ts +9 -4
  400. package/src/web/search/index.ts +3 -3
  401. package/dist/types/discovery/plugin-dir-roots.d.ts +0 -15
  402. package/dist/types/runtime-mcp/discoverable-tool-metadata.d.ts +0 -7
  403. package/src/discovery/plugin-dir-roots.ts +0 -28
  404. package/src/runtime-mcp/discoverable-tool-metadata.ts +0 -25
@@ -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":
@@ -12,6 +12,7 @@ const DELIVERY_MAX_TEXT_BYTES = 64 * 1024;
12
12
  const DELIVERY_PREVIEW_HEAD_BYTES = 32 * 1024;
13
13
  const DELIVERY_PREVIEW_TAIL_BYTES = 32 * 1024;
14
14
  const DELIVERY_MAX_ATTEMPTS = 3;
15
+ const MAX_DEAD_LETTERED_DELIVERIES = 50;
15
16
 
16
17
  export interface AsyncJob {
17
18
  id: string;
@@ -207,6 +208,12 @@ interface AsyncJobDelivery {
207
208
  promise?: Promise<void>;
208
209
  }
209
210
 
211
+ interface DeadLetteredDelivery {
212
+ jobId: string;
213
+ attempt: number;
214
+ lastError?: string;
215
+ }
216
+
210
217
  export interface AsyncJobDeliveryState {
211
218
  queued: number;
212
219
  delivering: boolean;
@@ -381,7 +388,8 @@ export class AsyncJobManager {
381
388
  * resume fails closed with reason "no_runner".
382
389
  */
383
390
  readonly #descriptorResumeRunners = new Map<string, ResumeRunner>();
384
- readonly #deadLetteredDeliveries = new Map<string, AsyncJobDelivery>();
391
+ readonly #deadLetteredDeliveries = new Map<string, DeadLetteredDelivery>();
392
+ readonly #deadLetteredDeliveryOwners = new Map<string, string | undefined>();
385
393
  readonly #ownerSubagentShutdownLeases = new Map<string, OwnerSubagentShutdownLeaseState>();
386
394
  #ownerSubagentShutdownSeq = 0;
387
395
  #lastDisposeDiagnostics: AsyncJobDisposeDiagnostics = { stuckJobIds: [], deliveriesDrained: true };
@@ -1333,12 +1341,16 @@ export class AsyncJobManager {
1333
1341
  }
1334
1342
 
1335
1343
  getDeliveryState(filter?: AsyncJobFilter): AsyncJobDeliveryState {
1344
+ this.#expireMonitorTombstones();
1345
+ this.#pruneEvictedDeadLetters();
1336
1346
  const deliveries = this.#filterDeliveries(filter);
1337
1347
  const inFlightDeliveries = this.#filterInFlightDeliveries(filter);
1338
1348
  const ownerId = filter?.ownerId;
1339
- const deadLettered = Array.from(this.#deadLetteredDeliveries.values()).filter(
1340
- delivery => !ownerId || delivery.ownerId === ownerId,
1341
- ).length;
1349
+ const deadLettered = ownerId
1350
+ ? Array.from(this.#deadLetteredDeliveries.keys()).filter(
1351
+ jobId => this.#deadLetteredDeliveryOwners.get(jobId) === ownerId,
1352
+ ).length
1353
+ : this.#deadLetteredDeliveries.size;
1342
1354
  const nextRetryAt = deliveries.reduce<number | undefined>((next, delivery) => {
1343
1355
  if (next === undefined) return delivery.nextAttemptAt;
1344
1356
  return Math.min(next, delivery.nextAttemptAt);
@@ -1553,6 +1565,7 @@ export class AsyncJobManager {
1553
1565
  this.#deliveries.length = 0;
1554
1566
  this.#inFlightDeliveries.length = 0;
1555
1567
  this.#deadLetteredDeliveries.clear();
1568
+ this.#deadLetteredDeliveryOwners.clear();
1556
1569
  this.#suppressedDeliveries.clear();
1557
1570
  this.#watchedJobs.clear();
1558
1571
  this.#outputState.clear();
@@ -1615,12 +1628,15 @@ export class AsyncJobManager {
1615
1628
  }
1616
1629
 
1617
1630
  #evictJob(jobId: string): void {
1631
+ this.#expireMonitorTombstones();
1618
1632
  this.#recordMonitorTombstone(jobId);
1619
1633
  this.#runLifecycle(jobId, "evict");
1620
1634
  this.#purgeTerminalSubagentStateForJob(jobId);
1621
1635
  this.#jobs.delete(jobId);
1622
1636
  this.#lifecycles.delete(jobId);
1623
1637
  this.#lifecyclePhases.delete(jobId);
1638
+ this.#deadLetteredDeliveries.delete(jobId);
1639
+ this.#deadLetteredDeliveryOwners.delete(jobId);
1624
1640
  this.#suppressedDeliveries.delete(jobId);
1625
1641
  this.#watchedJobs.delete(jobId);
1626
1642
  this.#outputState.delete(jobId);
@@ -1700,6 +1716,33 @@ export class AsyncJobManager {
1700
1716
  return this.#isDeliveryAcknowledged(jobId) || this.#watchedJobs.has(jobId);
1701
1717
  }
1702
1718
 
1719
+ #pruneEvictedDeadLetters(): void {
1720
+ for (const jobId of this.#deadLetteredDeliveries.keys()) {
1721
+ if (this.#jobs.has(jobId)) continue;
1722
+ this.#deadLetteredDeliveries.delete(jobId);
1723
+ this.#deadLetteredDeliveryOwners.delete(jobId);
1724
+ }
1725
+ }
1726
+
1727
+ #recordDeadLetter(delivery: AsyncJobDelivery): void {
1728
+ this.#pruneEvictedDeadLetters();
1729
+ if (!this.#jobs.has(delivery.jobId)) return;
1730
+ this.#deadLetteredDeliveries.delete(delivery.jobId);
1731
+ this.#deadLetteredDeliveryOwners.delete(delivery.jobId);
1732
+ this.#deadLetteredDeliveries.set(delivery.jobId, {
1733
+ jobId: delivery.jobId,
1734
+ attempt: delivery.attempt,
1735
+ lastError: delivery.lastError,
1736
+ });
1737
+ this.#deadLetteredDeliveryOwners.set(delivery.jobId, delivery.ownerId);
1738
+ while (this.#deadLetteredDeliveries.size > MAX_DEAD_LETTERED_DELIVERIES) {
1739
+ const oldestJobId = this.#deadLetteredDeliveries.keys().next().value;
1740
+ if (oldestJobId === undefined) return;
1741
+ this.#deadLetteredDeliveries.delete(oldestJobId);
1742
+ this.#deadLetteredDeliveryOwners.delete(oldestJobId);
1743
+ }
1744
+ }
1745
+
1703
1746
  #enqueueDelivery(jobId: string, text: string): void {
1704
1747
  // Skip delivery if already acknowledged
1705
1748
  if (this.#isDeliveryAcknowledged(jobId)) {
@@ -1717,7 +1760,7 @@ export class AsyncJobManager {
1717
1760
  });
1718
1761
  while (this.#deliveries.length > DEFAULT_MAX_DELIVERY_QUEUE) {
1719
1762
  const dropped = this.#deliveries.shift();
1720
- if (dropped) this.#deadLetteredDeliveries.set(dropped.jobId, dropped);
1763
+ if (dropped) this.#recordDeadLetter(dropped);
1721
1764
  }
1722
1765
  this.#ensureDeliveryLoop();
1723
1766
  }
@@ -1781,7 +1824,7 @@ export class AsyncJobManager {
1781
1824
  delivery.attempt += 1;
1782
1825
  delivery.lastError = error instanceof Error ? error.message : String(error);
1783
1826
  if (delivery.attempt >= DELIVERY_MAX_ATTEMPTS) {
1784
- this.#deadLetteredDeliveries.set(delivery.jobId, delivery);
1827
+ this.#recordDeadLetter(delivery);
1785
1828
  logger.warn("Async job completion delivery reached retry cap", {
1786
1829
  jobId: delivery.jobId,
1787
1830
  attempt: delivery.attempt,