@gajae-code/coding-agent 0.18.11 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (462) hide show
  1. package/CHANGELOG.md +760 -0
  2. package/dist/types/async/job-manager.d.ts +7 -3
  3. package/dist/types/async/result-formatting.d.ts +2 -0
  4. package/dist/types/autoresearch/git.d.ts +1 -1
  5. package/dist/types/capability/fs.d.ts +2 -2
  6. package/dist/types/capability/rule.d.ts +7 -2
  7. package/dist/types/cli/accounts-cli.d.ts +2 -2
  8. package/dist/types/cli/append-system-prompt.d.ts +6 -0
  9. package/dist/types/cli/args.d.ts +7 -2
  10. package/dist/types/cli/customize-doctor-precedence.d.ts +16 -0
  11. package/dist/types/cli/customize-doctor.d.ts +4 -3
  12. package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
  13. package/dist/types/cli/install-activation.d.ts +10 -4
  14. package/dist/types/cli/public-command-errors.d.ts +2 -0
  15. package/dist/types/cli/root-flags.d.ts +0 -12
  16. package/dist/types/cli/update-cli.d.ts +21 -3
  17. package/dist/types/cli-main.d.ts +0 -6
  18. package/dist/types/cli-ordinary.d.ts +2 -2
  19. package/dist/types/commands/accounts.d.ts +2 -1
  20. package/dist/types/commands/launch.d.ts +0 -6
  21. package/dist/types/commands/migrate.d.ts +1 -1
  22. package/dist/types/commands/sdk.d.ts +13 -0
  23. package/dist/types/commit/changelog/index.d.ts +1 -0
  24. package/dist/types/commit/map-reduce/index.d.ts +4 -4
  25. package/dist/types/config/autorouting-tier-map.d.ts +53 -1
  26. package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
  27. package/dist/types/config/config-hot-reload.d.ts +44 -0
  28. package/dist/types/config/file-lock.d.ts +52 -3
  29. package/dist/types/config/model-discovery-manager.d.ts +2 -0
  30. package/dist/types/config/model-profile-activation.d.ts +79 -9
  31. package/dist/types/config/model-registry.d.ts +72 -8
  32. package/dist/types/config/model-resolver.d.ts +7 -4
  33. package/dist/types/config/models-config-schema.d.ts +10 -0
  34. package/dist/types/config/settings-schema.d.ts +57 -4
  35. package/dist/types/config/settings.d.ts +33 -1
  36. package/dist/types/coordinator-mcp/server.d.ts +4 -0
  37. package/dist/types/customization/import.d.ts +2 -0
  38. package/dist/types/customization/types.d.ts +1 -1
  39. package/dist/types/dap/config.d.ts +8 -4
  40. package/dist/types/dap/session.d.ts +11 -2
  41. package/dist/types/debug/system-info.d.ts +6 -1
  42. package/dist/types/discovery/helpers.d.ts +7 -2
  43. package/dist/types/discovery/mcp-compat.d.ts +3 -1
  44. package/dist/types/edit/index.d.ts +5 -0
  45. package/dist/types/edit/modes/patch.d.ts +14 -0
  46. package/dist/types/edit/modes/replace.d.ts +3 -0
  47. package/dist/types/eval/py/runtime.d.ts +9 -0
  48. package/dist/types/exec/bash-executor.d.ts +12 -0
  49. package/dist/types/export/ttsr.d.ts +19 -0
  50. package/dist/types/extensibility/extensions/types.d.ts +5 -1
  51. package/dist/types/extensibility/slash-commands.d.ts +1 -0
  52. package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
  53. package/dist/types/gjc-runtime/ralplan-current-final.d.ts +54 -0
  54. package/dist/types/gjc-runtime/ralplan-runtime.d.ts +5 -0
  55. package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
  56. package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
  57. package/dist/types/gjc-runtime/tmux-sessions.d.ts +24 -0
  58. package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +6 -0
  59. package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
  60. package/dist/types/harness-control-plane/receipt-spool.d.ts +4 -0
  61. package/dist/types/hindsight/content.d.ts +5 -6
  62. package/dist/types/internal-urls/types.d.ts +2 -0
  63. package/dist/types/lsp/clients/swiftlint-client.d.ts +0 -4
  64. package/dist/types/main.d.ts +23 -18
  65. package/dist/types/migrate/action-planner.d.ts +10 -1
  66. package/dist/types/migrate/adapters/codex.d.ts +2 -1
  67. package/dist/types/migrate/adapters/index.d.ts +42 -1
  68. package/dist/types/migrate/executor.d.ts +3 -1
  69. package/dist/types/migrate/hook-module.d.ts +23 -0
  70. package/dist/types/migrate/report.d.ts +2 -1
  71. package/dist/types/migrate/types.d.ts +82 -3
  72. package/dist/types/modes/components/agent-dashboard.d.ts +1 -1
  73. package/dist/types/modes/components/model-selector.d.ts +43 -0
  74. package/dist/types/modes/components/settings-selector.d.ts +6 -0
  75. package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
  76. package/dist/types/modes/prompt-suggestion-controller.d.ts +1 -1
  77. package/dist/types/modes/theme/theme.d.ts +1 -0
  78. package/dist/types/modes/utils/host-status.d.ts +15 -11
  79. package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
  80. package/dist/types/runtime-mcp/manager.d.ts +7 -0
  81. package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
  82. package/dist/types/runtime-mcp/project-host-values.d.ts +11 -5
  83. package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
  84. package/dist/types/sdk/broker/broker-exit.d.ts +3 -3
  85. package/dist/types/sdk/broker/broker.d.ts +29 -2
  86. package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
  87. package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
  88. package/dist/types/sdk/broker/ensure.d.ts +141 -9
  89. package/dist/types/sdk/broker/hop.d.ts +45 -0
  90. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
  91. package/dist/types/sdk/broker/lifecycle.d.ts +22 -0
  92. package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
  93. package/dist/types/sdk/broker/session-index.d.ts +6 -1
  94. package/dist/types/sdk/broker/transport.d.ts +2 -0
  95. package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
  96. package/dist/types/sdk/bus/index.d.ts +44 -0
  97. package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
  98. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -1
  99. package/dist/types/sdk/bus/telegram-daemon.d.ts +2 -0
  100. package/dist/types/sdk/bus/threaded-render.d.ts +2 -1
  101. package/dist/types/sdk/cli/session-cli.d.ts +0 -1
  102. package/dist/types/sdk/host/control/operations.d.ts +5 -1
  103. package/dist/types/sdk/host/events.d.ts +4 -0
  104. package/dist/types/sdk/host/host.d.ts +2 -1
  105. package/dist/types/sdk/host/prompt-image-upload.d.ts +43 -0
  106. package/dist/types/sdk/host/session-runtime.d.ts +40 -8
  107. package/dist/types/sdk/host/surface-policy.d.ts +2 -1
  108. package/dist/types/sdk/lifecycle/service.d.ts +12 -0
  109. package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
  110. package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
  111. package/dist/types/sdk/prompt-status.d.ts +11 -4
  112. package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
  113. package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
  114. package/dist/types/sdk/session-list.d.ts +1 -1
  115. package/dist/types/session/agent-session.d.ts +107 -9
  116. package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
  117. package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
  118. package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
  119. package/dist/types/session/messages.d.ts +5 -1
  120. package/dist/types/session/session-manager.d.ts +29 -3
  121. package/dist/types/session/startup-auth-config.d.ts +24 -2
  122. package/dist/types/session/streaming-output.d.ts +11 -0
  123. package/dist/types/session/terminal-abort.d.ts +3 -1
  124. package/dist/types/session-import/service.d.ts +1 -1
  125. package/dist/types/skill-state/workflow-mutation-guard.d.ts +20 -4
  126. package/dist/types/slash-commands/helpers/mcp.d.ts +5 -0
  127. package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
  128. package/dist/types/ssh/ssh-executor.d.ts +8 -1
  129. package/dist/types/system-prompt.d.ts +3 -2
  130. package/dist/types/task/executor.d.ts +19 -2
  131. package/dist/types/task/role-body.d.ts +11 -0
  132. package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
  133. package/dist/types/tools/atomic-file-write.d.ts +9 -7
  134. package/dist/types/tools/awaiting-input.d.ts +28 -0
  135. package/dist/types/tools/bash-allowed-prefixes.d.ts +17 -0
  136. package/dist/types/tools/bash-skill-urls.d.ts +4 -0
  137. package/dist/types/tools/bash.d.ts +7 -0
  138. package/dist/types/tools/descriptors.d.ts +15 -2
  139. package/dist/types/tools/fetch.d.ts +7 -1
  140. package/dist/types/tools/index.d.ts +2 -0
  141. package/dist/types/tools/irc.d.ts +5 -3
  142. package/dist/types/tools/python.d.ts +1 -1
  143. package/dist/types/tools/report-issue.d.ts +41 -0
  144. package/dist/types/tools/subagent.d.ts +23 -0
  145. package/dist/types/tools/tmux-self-injection-guard.d.ts +2 -0
  146. package/dist/types/tools/ultragoal-ask-guard.d.ts +1 -1
  147. package/dist/types/tools/write.d.ts +2 -0
  148. package/dist/types/utils/file-mentions.d.ts +5 -0
  149. package/dist/types/utils/image-limits.d.ts +7 -0
  150. package/dist/types/utils/image-loading.d.ts +0 -1
  151. package/dist/types/utils/open.d.ts +0 -1
  152. package/dist/types/utils/pasted-image-loading.d.ts +1 -5
  153. package/dist/types/utils/prompt-suggestion.d.ts +2 -2
  154. package/dist/types/utils/shell-snapshot.d.ts +2 -0
  155. package/dist/types/utils/title-generator.d.ts +13 -3
  156. package/dist/types/web/scrapers/types.d.ts +8 -1
  157. package/dist/types/web/search/providers/codex.d.ts +6 -7
  158. package/dist/types/web/search/providers/insane.d.ts +7 -1
  159. package/dist/types/web/search/providers/searxng.d.ts +5 -0
  160. package/package.json +10 -9
  161. package/scripts/acp-conformance-agent.ts +12 -2
  162. package/scripts/build-binary.ts +2 -1
  163. package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
  164. package/scripts/generate-docs-index.ts +8 -1
  165. package/scripts/generate-sdk-operation-inventory.ts +38 -4
  166. package/src/async/job-manager.ts +356 -56
  167. package/src/async/result-formatting.ts +40 -0
  168. package/src/autoresearch/git.ts +9 -2
  169. package/src/autoresearch/prompts/prompt-setup.md +1 -1
  170. package/src/capability/fs.ts +58 -22
  171. package/src/capability/index.ts +2 -2
  172. package/src/capability/rule.ts +11 -2
  173. package/src/cli/accounts-cli.ts +176 -8
  174. package/src/cli/append-system-prompt.ts +12 -0
  175. package/src/cli/args.ts +11 -7
  176. package/src/cli/auth-broker-cli.ts +21 -11
  177. package/src/cli/customize-doctor-precedence.ts +31 -0
  178. package/src/cli/customize-doctor.ts +49 -39
  179. package/src/cli/doctor/install-repairs.ts +35 -5
  180. package/src/cli/fast-help.ts +1 -3
  181. package/src/cli/install-activation.ts +47 -4
  182. package/src/cli/migrate-cli.ts +19 -6
  183. package/src/cli/public-command-errors.ts +6 -0
  184. package/src/cli/root-flags.ts +2 -4
  185. package/src/cli/stats-cli.ts +9 -5
  186. package/src/cli/update-cli.ts +471 -13
  187. package/src/cli-ordinary.ts +7 -2
  188. package/src/commands/accounts.ts +10 -5
  189. package/src/commands/harness.ts +25 -15
  190. package/src/commands/migrate.ts +3 -3
  191. package/src/commands/sdk.ts +277 -50
  192. package/src/commands/ultragoal.ts +16 -8
  193. package/src/commit/agentic/agent.ts +6 -6
  194. package/src/commit/analysis/conventional.ts +14 -5
  195. package/src/commit/changelog/index.ts +39 -1
  196. package/src/commit/map-reduce/index.ts +7 -7
  197. package/src/commit/message.ts +10 -3
  198. package/src/commit/pipeline.ts +12 -12
  199. package/src/config/autorouting-tier-map.ts +50 -1
  200. package/src/config/config-file.ts +106 -3
  201. package/src/config/config-hot-reload-trust.ts +148 -0
  202. package/src/config/config-hot-reload.ts +742 -0
  203. package/src/config/file-lock.ts +1615 -328
  204. package/src/config/keybindings.ts +154 -7
  205. package/src/config/model-bindings-applier.ts +85 -47
  206. package/src/config/model-discovery-manager.ts +10 -0
  207. package/src/config/model-profile-activation.ts +889 -148
  208. package/src/config/model-registry.ts +1706 -205
  209. package/src/config/model-resolver.ts +52 -22
  210. package/src/config/models-config-schema.ts +6 -0
  211. package/src/config/settings-schema.ts +73 -4
  212. package/src/config/settings.ts +460 -24
  213. package/src/coordinator-mcp/policy.ts +26 -1
  214. package/src/coordinator-mcp/server.ts +37 -2
  215. package/src/crash/sanitize.ts +7 -1
  216. package/src/customization/import.ts +279 -8
  217. package/src/customization/inventory.ts +24 -8
  218. package/src/customization/types.ts +1 -0
  219. package/src/dap/client.ts +3 -2
  220. package/src/dap/config.ts +31 -11
  221. package/src/dap/defaults.json +1 -1
  222. package/src/dap/session.ts +161 -36
  223. package/src/debug/crash-diagnostics.ts +89 -6
  224. package/src/debug/report-bundle.ts +90 -2
  225. package/src/debug/system-info.ts +8 -3
  226. package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
  227. package/src/discovery/agents-md.ts +1 -1
  228. package/src/discovery/builtin.ts +4 -3
  229. package/src/discovery/helpers.ts +25 -16
  230. package/src/discovery/mcp-compat.ts +120 -17
  231. package/src/edit/apply-patch/index.ts +12 -1
  232. package/src/edit/index.ts +204 -22
  233. package/src/edit/modes/patch.ts +214 -8
  234. package/src/edit/modes/replace.ts +136 -0
  235. package/src/eval/js/context-manager.ts +29 -3
  236. package/src/eval/js/worker-entry.ts +51 -18
  237. package/src/eval/py/executor.ts +14 -4
  238. package/src/eval/py/runner.py +144 -5
  239. package/src/eval/py/runtime.ts +44 -4
  240. package/src/exec/bash-executor.ts +81 -4
  241. package/src/exec/bash-shell-guardian.ts +4 -1
  242. package/src/exec/bash-shell-supervisor.ts +8 -4
  243. package/src/exec/isolated-shell.ts +5 -1
  244. package/src/exec/non-interactive-env.ts +0 -1
  245. package/src/export/html/index.ts +86 -6
  246. package/src/export/ttsr.ts +176 -1
  247. package/src/extensibility/custom-tools/wrapper.ts +3 -1
  248. package/src/extensibility/extensions/loader.ts +10 -1
  249. package/src/extensibility/extensions/ouroboros-ooo-bridge.ts +63 -1
  250. package/src/extensibility/extensions/types.ts +5 -1
  251. package/src/extensibility/hooks/loader.ts +10 -2
  252. package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
  253. package/src/extensibility/plugins/marketplace/manager.ts +36 -10
  254. package/src/extensibility/slash-commands.ts +5 -0
  255. package/src/gjc-runtime/gc-runtime.ts +37 -7
  256. package/src/gjc-runtime/launch-tmux.ts +30 -15
  257. package/src/gjc-runtime/launch-worktree.test.ts +148 -0
  258. package/src/gjc-runtime/launch-worktree.ts +101 -14
  259. package/src/gjc-runtime/managed-owner-admission.ts +46 -2
  260. package/src/gjc-runtime/ralplan-current-final.ts +294 -0
  261. package/src/gjc-runtime/ralplan-runtime.ts +95 -1
  262. package/src/gjc-runtime/session-resolution.ts +38 -6
  263. package/src/gjc-runtime/session-state-lock.ts +59 -14
  264. package/src/gjc-runtime/state-runtime.ts +23 -19
  265. package/src/gjc-runtime/state-writer.ts +109 -5
  266. package/src/gjc-runtime/tmux-sessions.ts +93 -13
  267. package/src/gjc-runtime/ultragoal-change-set.ts +90 -11
  268. package/src/gjc-runtime/ultragoal-guard.ts +9 -1
  269. package/src/gjc-runtime/ultragoal-runtime.ts +15 -5
  270. package/src/harness-control-plane/finalize.ts +11 -0
  271. package/src/harness-control-plane/receipt-spool.ts +105 -28
  272. package/src/harness-control-plane/storage.ts +124 -6
  273. package/src/hindsight/content.ts +116 -16
  274. package/src/hindsight/mental-models.ts +22 -10
  275. package/src/hindsight/state.ts +7 -4
  276. package/src/hooks/native-skill-hook.ts +17 -12
  277. package/src/internal-urls/artifact-protocol.ts +3 -1
  278. package/src/internal-urls/docs-index.generated.ts +23 -22
  279. package/src/internal-urls/local-protocol.ts +167 -8
  280. package/src/internal-urls/types.ts +2 -0
  281. package/src/lsp/client.ts +2 -1
  282. package/src/lsp/clients/biome-client.ts +2 -0
  283. package/src/lsp/clients/swiftlint-client.ts +2 -0
  284. package/src/lsp/index.ts +29 -0
  285. package/src/lsp/workspace-path.ts +23 -0
  286. package/src/main.ts +330 -92
  287. package/src/memories/index.ts +25 -2
  288. package/src/migrate/action-planner.ts +574 -2
  289. package/src/migrate/adapters/claude-code.ts +162 -5
  290. package/src/migrate/adapters/codex.ts +77 -7
  291. package/src/migrate/adapters/index.ts +258 -5
  292. package/src/migrate/adapters/opencode.ts +10 -1
  293. package/src/migrate/executor.ts +222 -7
  294. package/src/migrate/hook-module.ts +193 -0
  295. package/src/migrate/report.ts +63 -2
  296. package/src/migrate/types.ts +84 -4
  297. package/src/modes/DESIGN.md +51 -0
  298. package/src/modes/acp/acp-agent.ts +10 -1
  299. package/src/modes/acp/permission-mode.ts +18 -1
  300. package/src/modes/components/agent-dashboard.ts +20 -4
  301. package/src/modes/components/assistant-message.ts +55 -1
  302. package/src/modes/components/customization/customization-dashboard.ts +7 -0
  303. package/src/modes/components/customization/import-wizard.ts +29 -3
  304. package/src/modes/components/model-selector.ts +157 -103
  305. package/src/modes/components/settings-selector.ts +103 -37
  306. package/src/modes/components/welcome.ts +3 -1
  307. package/src/modes/controllers/command-controller.ts +300 -9
  308. package/src/modes/controllers/event-controller.ts +1 -1
  309. package/src/modes/controllers/extension-ui-controller.ts +31 -1
  310. package/src/modes/controllers/goal-mode-controller.ts +79 -10
  311. package/src/modes/controllers/input-controller.ts +2 -0
  312. package/src/modes/controllers/plan-mode-controller.ts +66 -11
  313. package/src/modes/controllers/runtime-mcp-command-controller.ts +7 -6
  314. package/src/modes/controllers/selector-controller.ts +76 -7
  315. package/src/modes/interactive-mode.ts +123 -4
  316. package/src/modes/prompt-suggestion-controller.ts +1 -1
  317. package/src/modes/runtime-init.ts +5 -1
  318. package/src/modes/theme/theme.ts +15 -0
  319. package/src/modes/utils/host-status.ts +21 -10
  320. package/src/prompts/agent-fragments/browser-aside.md +2 -2
  321. package/src/prompts/system/irc-incoming.md +3 -1
  322. package/src/prompts/tools/debug.md +1 -1
  323. package/src/prompts/tools/irc.md +1 -1
  324. package/src/prompts/tools/read.md +1 -1
  325. package/src/prompts/tools/report-issue.md +13 -0
  326. package/src/prompts/tools/task.md +1 -1
  327. package/src/runtime-credential-selector.ts +2 -2
  328. package/src/runtime-mcp/content-limits.ts +7 -0
  329. package/src/runtime-mcp/manager-pool.test.ts +5 -4
  330. package/src/runtime-mcp/manager.ts +40 -3
  331. package/src/runtime-mcp/oauth-flow.ts +32 -6
  332. package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
  333. package/src/runtime-mcp/project-host-values.ts +12 -8
  334. package/src/runtime-mcp/render.ts +16 -1
  335. package/src/runtime-mcp/tool-bridge.ts +194 -21
  336. package/src/runtime-mcp/transports/stdio.ts +2 -1
  337. package/src/sdk/broker/broker-exit.ts +10 -5
  338. package/src/sdk/broker/broker.ts +484 -85
  339. package/src/sdk/broker/daemon-entry.ts +338 -116
  340. package/src/sdk/broker/doctor-restart.ts +2 -1
  341. package/src/sdk/broker/ensure.ts +1214 -268
  342. package/src/sdk/broker/hop.ts +286 -0
  343. package/src/sdk/broker/lifecycle-ledger.ts +38 -11
  344. package/src/sdk/broker/lifecycle.ts +102 -6
  345. package/src/sdk/broker/lock-host-identity.ts +29 -0
  346. package/src/sdk/broker/session-index.ts +91 -16
  347. package/src/sdk/broker/transport.ts +17 -1
  348. package/src/sdk/bus/chat-command-policy.ts +16 -3
  349. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  350. package/src/sdk/bus/index.ts +460 -35
  351. package/src/sdk/bus/reconciliation-store.ts +201 -8
  352. package/src/sdk/bus/session-control.ts +2 -0
  353. package/src/sdk/bus/slack-daemon.ts +105 -9
  354. package/src/sdk/bus/telegram-daemon-contract.ts +9 -1
  355. package/src/sdk/bus/telegram-daemon.ts +10 -2
  356. package/src/sdk/bus/threaded-render.ts +20 -1
  357. package/src/sdk/cli/session-cli.ts +23 -6
  358. package/src/sdk/host/control/dispatch.ts +13 -1
  359. package/src/sdk/host/control/operations.ts +10 -1
  360. package/src/sdk/host/events.ts +67 -4
  361. package/src/sdk/host/host.ts +8 -2
  362. package/src/sdk/host/prompt-image-upload.ts +438 -0
  363. package/src/sdk/host/sdk-surface-parity.test.ts +15 -0
  364. package/src/sdk/host/session-runtime.test.ts +1737 -129
  365. package/src/sdk/host/session-runtime.ts +684 -83
  366. package/src/sdk/host/surface-policy.ts +4 -0
  367. package/src/sdk/host/websocket-transport.lifecycle.test.ts +90 -2
  368. package/src/sdk/host/websocket-transport.ts +19 -7
  369. package/src/sdk/lifecycle/service.ts +15 -1
  370. package/src/sdk/prompt-deadline-flush.ts +78 -5
  371. package/src/sdk/prompt-deadline-manager.ts +68 -14
  372. package/src/sdk/prompt-status.ts +6 -4
  373. package/src/sdk/protocol/adapter-validation.ts +81 -12
  374. package/src/sdk/protocol/operation-inventory.generated.json +261 -2
  375. package/src/sdk/protocol/operation-registry.ts +33 -3
  376. package/src/sdk/reconciliation-extensions.ts +1 -0
  377. package/src/sdk/session-list.ts +1 -0
  378. package/src/sdk/session.ts +237 -97
  379. package/src/session/agent-session.ts +2726 -479
  380. package/src/session/history-storage.ts +182 -12
  381. package/src/session/internal/managed-session-scope.ts +173 -57
  382. package/src/session/internal/managed-session-storage.ts +85 -12
  383. package/src/session/internal/native-publish-outcome.ts +5 -1
  384. package/src/session/messages.ts +47 -6
  385. package/src/session/session-manager.ts +326 -19
  386. package/src/session/startup-auth-config.ts +116 -8
  387. package/src/session/streaming-output.ts +262 -4
  388. package/src/session/terminal-abort.ts +14 -2
  389. package/src/session-import/redact.ts +53 -2
  390. package/src/session-import/service.ts +1 -0
  391. package/src/skill-state/workflow-mutation-guard.ts +2145 -206
  392. package/src/slash-commands/builtin-registry.ts +21 -6
  393. package/src/slash-commands/helpers/credential-switch.ts +10 -5
  394. package/src/slash-commands/helpers/mcp.ts +11 -3
  395. package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
  396. package/src/ssh/ssh-executor.ts +9 -2
  397. package/src/stt/recorder.ts +26 -9
  398. package/src/system-prompt.ts +61 -16
  399. package/src/task/executor.ts +115 -20
  400. package/src/task/index.ts +389 -175
  401. package/src/task/role-body.ts +84 -0
  402. package/src/task/token-log-mode.test.ts +162 -0
  403. package/src/task/token-log.ts +91 -2
  404. package/src/tools/archive-reader.ts +650 -37
  405. package/src/tools/ask.ts +1 -0
  406. package/src/tools/ast-edit-write-path.ts +64 -0
  407. package/src/tools/ast-edit.ts +18 -1
  408. package/src/tools/ast-grep.ts +7 -2
  409. package/src/tools/atomic-file-write.ts +46 -15
  410. package/src/tools/auto-generated-guard.ts +15 -3
  411. package/src/tools/awaiting-input.ts +114 -0
  412. package/src/tools/bash-allowed-prefixes.ts +214 -6
  413. package/src/tools/bash-interactive.ts +14 -2
  414. package/src/tools/bash-skill-urls.ts +58 -5
  415. package/src/tools/bash.ts +113 -26
  416. package/src/tools/browser/tab-worker.ts +39 -13
  417. package/src/tools/browser.ts +17 -7
  418. package/src/tools/cron.ts +10 -1
  419. package/src/tools/debug.ts +16 -8
  420. package/src/tools/descriptors.test.ts +44 -0
  421. package/src/tools/descriptors.ts +50 -6
  422. package/src/tools/eval.ts +15 -0
  423. package/src/tools/fetch.ts +93 -4
  424. package/src/tools/gh.ts +27 -12
  425. package/src/tools/image-gen.ts +20 -6
  426. package/src/tools/index.ts +2 -0
  427. package/src/tools/irc.ts +5 -3
  428. package/src/tools/monitor.ts +9 -1
  429. package/src/tools/output-meta.ts +74 -5
  430. package/src/tools/python.ts +1 -1
  431. package/src/tools/read.ts +26 -37
  432. package/src/tools/recipe/runner.ts +23 -12
  433. package/src/tools/render-utils.ts +2 -2
  434. package/src/tools/report-issue.ts +184 -0
  435. package/src/tools/search.ts +3 -2
  436. package/src/tools/ssh.ts +274 -8
  437. package/src/tools/subagent-render.ts +114 -12
  438. package/src/tools/subagent.ts +118 -5
  439. package/src/tools/tmux-self-injection-guard.ts +3301 -122
  440. package/src/tools/todo-write.ts +41 -3
  441. package/src/tools/tool-catalog.generated.ts +32 -4
  442. package/src/tools/ultragoal-ask-guard.ts +13 -1
  443. package/src/tools/write.ts +42 -3
  444. package/src/tui/tree-list.ts +15 -1
  445. package/src/utils/commit-message-generator.ts +12 -4
  446. package/src/utils/external-editor.ts +21 -7
  447. package/src/utils/file-mentions.ts +75 -7
  448. package/src/utils/git.ts +38 -7
  449. package/src/utils/image-limits.ts +8 -0
  450. package/src/utils/image-loading.ts +1 -1
  451. package/src/utils/open.ts +73 -4
  452. package/src/utils/pasted-image-loading.ts +9 -8
  453. package/src/utils/prompt-suggestion.ts +5 -4
  454. package/src/utils/shell-snapshot.ts +9 -1
  455. package/src/utils/title-generator.ts +72 -22
  456. package/src/web/scrapers/index.ts +3 -1
  457. package/src/web/scrapers/types.ts +8 -0
  458. package/src/web/scrapers/youtube.ts +3 -2
  459. package/src/web/search/index.ts +2 -1
  460. package/src/web/search/providers/codex.ts +29 -32
  461. package/src/web/search/providers/insane.ts +91 -28
  462. package/src/web/search/providers/searxng.ts +62 -10
@@ -670,11 +670,22 @@ export interface ReconciliationStore {
670
670
  delete(): Promise<void>;
671
671
  }
672
672
 
673
+ export interface ReconciliationStoreInstrumentationEvent {
674
+ at: number;
675
+ phase: "enqueued" | "started" | "completed" | "failed";
676
+ operation?: string;
677
+ substep?: string;
678
+ error?: string;
679
+ /** Detailed information about lock acquisition, promise identity, db state, etc. */
680
+ detail?: string;
681
+ }
682
+
673
683
  export function createReconciliationStore(options: {
674
684
  sessionFile: string | null | undefined;
675
685
  sessionId: string;
676
686
  fs?: ReconciliationStoreFs;
677
687
  now?: () => number;
688
+ onInstrumentationForTests?: (event: ReconciliationStoreInstrumentationEvent) => void;
678
689
  }): ReconciliationStore {
679
690
  const fileFs = options.fs ?? nodeFs;
680
691
  const now = options.now ?? Date.now;
@@ -701,20 +712,56 @@ export function createReconciliationStore(options: {
701
712
  const directory = path.dirname(filePath);
702
713
  let temporary: string | undefined;
703
714
  try {
715
+ try {
716
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "started", substep: "mkdir" });
717
+ } catch {}
704
718
  await fileFs.mkdir(directory, { recursive: true, mode: 0o700 });
719
+ try {
720
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "completed", substep: "mkdir" });
721
+ } catch {}
705
722
  temporary = `${filePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;
723
+ try {
724
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "started", substep: "writeFile" });
725
+ } catch {}
706
726
  await fileFs.writeFile(temporary, `${JSON.stringify(document)}\n`, { mode: 0o600 });
707
727
  try {
728
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "completed", substep: "writeFile" });
729
+ } catch {}
730
+ try {
731
+ try {
732
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "started", substep: "open" });
733
+ } catch {}
708
734
  const handle = await fileFs.open(temporary, "r+");
709
735
  try {
736
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "completed", substep: "open" });
737
+ } catch {}
738
+ try {
739
+ try {
740
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "started", substep: "sync" });
741
+ } catch {}
710
742
  await handle.sync();
743
+ try {
744
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "completed", substep: "sync" });
745
+ } catch {}
711
746
  } finally {
747
+ try {
748
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "started", substep: "close" });
749
+ } catch {}
712
750
  await handle.close();
751
+ try {
752
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "completed", substep: "close" });
753
+ } catch {}
713
754
  }
714
755
  } catch {
715
756
  // fsync optional on some fs seams
716
757
  }
758
+ try {
759
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "started", substep: "rename" });
760
+ } catch {}
717
761
  await fileFs.rename(temporary, filePath);
762
+ try {
763
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "completed", substep: "rename" });
764
+ } catch {}
718
765
  } catch (error) {
719
766
  // Every persistence-path failure (mkdir included) is evidence a drained
720
767
  // window must surface, never silently treat as quiescent (#4743).
@@ -723,6 +770,9 @@ export function createReconciliationStore(options: {
723
770
  code: "reconciliation_persist_failed",
724
771
  });
725
772
  unreportedPersistFailures.push(coded);
773
+ try {
774
+ options.onInstrumentationForTests?.({ at: Date.now(), phase: "failed", error: coded.message });
775
+ } catch {}
726
776
  throw coded;
727
777
  }
728
778
  };
@@ -795,7 +845,26 @@ export function createReconciliationStore(options: {
795
845
  const transact = async (
796
846
  mutator: (records: DurableReconciliationRecord[]) => DurableReconciliationRecord[],
797
847
  ): Promise<void> => {
848
+ const promiseId = `reconcil-transact-${randomUUID().slice(0, 8)}`;
849
+ const enqueueTime = Date.now();
798
850
  const run = async () => {
851
+ const lockWaitMs = Date.now() - enqueueTime;
852
+ try {
853
+ options.onInstrumentationForTests?.({
854
+ at: enqueueTime,
855
+ phase: "enqueued",
856
+ operation: "transact",
857
+ detail: `promise=${promiseId}`,
858
+ });
859
+ } catch {}
860
+ try {
861
+ options.onInstrumentationForTests?.({
862
+ at: Date.now(),
863
+ phase: "started",
864
+ operation: "transact",
865
+ detail: `promise=${promiseId} lock-wait=${lockWaitMs}ms`,
866
+ });
867
+ } catch {}
799
868
  const next = mutator(memory.map(r => ({ ...r })));
800
869
  await writeAtomic({
801
870
  version: RECONCILIATION_STORE_VERSION,
@@ -805,19 +874,55 @@ export function createReconciliationStore(options: {
805
874
  ...(terminalKeyMemory.length > 0 ? { evictedTerminalKeys: terminalKeyMemory } : {}),
806
875
  });
807
876
  memory = next;
877
+ try {
878
+ options.onInstrumentationForTests?.({
879
+ at: Date.now(),
880
+ phase: "completed",
881
+ operation: "transact",
882
+ detail: `promise=${promiseId}`,
883
+ });
884
+ } catch {}
808
885
  };
809
886
  const pending = chain.then(run, run);
810
- chain = pending.then(
887
+ const settled = pending.then(
811
888
  () => undefined,
812
889
  () => undefined,
813
890
  );
814
- await pending;
891
+ chain = settled;
892
+ try {
893
+ await pending;
894
+ } catch (error) {
895
+ try {
896
+ options.onInstrumentationForTests?.({
897
+ at: Date.now(),
898
+ phase: "failed",
899
+ operation: "transact",
900
+ detail: `promise=${promiseId} lock-wait=${Date.now() - enqueueTime}ms`,
901
+ error: error instanceof Error ? error.message : String(error),
902
+ });
903
+ } catch {}
904
+ throw error;
905
+ }
815
906
  };
816
907
 
817
908
  const transactTerminalScopes = async (
818
909
  mutator: (scopes: DurableTerminalScopeRecord[]) => DurableTerminalScopeRecord[],
819
910
  ): Promise<void> => {
820
911
  const run = async () => {
912
+ try {
913
+ options.onInstrumentationForTests?.({
914
+ at: Date.now(),
915
+ phase: "enqueued",
916
+ operation: "transactTerminalScopes",
917
+ });
918
+ } catch {}
919
+ try {
920
+ options.onInstrumentationForTests?.({
921
+ at: Date.now(),
922
+ phase: "started",
923
+ operation: "transactTerminalScopes",
924
+ });
925
+ } catch {}
821
926
  const next = mutator(terminalMemory.map(s => ({ ...s })));
822
927
  await writeAtomic({
823
928
  version: RECONCILIATION_STORE_VERSION,
@@ -827,13 +932,33 @@ export function createReconciliationStore(options: {
827
932
  ...(terminalKeyMemory.length > 0 ? { evictedTerminalKeys: terminalKeyMemory } : {}),
828
933
  });
829
934
  terminalMemory = next;
935
+ try {
936
+ options.onInstrumentationForTests?.({
937
+ at: Date.now(),
938
+ phase: "completed",
939
+ operation: "transactTerminalScopes",
940
+ });
941
+ } catch {}
830
942
  };
831
943
  const pending = chain.then(run, run);
832
- chain = pending.then(
944
+ const settled = pending.then(
833
945
  () => undefined,
834
946
  () => undefined,
835
947
  );
836
- await pending;
948
+ chain = settled;
949
+ try {
950
+ await pending;
951
+ } catch (error) {
952
+ try {
953
+ options.onInstrumentationForTests?.({
954
+ at: Date.now(),
955
+ phase: "failed",
956
+ operation: "transactTerminalScopes",
957
+ error: error instanceof Error ? error.message : String(error),
958
+ });
959
+ } catch {}
960
+ throw error;
961
+ }
837
962
  };
838
963
 
839
964
  const transactTerminalState = async (
@@ -843,6 +968,20 @@ export function createReconciliationStore(options: {
843
968
  },
844
969
  ): Promise<void> => {
845
970
  const run = async () => {
971
+ try {
972
+ options.onInstrumentationForTests?.({
973
+ at: Date.now(),
974
+ phase: "enqueued",
975
+ operation: "transactTerminalState",
976
+ });
977
+ } catch {}
978
+ try {
979
+ options.onInstrumentationForTests?.({
980
+ at: Date.now(),
981
+ phase: "started",
982
+ operation: "transactTerminalState",
983
+ });
984
+ } catch {}
846
985
  const next = mutator({
847
986
  scopes: terminalMemory.map(s => ({ ...s })),
848
987
  keys: terminalKeyMemory.map(k => ({ ...k })),
@@ -856,19 +995,53 @@ export function createReconciliationStore(options: {
856
995
  });
857
996
  terminalMemory = next.scopes;
858
997
  terminalKeyMemory = next.keys;
998
+ try {
999
+ options.onInstrumentationForTests?.({
1000
+ at: Date.now(),
1001
+ phase: "completed",
1002
+ operation: "transactTerminalState",
1003
+ });
1004
+ } catch {}
859
1005
  };
860
1006
  const pending = chain.then(run, run);
861
- chain = pending.then(
1007
+ const settled = pending.then(
862
1008
  () => undefined,
863
1009
  () => undefined,
864
1010
  );
865
- await pending;
1011
+ chain = settled;
1012
+ try {
1013
+ await pending;
1014
+ } catch (error) {
1015
+ try {
1016
+ options.onInstrumentationForTests?.({
1017
+ at: Date.now(),
1018
+ phase: "failed",
1019
+ operation: "transactTerminalState",
1020
+ error: error instanceof Error ? error.message : String(error),
1021
+ });
1022
+ } catch {}
1023
+ throw error;
1024
+ }
866
1025
  };
867
1026
 
868
1027
  const transactTerminalKeys = async (
869
1028
  mutator: (keys: EvictedTerminalKeyEntry[]) => EvictedTerminalKeyEntry[],
870
1029
  ): Promise<void> => {
871
1030
  const run = async () => {
1031
+ try {
1032
+ options.onInstrumentationForTests?.({
1033
+ at: Date.now(),
1034
+ phase: "enqueued",
1035
+ operation: "transactTerminalKeys",
1036
+ });
1037
+ } catch {}
1038
+ try {
1039
+ options.onInstrumentationForTests?.({
1040
+ at: Date.now(),
1041
+ phase: "started",
1042
+ operation: "transactTerminalKeys",
1043
+ });
1044
+ } catch {}
872
1045
  const next = mutator(terminalKeyMemory.map(k => ({ ...k })));
873
1046
  await writeAtomic({
874
1047
  version: RECONCILIATION_STORE_VERSION,
@@ -878,13 +1051,33 @@ export function createReconciliationStore(options: {
878
1051
  ...(next.length > 0 ? { evictedTerminalKeys: next } : {}),
879
1052
  });
880
1053
  terminalKeyMemory = next;
1054
+ try {
1055
+ options.onInstrumentationForTests?.({
1056
+ at: Date.now(),
1057
+ phase: "completed",
1058
+ operation: "transactTerminalKeys",
1059
+ });
1060
+ } catch {}
881
1061
  };
882
1062
  const pending = chain.then(run, run);
883
- chain = pending.then(
1063
+ const settled = pending.then(
884
1064
  () => undefined,
885
1065
  () => undefined,
886
1066
  );
887
- await pending;
1067
+ chain = settled;
1068
+ try {
1069
+ await pending;
1070
+ } catch (error) {
1071
+ try {
1072
+ options.onInstrumentationForTests?.({
1073
+ at: Date.now(),
1074
+ phase: "failed",
1075
+ operation: "transactTerminalKeys",
1076
+ error: error instanceof Error ? error.message : String(error),
1077
+ });
1078
+ } catch {}
1079
+ throw error;
1080
+ }
888
1081
  };
889
1082
 
890
1083
  const deleteStore = async (): Promise<void> => {
@@ -1,3 +1,4 @@
1
+ import { setSessionOutboundRedact } from "../host/events";
1
2
  import {
2
3
  type GenericNotificationSessionSource,
3
4
  getCurrentTelegramActivationMarker,
@@ -480,6 +481,7 @@ export class NotificationSessionController {
480
481
  policy: Omit<NotificationRuntimePolicy, "mode">,
481
482
  mode: NotificationRuntimePolicy["mode"],
482
483
  ): void {
484
+ setSessionOutboundRedact(binding.sessionId, policy.redact);
483
485
  runtime?.refreshPolicy?.(binding, { ...policy, mode });
484
486
  }
485
487
 
@@ -58,6 +58,7 @@ function slackPublicationClientMsgId(publicationId: string): string {
58
58
 
59
59
  // Durable filesystem publication leases must outlast one event-loop and persistence turn.
60
60
  const MIN_PUBLICATION_LEASE_MS = 100;
61
+ const ROOT_PUBLICATION_POLL_MS = 50;
61
62
  const INBOUND_REACTION_DEADLINE_MS = 5_000;
62
63
  const RETIREMENT_DRAIN_MS = 5_000;
63
64
  const INBOUND_REACTION = "eyes";
@@ -800,6 +801,7 @@ export class SlackNotificationDaemon {
800
801
  endpointGeneration?: number,
801
802
  requestedClientMsgId?: string,
802
803
  ): Promise<SlackRootPublication> {
804
+ const lifecycleGeneration = this.#lifecycleGeneration;
803
805
  const endpoint = await this.#resolveAttachment(sessionId);
804
806
  if (!endpoint || (endpointGeneration !== undefined && endpoint.generation !== endpointGeneration))
805
807
  throw new SlackEndpointBindingError("Slack root publication requires the current session endpoint.");
@@ -816,7 +818,14 @@ export class SlackNotificationDaemon {
816
818
  )
817
819
  return current;
818
820
  if (current?.state === "posting_root") {
819
- if (current.rootPublicationOwner === this.#publicationOwnerId) return current;
821
+ // A live lease of our own belongs to an in-flight post; an expired one is
822
+ // reclaimed under a new fence exactly like a crashed peer's, otherwise the
823
+ // root waiter would re-enter postRoot forever.
824
+ if (
825
+ current.rootPublicationOwner === this.#publicationOwnerId &&
826
+ !this.#leaseExpired(current.rootPublicationLeaseExpiresAt, now)
827
+ )
828
+ return current;
820
829
  claimed = true;
821
830
  return nextRecord(current, {
822
831
  rootPublicationOwner: this.#publicationOwnerId,
@@ -859,7 +868,17 @@ export class SlackNotificationDaemon {
859
868
  }
860
869
  if (!pending?.clientMsgId) throw new Error("Unable to persist Slack root post intent");
861
870
  if (!claimed)
862
- return { conversation: await this.#waitForRoot(pendingKey, sessionId, body, generation), created: false };
871
+ return {
872
+ conversation: await this.#waitForRoot(
873
+ pendingKey,
874
+ sessionId,
875
+ body,
876
+ generation,
877
+ lifecycleGeneration,
878
+ endpoint.authorityId,
879
+ ),
880
+ created: false,
881
+ };
863
882
  if (pending.endpointGeneration !== generation) throw new SlackEndpointBindingError();
864
883
  const clientMsgId = pending.clientMsgId;
865
884
  const fence = pending.rootPublicationFence;
@@ -907,7 +926,7 @@ export class SlackNotificationDaemon {
907
926
  // dispatch; resume performs any required replacement after reconciliation.
908
927
  const active = await this.store.transact(pendingKey, current => {
909
928
  if (
910
- !current ||
929
+ current?.state !== "posting_root" ||
911
930
  current.clientMsgId !== clientMsgId ||
912
931
  current.rootPublicationOwner !== this.#publicationOwnerId ||
913
932
  current.rootPublicationFence !== fence
@@ -926,7 +945,17 @@ export class SlackNotificationDaemon {
926
945
  });
927
946
  if (!active) throw new Error("Slack root mapping disappeared");
928
947
  if (active.state !== "active")
929
- return { conversation: await this.#waitForRoot(pendingKey, sessionId, body, generation), created: false };
948
+ return {
949
+ conversation: await this.#waitForRoot(
950
+ pendingKey,
951
+ sessionId,
952
+ body,
953
+ generation,
954
+ lifecycleGeneration,
955
+ endpoint.authorityId,
956
+ ),
957
+ created: false,
958
+ };
930
959
  return { conversation: active, created: createdRootEffect };
931
960
  }
932
961
 
@@ -1267,8 +1296,12 @@ export class SlackNotificationDaemon {
1267
1296
  )
1268
1297
  return record;
1269
1298
  inboundDispatches = [...(record.inboundDispatches ?? [])];
1299
+ // Fence the publisher before an abort-ignoring provider can renew or reactivate this mapping.
1270
1300
  return nextRecord(record, {
1271
1301
  state: "closed_marker",
1302
+ rootPublicationOwner: undefined,
1303
+ rootPublicationLeaseExpiresAt: undefined,
1304
+ rootPublicationFence: (record.rootPublicationFence ?? 0) + 1,
1272
1305
  pendingActionId: undefined,
1273
1306
  cleanupEffectId: undefined,
1274
1307
  inboundDispatches: [],
@@ -3105,7 +3138,7 @@ export class SlackNotificationDaemon {
3105
3138
  let renewed = false;
3106
3139
  await this.store.transact(key, current => {
3107
3140
  if (
3108
- !current ||
3141
+ current?.state !== "posting_root" ||
3109
3142
  current.clientMsgId !== clientMsgId ||
3110
3143
  current.rootPublicationOwner !== this.#publicationOwnerId ||
3111
3144
  current.rootPublicationFence !== fence
@@ -3269,18 +3302,82 @@ export class SlackNotificationDaemon {
3269
3302
  sessionId: string,
3270
3303
  body: string,
3271
3304
  endpointGeneration: number,
3305
+ lifecycleGeneration: number,
3306
+ attachmentAuthorityId?: string,
3272
3307
  ): Promise<SlackConversation> {
3273
- for (let attempt = 0; attempt < 100; attempt++) {
3274
- await Bun.sleep(10);
3308
+ // Another owner may renew this lease while provider work is active, so wait for the durable transition.
3309
+ while (true) {
3310
+ if (lifecycleGeneration !== this.#lifecycleGeneration)
3311
+ throw new Error("Slack daemon stopped while waiting for root publication");
3312
+ await Bun.sleep(ROOT_PUBLICATION_POLL_MS);
3313
+ if (lifecycleGeneration !== this.#lifecycleGeneration)
3314
+ throw new Error("Slack daemon stopped while waiting for root publication");
3275
3315
  const current = await this.store.read(key);
3316
+ if (lifecycleGeneration !== this.#lifecycleGeneration)
3317
+ throw new Error("Slack daemon stopped while waiting for root publication");
3276
3318
  if (current?.state === "active") {
3277
3319
  const currentGeneration = this.#requireEndpointGeneration(current);
3278
- if (currentGeneration === endpointGeneration) return current;
3320
+ if (currentGeneration === endpointGeneration) {
3321
+ const endpoint = await this.#resolveAttachment(sessionId);
3322
+ if (lifecycleGeneration !== this.#lifecycleGeneration)
3323
+ throw new Error("Slack daemon stopped while waiting for root publication");
3324
+ if (
3325
+ !endpoint?.isCurrent() ||
3326
+ endpoint.sessionId !== sessionId ||
3327
+ endpoint.generation !== endpointGeneration ||
3328
+ endpoint.authorityId !== attachmentAuthorityId ||
3329
+ current.attachmentAuthorityId !== attachmentAuthorityId
3330
+ )
3331
+ throw new SlackEndpointBindingError("Slack root publication was retired before completion.");
3332
+ return current;
3333
+ }
3279
3334
  if (currentGeneration > endpointGeneration)
3280
3335
  throw new SlackEndpointBindingError("Slack root belongs to a newer endpoint generation.");
3281
3336
  return await this.resume(sessionId, body, endpointGeneration);
3282
3337
  }
3338
+ if (current?.state === "closed_marker") {
3339
+ const currentGeneration = this.#requireEndpointGeneration(current);
3340
+ if (currentGeneration > endpointGeneration)
3341
+ throw new SlackEndpointBindingError("Slack root belongs to a newer endpoint generation.");
3342
+ const endpoint = await this.#resolveAttachment(sessionId);
3343
+ if (lifecycleGeneration !== this.#lifecycleGeneration)
3344
+ throw new Error("Slack daemon stopped while waiting for root publication");
3345
+ if (
3346
+ !endpoint?.isCurrent() ||
3347
+ endpoint.sessionId !== sessionId ||
3348
+ endpoint.generation !== endpointGeneration ||
3349
+ endpoint.authorityId !== attachmentAuthorityId
3350
+ )
3351
+ throw new SlackEndpointBindingError("Slack root publication was retired before completion.");
3352
+ if (currentGeneration === endpointGeneration) {
3353
+ if (!current.rootTs)
3354
+ throw new SlackEndpointBindingError("Slack root publication was retired before completion.");
3355
+ if (
3356
+ current.rootPublicationOwner !== undefined &&
3357
+ !this.#leaseExpired(current.rootPublicationLeaseExpiresAt, this.#now())
3358
+ )
3359
+ continue;
3360
+ return await this.postRoot(sessionId, body, endpointGeneration);
3361
+ }
3362
+ if (
3363
+ current.rootPublicationOwner !== undefined &&
3364
+ !this.#leaseExpired(current.rootPublicationLeaseExpiresAt, this.#now())
3365
+ )
3366
+ continue;
3367
+ return await this.resume(sessionId, body, endpointGeneration);
3368
+ }
3369
+ if (current?.state === "resumed_root") {
3370
+ const currentGeneration = this.#requireEndpointGeneration(current);
3371
+ if (currentGeneration > endpointGeneration)
3372
+ throw new SlackEndpointBindingError("Slack root belongs to a newer endpoint generation.");
3373
+ if (
3374
+ current.rootPublicationOwner === undefined ||
3375
+ this.#leaseExpired(current.rootPublicationLeaseExpiresAt, this.#now())
3376
+ )
3377
+ return await this.resume(sessionId, body, endpointGeneration);
3378
+ }
3283
3379
  if (
3380
+ current === undefined ||
3284
3381
  current?.state === "error" ||
3285
3382
  (current?.state === "posting_root" &&
3286
3383
  this.#leaseExpired(current.rootPublicationLeaseExpiresAt, this.#now())) ||
@@ -3291,7 +3388,6 @@ export class SlackNotificationDaemon {
3291
3388
  return await this.postRoot(sessionId, body, endpointGeneration);
3292
3389
  }
3293
3390
  }
3294
- throw new Error("Slack root post is still pending");
3295
3391
  }
3296
3392
 
3297
3393
  async #waitForAction(key: string, sessionId: string, body: string, actionId: string): Promise<SlackConversation> {
@@ -301,8 +301,16 @@ export const SDK_LIFECYCLE_ROUTER_PROTOCOL_VERSION = 1;
301
301
  * Generation 202 joins queued-removal terminal publication before ordinary
302
302
  * abort acknowledgement, replacing owners that still acknowledge cancellation
303
303
  * before its terminal record is durable.
304
+ * Generation 203 replaces owners that still treat a project `.gjc` file as an
305
+ * explicit deadline-autosave opt-in for a primary checkout.
306
+ * Generation 205 replaces owners whose process descendant walk can adopt
307
+ * children of a recycled PID. Generation 206 verifies macOS descendant
308
+ * identities and parentage before retaining PTY termination authority, and
309
+ * reaps adopted Linux PTY descendants when GJC is a child reaper.
310
+ * Generation 209 installs connection-owned private SDK image staging with
311
+ * execution-owned reservations, replacing hosts without that lifecycle contract.
304
312
  */
305
- export const DAEMON_GENERATION = 202;
313
+ export const DAEMON_GENERATION = 209;
306
314
 
307
315
  /**
308
316
  * Serving-compatibility boundary for daemon lifecycle requests. Epoch 7
@@ -302,6 +302,8 @@ export const ASK_SELECTED_ACK_CAPABILITY = "ask_selected_ack_v1";
302
302
  export const ASK_CONTROLS_CAPABILITY = "ask_controls_v1";
303
303
  /** Capability for the closed tool phase set: started, completed, failed, and cancelled. */
304
304
  export const TOOL_ACTIVITY_CAPABILITY = "tool_activity_v2";
305
+ /** Receive content-free notifications when a running command needs host-side authentication. */
306
+ export const AWAITING_INPUT_CAPABILITY = "awaiting_input_v1";
305
307
  /** Receive-only compatibility capability for pre-v2 hosts. */
306
308
  export const LEGACY_TOOL_ACTIVITY_CAPABILITY = "tool_activity_v1";
307
309
  /** Public `sdk/bus/telegram-daemon` path for the canonical `sdk/host` capability token. */
@@ -5428,6 +5430,7 @@ export class TelegramNotificationDaemon {
5428
5430
  ASK_CONTROLS_CAPABILITY,
5429
5431
  ASK_SELECTED_ACK_CAPABILITY,
5430
5432
  TOOL_ACTIVITY_CAPABILITY,
5433
+ AWAITING_INPUT_CAPABILITY,
5431
5434
  LEGACY_TOOL_ACTIVITY_CAPABILITY,
5432
5435
  POSITIONED_NOTIFICATION_EFFECTS_CAPABILITY,
5433
5436
  "ephemeral_turn_v1",
@@ -7255,6 +7258,7 @@ export class TelegramNotificationDaemon {
7255
7258
  "config_update",
7256
7259
  "control_command_result",
7257
7260
  "tool_activity",
7261
+ "awaiting_input",
7258
7262
  "reasoning_summary",
7259
7263
  ]);
7260
7264
 
@@ -10874,8 +10878,12 @@ export class TelegramNotificationDaemon {
10874
10878
  this.failLegacyToolStart(toolActivity);
10875
10879
  await this.#failPublicationPreSend(publicationId, "topic authority is inactive or malformed");
10876
10880
  }
10881
+ const flatSend =
10882
+ threadedFrame.type === "awaiting_input"
10883
+ ? { ...send, text: `${send.text} · ${sessionTag(logicalSessionId)}` }
10884
+ : send;
10877
10885
  if (!send.identity && !existingTopic && !this.flatIdentitySent.has(logicalSessionId)) {
10878
- await this.deliverFlatFallback(logicalSessionId, send, toolActivity, socketLease, publicationId);
10886
+ await this.deliverFlatFallback(logicalSessionId, flatSend, toolActivity, socketLease, publicationId);
10879
10887
  return;
10880
10888
  }
10881
10889
  const topicId =
@@ -10896,7 +10904,7 @@ export class TelegramNotificationDaemon {
10896
10904
  abandonStaleToolStart();
10897
10905
  return;
10898
10906
  }
10899
- await this.deliverFlatFallback(logicalSessionId, send, toolActivity, socketLease, publicationId);
10907
+ await this.deliverFlatFallback(logicalSessionId, flatSend, toolActivity, socketLease, publicationId);
10900
10908
  return;
10901
10909
  }
10902
10910
  if (send.identity) {
@@ -2,7 +2,7 @@
2
2
  * Pure rendering of threaded-session frames into Telegram send specs.
3
3
  *
4
4
  * The daemon receives the additive `ServerMessage` frames (identity_header,
5
- * context_update, turn_stream, image_attachment, config_update) over the session
5
+ * context_update, turn_stream, image_attachment, config_update, awaiting_input) over the session
6
6
  * WS and must turn each into a Bot API call scoped to the session's forum topic
7
7
  * (`message_thread_id`), throttled through the shared rate-limit pool. This
8
8
  * module is the pure frame→send mapping (including the priority lane and live-
@@ -80,6 +80,7 @@ interface ThreadedFrame {
80
80
  // tool_activity
81
81
  toolCallId?: unknown;
82
82
  toolName?: unknown;
83
+ kind?: unknown;
83
84
  argsSummary?: unknown;
84
85
  resultSummary?: unknown;
85
86
  isError?: unknown;
@@ -261,6 +262,24 @@ export function renderThreadedFrame(frame: ThreadedFrame): ThreadedSend | undefi
261
262
  terminal: phase !== "started",
262
263
  };
263
264
  }
265
+ case "awaiting_input": {
266
+ const toolCallId = str(frame.toolCallId);
267
+ if (!toolCallId) return undefined;
268
+ let text: string;
269
+ switch (frame.kind) {
270
+ case "browser_auth":
271
+ text =
272
+ "⏳ A running command is waiting for browser sign-in. Finish it on the host; the agent continues when the command does.";
273
+ break;
274
+ case "device_code":
275
+ text =
276
+ "⏳ A running command is waiting for a device-code sign-in. Finish it on the host; the agent continues when the command does.";
277
+ break;
278
+ default:
279
+ return undefined;
280
+ }
281
+ return { method: "sendMessage", lane: "ask", text, coalesceKey: `awaiting:${toolCallId}` };
282
+ }
264
283
  case "reasoning_summary": {
265
284
  const text = str(frame.text);
266
285
  if (!text) return undefined;
@@ -258,17 +258,34 @@ function normalizeSessionFailure(error: unknown, args: SdkSessionCliArgs): Publi
258
258
  }
259
259
 
260
260
  /** Lifecycle terminality/retryability is not, by itself, proof of an effect outcome. */
261
+ /**
262
+ * Lifecycle codes the broker produces when it refuses the request payload itself. Input shape is
263
+ decided before the request can be dispatched, and an outcome the broker cannot establish comes
264
+ back as `terminal_uncertain` instead, so these codes never stand for an applied operation. They
265
+ still collapse into `operation_failed` below, which cannot say why the request was refused, so
266
+ the refusal class survives as one fixed diagnostic.
267
+ */
268
+ const LIFECYCLE_INPUT_REFUSAL_CODES = new Set(["invalid_input", "invalid_request"]);
269
+
261
270
  export function lifecyclePublicFailure(outcome: Extract<SessionLifecycleResult, { ok: false }>): PublicCommandFailure {
262
271
  const failure = sdkPublicFailure(outcome.error.code);
263
272
  // The service emits retryable protocol_error only when requestSent is explicitly false.
264
273
  const proof: PublicEffectProof =
265
274
  outcome.certainty === "retryable" && outcome.error.code === "protocol_error" ? "pre-send" : "unknown";
266
- // `operation_failed` cannot distinguish a conflict from any other failed operation, so
267
- // the conflict survives as one fixed diagnostic. The broker message itself is never
268
- // rendered: it may carry request keys, paths, or credentials, and its cause is not
269
- // decidable from the code alone.
275
+ // `operation_failed` cannot distinguish a conflict or an input refusal from any other failed
276
+ // operation, so each survives as one fixed diagnostic. The broker message itself is never
277
+ // rendered: it may carry request keys, paths, or credentials, and its cause is not decidable
278
+ // from the code alone.
279
+ let diagnostic: PublicCommandDiagnosticCode | undefined;
280
+ if (outcome.error.code === "idempotency_conflict") {
281
+ diagnostic = "lifecycle_idempotency_conflict";
282
+ } else if (outcome.error.code === "legacy_lifecycle_ambiguous") {
283
+ diagnostic = "lifecycle_legacy_history_ambiguous";
284
+ } else if (LIFECYCLE_INPUT_REFUSAL_CODES.has(outcome.error.code)) {
285
+ diagnostic = "lifecycle_input_refused";
286
+ }
270
287
  const diagnostics: readonly PublicCommandDiagnosticCode[] | undefined =
271
- outcome.error.code === "idempotency_conflict" ? ["lifecycle_idempotency_conflict"] : undefined;
288
+ diagnostic === undefined ? undefined : [diagnostic];
272
289
  return new PublicCommandFailure({
273
290
  ...failure.input,
274
291
  ...(diagnostics === undefined ? {} : { diagnostics }),
@@ -2209,7 +2226,7 @@ async function runRawControl(
2209
2226
  input: JsonRecord,
2210
2227
  args: SdkSessionCliArgs,
2211
2228
  ): Promise<unknown> {
2212
- const invalid = validateAdapterControl(operation, input);
2229
+ const invalid = validateAdapterControl(operation, input, { allowUltrafastTier: true });
2213
2230
  if (invalid) throw new SdkSessionCliError(invalid.code, invalid.message, 2);
2214
2231
  await ensureBroker({ agentDir });
2215
2232
  const operatorRequest = operatorAbortBrokerRequest(sessionId, operation, input, args);