@gajae-code/coding-agent 0.17.2 → 0.17.5

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 (390) hide show
  1. package/CHANGELOG.md +267 -0
  2. package/dist/types/cli/daemon-cli.d.ts +3 -1
  3. package/dist/types/cli/github-release.d.ts +17 -0
  4. package/dist/types/cli/public-command-entry.d.ts +56 -0
  5. package/dist/types/cli/public-command-errors.d.ts +126 -0
  6. package/dist/types/cli/public-command-evidence.d.ts +99 -0
  7. package/dist/types/cli/public-command-help.d.ts +65 -0
  8. package/dist/types/cli/public-command-registry.d.ts +69 -0
  9. package/dist/types/cli/session-picker.d.ts +1 -1
  10. package/dist/types/cli/setup-cli.d.ts +1 -0
  11. package/dist/types/cli/skills-cli.d.ts +5 -0
  12. package/dist/types/cli.d.ts +3 -0
  13. package/dist/types/commands/daemon.d.ts +4 -50
  14. package/dist/types/commands/sdk.d.ts +20 -37
  15. package/dist/types/commands/setup.d.ts +3 -0
  16. package/dist/types/commands/skills.d.ts +9 -0
  17. package/dist/types/config/autorouting-tier-map.d.ts +1049 -3
  18. package/dist/types/config/file-lock.d.ts +13 -3
  19. package/dist/types/config/model-profile-activation.d.ts +45 -1
  20. package/dist/types/config/model-registry.d.ts +14 -3
  21. package/dist/types/config/model-resolver.d.ts +1 -1
  22. package/dist/types/config/settings-schema.d.ts +11 -0
  23. package/dist/types/coordinator-mcp/question-state.d.ts +6 -1
  24. package/dist/types/daemon/operator-contract.d.ts +5 -1
  25. package/dist/types/eval/js/worker-protocol.d.ts +2 -0
  26. package/dist/types/exec/bash-executor.d.ts +2 -0
  27. package/dist/types/extensibility/extensions/types.d.ts +12 -0
  28. package/dist/types/extensibility/gjc-plugins/registry.d.ts +4 -0
  29. package/dist/types/extensibility/gjc-plugins/runtime-adapters.d.ts +11 -2
  30. package/dist/types/extensibility/runtime-skill-discovery.d.ts +18 -0
  31. package/dist/types/extensibility/shared-events.d.ts +3 -1
  32. package/dist/types/gjc-runtime/session-state-lock.d.ts +61 -0
  33. package/dist/types/gjc-runtime/state-writer.d.ts +14 -1
  34. package/dist/types/harness-control-plane/control-endpoint.d.ts +4 -1
  35. package/dist/types/harness-control-plane/finalize.d.ts +14 -3
  36. package/dist/types/internal-urls/embedded-protocol.d.ts +9 -0
  37. package/dist/types/internal-urls/index.d.ts +1 -0
  38. package/dist/types/internal-urls/parse.d.ts +9 -1
  39. package/dist/types/main.d.ts +23 -1
  40. package/dist/types/modes/acp/acp-agent.d.ts +55 -1
  41. package/dist/types/modes/acp/startup-provenance.d.ts +16 -0
  42. package/dist/types/modes/components/custom-provider-wizard.d.ts +19 -1
  43. package/dist/types/modes/components/session-selector.d.ts +5 -2
  44. package/dist/types/modes/components/user-message-selector.d.ts +5 -2
  45. package/dist/types/modes/controllers/command-controller.d.ts +1 -1
  46. package/dist/types/modes/controllers/selector-controller.d.ts +1 -1
  47. package/dist/types/modes/interactive-mode.d.ts +1 -1
  48. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +11 -1
  49. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +14 -1
  50. package/dist/types/modes/types.d.ts +2 -2
  51. package/dist/types/runtime/process-lifecycle.d.ts +2 -0
  52. package/dist/types/runtime-mcp/loader.d.ts +2 -0
  53. package/dist/types/runtime-mcp/manager.d.ts +69 -6
  54. package/dist/types/runtime-mcp/pool.d.ts +17 -0
  55. package/dist/types/runtime-mcp/redaction.d.ts +20 -0
  56. package/dist/types/runtime-mcp/startup-policy.d.ts +6 -0
  57. package/dist/types/runtime-mcp/tool-bridge.d.ts +9 -0
  58. package/dist/types/runtime-mcp/transports/http.d.ts +11 -0
  59. package/dist/types/sdk/broker/broker.d.ts +17 -4
  60. package/dist/types/sdk/broker/ensure.d.ts +3 -0
  61. package/dist/types/sdk/broker/identity.d.ts +5 -1
  62. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +23 -3
  63. package/dist/types/sdk/broker/lifecycle.d.ts +15 -8
  64. package/dist/types/sdk/broker/managed-task-dag.d.ts +1335 -0
  65. package/dist/types/sdk/broker/managed-task-verification.d.ts +37 -0
  66. package/dist/types/sdk/broker/runtime.d.ts +1 -1
  67. package/dist/types/sdk/broker/session-index.d.ts +22 -3
  68. package/dist/types/sdk/broker/spawn-authority.d.ts +12 -0
  69. package/dist/types/sdk/broker/startup-failure.d.ts +4 -0
  70. package/dist/types/sdk/broker/stderr-drainer.d.ts +13 -0
  71. package/dist/types/sdk/bus/index.d.ts +19 -0
  72. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +7 -1
  73. package/dist/types/sdk/bus/telegram-daemon.d.ts +5 -0
  74. package/dist/types/sdk/cli/master-cli.d.ts +6 -10
  75. package/dist/types/sdk/cli/rows.d.ts +19 -1
  76. package/dist/types/sdk/cli/session-cli.d.ts +22 -5
  77. package/dist/types/sdk/client/client.d.ts +2 -0
  78. package/dist/types/sdk/guides/cli.d.ts +3 -4
  79. package/dist/types/sdk/guides/verify.d.ts +2 -0
  80. package/dist/types/sdk/host/host.d.ts +9 -0
  81. package/dist/types/sdk/host/session-runtime.d.ts +31 -0
  82. package/dist/types/sdk/host/types.d.ts +10 -0
  83. package/dist/types/sdk/index.d.ts +1 -0
  84. package/dist/types/sdk/prompt-deadline-flush.d.ts +85 -0
  85. package/dist/types/sdk/prompt-deadline-manager.d.ts +37 -0
  86. package/dist/types/sdk/prompt-tool-boundary.d.ts +73 -0
  87. package/dist/types/sdk/router/session-router.d.ts +2 -0
  88. package/dist/types/sdk/session.d.ts +3 -3
  89. package/dist/types/sdk/startup-capability.d.ts +2 -0
  90. package/dist/types/sdk/transport/relay.d.ts +1 -0
  91. package/dist/types/sdk/transport/serve-cli.d.ts +48 -4
  92. package/dist/types/sdk/transport/stdio.d.ts +5 -1
  93. package/dist/types/session/agent-session.d.ts +175 -23
  94. package/dist/types/session/fallback-chain-controller.d.ts +6 -6
  95. package/dist/types/session/fold-coordinator.d.ts +17 -3
  96. package/dist/types/session/internal/managed-session-storage.d.ts +7 -1
  97. package/dist/types/session/session-manager.d.ts +64 -1
  98. package/dist/types/session/session-work-lease.d.ts +14 -0
  99. package/dist/types/setup/model-onboarding-guidance.d.ts +1 -1
  100. package/dist/types/setup/provider-onboarding.d.ts +81 -1
  101. package/dist/types/task/types.d.ts +2 -0
  102. package/dist/types/tools/bash-interactive.d.ts +1 -0
  103. package/dist/types/tools/bash.d.ts +37 -11
  104. package/dist/types/tools/fetch.d.ts +10 -1
  105. package/dist/types/tools/job.d.ts +1 -1
  106. package/dist/types/tools/steer-fold.d.ts +31 -0
  107. package/dist/types/tools/subagent.d.ts +8 -1
  108. package/dist/types/utils/git.d.ts +28 -2
  109. package/dist/types/utils/mupdf-embedded.d.ts +2 -0
  110. package/dist/types/utils/mupdf.d.ts +4 -0
  111. package/dist/types/utils/session-title-generation.d.ts +6 -0
  112. package/dist/types/utils/title-generator.d.ts +11 -2
  113. package/dist/types/web/scrapers/types.d.ts +3 -0
  114. package/package.json +18 -10
  115. package/scripts/build-binary.ts +9 -3
  116. package/scripts/compile-args.ts +0 -9
  117. package/scripts/embed-mupdf.ts +52 -0
  118. package/scripts/generate-sdk-operation-inventory.ts +31 -1
  119. package/scripts/vendor-markit.ts +196 -0
  120. package/src/async/job-manager.ts +22 -1
  121. package/src/cli/daemon-cli.ts +53 -18
  122. package/src/cli/github-release.ts +87 -5
  123. package/src/cli/mcp-cli.ts +38 -4
  124. package/src/cli/public-command-entry.ts +450 -0
  125. package/src/cli/public-command-errors.ts +581 -0
  126. package/src/cli/public-command-evidence.ts +717 -0
  127. package/src/cli/public-command-help.ts +360 -0
  128. package/src/cli/public-command-registry.ts +541 -0
  129. package/src/cli/session-picker.ts +2 -1
  130. package/src/cli/setup-cli.ts +10 -1
  131. package/src/cli/skills-cli.ts +46 -2
  132. package/src/cli/stats-cli.ts +11 -1
  133. package/src/cli.ts +61 -1
  134. package/src/commands/daemon.ts +65 -69
  135. package/src/commands/sdk.ts +175 -117
  136. package/src/commands/setup.ts +2 -0
  137. package/src/commands/skills.ts +11 -0
  138. package/src/config/autorouting-tier-map.ts +543 -3
  139. package/src/config/file-lock.ts +206 -65
  140. package/src/config/model-discovery-manager.ts +4 -4
  141. package/src/config/model-profile-activation.ts +417 -66
  142. package/src/config/model-registry.ts +254 -36
  143. package/src/config/model-resolver.ts +6 -1
  144. package/src/config/settings-schema.ts +26 -2
  145. package/src/coordinator-mcp/policy.ts +10 -5
  146. package/src/coordinator-mcp/question-gate-codec.ts +17 -0
  147. package/src/coordinator-mcp/question-state.ts +179 -9
  148. package/src/coordinator-mcp/server.ts +521 -87
  149. package/src/coordinator-mcp/session-reaper.ts +6 -4
  150. package/src/crash/record-loader.ts +6 -2
  151. package/src/daemon/operator-contract.ts +26 -12
  152. package/src/defaults/gjc/skills/ultragoal/SKILL.md +1 -1
  153. package/src/eval/js/context-manager.ts +8 -8
  154. package/src/eval/js/worker-core.ts +9 -4
  155. package/src/eval/js/worker-protocol.ts +2 -0
  156. package/src/exec/bash-executor.ts +3 -0
  157. package/src/extensibility/extensions/runner.ts +52 -4
  158. package/src/extensibility/extensions/types.ts +10 -0
  159. package/src/extensibility/gjc-plugins/registry.ts +196 -37
  160. package/src/extensibility/gjc-plugins/runtime-adapters.ts +46 -8
  161. package/src/extensibility/runtime-skill-discovery.ts +61 -3
  162. package/src/extensibility/shared-events.ts +3 -1
  163. package/src/gjc-runtime/session-state-lock.ts +165 -24
  164. package/src/gjc-runtime/state-writer.ts +317 -6
  165. package/src/gjc-runtime/ultragoal-succession.ts +31 -3
  166. package/src/harness-control-plane/control-endpoint.ts +24 -6
  167. package/src/harness-control-plane/finalize.ts +312 -25
  168. package/src/harness-control-plane/owner.ts +323 -89
  169. package/src/internal-urls/docs-index.generated.ts +23 -20
  170. package/src/internal-urls/embedded-protocol.ts +83 -0
  171. package/src/internal-urls/index.ts +1 -0
  172. package/src/internal-urls/parse.ts +21 -1
  173. package/src/internal-urls/router.ts +4 -2
  174. package/src/main.ts +192 -74
  175. package/src/modes/acp/acp-agent.ts +973 -56
  176. package/src/modes/acp/startup-provenance.ts +59 -0
  177. package/src/modes/components/custom-provider-wizard.ts +308 -7
  178. package/src/modes/components/gjc-bundle-settings.ts +21 -1
  179. package/src/modes/components/oauth-selector.ts +9 -0
  180. package/src/modes/components/session-selector.ts +47 -4
  181. package/src/modes/components/tool-status-header.ts +72 -6
  182. package/src/modes/components/user-message-selector.ts +57 -15
  183. package/src/modes/controllers/command-controller.ts +58 -32
  184. package/src/modes/controllers/extension-ui-controller.ts +33 -7
  185. package/src/modes/controllers/input-controller.ts +4 -0
  186. package/src/modes/controllers/runtime-mcp-command-controller.ts +1 -1
  187. package/src/modes/controllers/selector-controller.ts +161 -15
  188. package/src/modes/interactive-mode.ts +21 -7
  189. package/src/modes/runtime-init.ts +1 -0
  190. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +124 -7
  191. package/src/modes/shared/agent-wire/workflow-gate-types.ts +16 -2
  192. package/src/modes/types.ts +2 -2
  193. package/src/prompts/agent-fragments/browser-aside.md +1 -0
  194. package/src/prompts/system/title-system.md +1 -1
  195. package/src/prompts/tools/bash.md +1 -1
  196. package/src/prompts/tools/job.md +1 -1
  197. package/src/prompts/tools/read.md +2 -0
  198. package/src/runtime/network-prewarm-service.test.ts +36 -1
  199. package/src/runtime/network-prewarm-service.ts +28 -3
  200. package/src/runtime/process-lifecycle.ts +22 -11
  201. package/src/runtime-mcp/config.ts +16 -1
  202. package/src/runtime-mcp/loader.ts +6 -3
  203. package/src/runtime-mcp/manager.ts +845 -109
  204. package/src/runtime-mcp/pool.test.ts +31 -0
  205. package/src/runtime-mcp/pool.ts +304 -28
  206. package/src/runtime-mcp/redaction.ts +42 -0
  207. package/src/runtime-mcp/startup-policy.ts +7 -0
  208. package/src/runtime-mcp/tool-bridge.ts +71 -0
  209. package/src/runtime-mcp/transports/http.ts +108 -25
  210. package/src/sdk/acp/adapter.ts +27 -8
  211. package/src/sdk/broker/broker.ts +1431 -198
  212. package/src/sdk/broker/ensure.ts +21 -3
  213. package/src/sdk/broker/identity.ts +22 -1
  214. package/src/sdk/broker/lifecycle-ledger.ts +95 -31
  215. package/src/sdk/broker/lifecycle.ts +690 -141
  216. package/src/sdk/broker/managed-task-dag.ts +1927 -0
  217. package/src/sdk/broker/managed-task-verification.ts +642 -0
  218. package/src/sdk/broker/runtime.ts +1 -1
  219. package/src/sdk/broker/session-index.ts +97 -4
  220. package/src/sdk/broker/spawn-authority.ts +175 -14
  221. package/src/sdk/broker/startup-failure.ts +80 -1
  222. package/src/sdk/broker/stderr-drainer.ts +59 -0
  223. package/src/sdk/broker/transport.ts +1 -0
  224. package/src/sdk/bus/chat-daemon-control.ts +2 -2
  225. package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
  226. package/src/sdk/bus/index.ts +707 -81
  227. package/src/sdk/bus/telegram-daemon-cli.ts +31 -2
  228. package/src/sdk/bus/telegram-daemon-contract.ts +7 -1
  229. package/src/sdk/bus/telegram-daemon.ts +10 -3
  230. package/src/sdk/cli/master-cli.ts +47 -36
  231. package/src/sdk/cli/rows.ts +30 -7
  232. package/src/sdk/cli/session-cli.ts +705 -184
  233. package/src/sdk/client/client.ts +18 -0
  234. package/src/sdk/guides/catalog.ts +2 -2
  235. package/src/sdk/guides/cli.ts +20 -62
  236. package/src/sdk/guides/verify.ts +14 -0
  237. package/src/sdk/host/host.ts +49 -5
  238. package/src/sdk/host/session-runtime.test.ts +184 -2
  239. package/src/sdk/host/session-runtime.ts +322 -101
  240. package/src/sdk/host/types.ts +12 -1
  241. package/src/sdk/host/websocket-transport.lifecycle.test.ts +84 -0
  242. package/src/sdk/host/websocket-transport.ts +40 -6
  243. package/src/sdk/index.ts +11 -0
  244. package/src/sdk/lifecycle/service.ts +2 -0
  245. package/src/sdk/prompt-deadline-flush.ts +356 -0
  246. package/src/sdk/prompt-deadline-manager.ts +133 -1
  247. package/src/sdk/prompt-tool-boundary.ts +121 -0
  248. package/src/sdk/protocol/operation-inventory.generated.json +106 -0
  249. package/src/sdk/router/session-router.ts +9 -1
  250. package/src/sdk/session.ts +763 -116
  251. package/src/sdk/startup-capability.ts +1 -1
  252. package/src/sdk/transport/relay.ts +71 -6
  253. package/src/sdk/transport/serve-cli.ts +397 -42
  254. package/src/sdk/transport/socket.ts +12 -11
  255. package/src/sdk/transport/stdio.ts +7 -3
  256. package/src/session/agent-session.ts +2472 -407
  257. package/src/session/fallback-chain-controller.ts +6 -7
  258. package/src/session/fold-coordinator.ts +24 -5
  259. package/src/session/internal/managed-session-scope.ts +68 -18
  260. package/src/session/internal/managed-session-storage.ts +334 -12
  261. package/src/session/session-manager.ts +382 -44
  262. package/src/session/session-work-lease.ts +34 -0
  263. package/src/setup/model-onboarding-guidance.ts +1 -1
  264. package/src/setup/provider-onboarding.ts +397 -24
  265. package/src/setup/provider-presets.json +2 -1
  266. package/src/slash-commands/builtin-registry.ts +259 -15
  267. package/src/task/executor.ts +46 -17
  268. package/src/task/index.ts +14 -2
  269. package/src/task/types.ts +2 -0
  270. package/src/tools/bash-interactive.ts +2 -0
  271. package/src/tools/bash.ts +118 -78
  272. package/src/tools/fetch.ts +140 -25
  273. package/src/tools/job.ts +151 -25
  274. package/src/tools/output-meta.ts +15 -2
  275. package/src/tools/path-utils.ts +27 -3
  276. package/src/tools/read.ts +3 -3
  277. package/src/tools/steer-fold.ts +107 -0
  278. package/src/tools/subagent-render.ts +24 -1
  279. package/src/tools/subagent.ts +27 -1
  280. package/src/tools/tool-catalog.generated.ts +29 -2
  281. package/src/tools/tool-errors.ts +4 -0
  282. package/src/utils/git.ts +53 -3
  283. package/src/utils/markit.ts +55 -41
  284. package/src/utils/mupdf-assets.d.ts +4 -0
  285. package/src/utils/mupdf-embedded.ts +4 -0
  286. package/src/utils/mupdf.ts +136 -0
  287. package/src/utils/session-title-generation.ts +29 -0
  288. package/src/utils/title-generator.ts +46 -2
  289. package/src/web/scrapers/types.ts +24 -3
  290. package/vendor/markit-ai/LICENSE +21 -0
  291. package/vendor/markit-ai/MANIFEST.json +412 -0
  292. package/vendor/markit-ai/dist/commands/config.d.ts +4 -0
  293. package/vendor/markit-ai/dist/commands/config.js +139 -0
  294. package/vendor/markit-ai/dist/commands/convert.d.ts +6 -0
  295. package/vendor/markit-ai/dist/commands/convert.js +113 -0
  296. package/vendor/markit-ai/dist/commands/formats.d.ts +2 -0
  297. package/vendor/markit-ai/dist/commands/formats.js +92 -0
  298. package/vendor/markit-ai/dist/commands/init.d.ts +2 -0
  299. package/vendor/markit-ai/dist/commands/init.js +29 -0
  300. package/vendor/markit-ai/dist/commands/onboard.d.ts +2 -0
  301. package/vendor/markit-ai/dist/commands/onboard.js +61 -0
  302. package/vendor/markit-ai/dist/commands/plugin.d.ts +4 -0
  303. package/vendor/markit-ai/dist/commands/plugin.js +58 -0
  304. package/vendor/markit-ai/dist/config.d.ts +26 -0
  305. package/vendor/markit-ai/dist/config.js +42 -0
  306. package/vendor/markit-ai/dist/converters/audio.d.ts +7 -0
  307. package/vendor/markit-ai/dist/converters/audio.js +104 -0
  308. package/vendor/markit-ai/dist/converters/csv.d.ts +7 -0
  309. package/vendor/markit-ai/dist/converters/csv.js +83 -0
  310. package/vendor/markit-ai/dist/converters/docx.d.ts +6 -0
  311. package/vendor/markit-ai/dist/converters/docx.js +57 -0
  312. package/vendor/markit-ai/dist/converters/epub.d.ts +8 -0
  313. package/vendor/markit-ai/dist/converters/epub.js +128 -0
  314. package/vendor/markit-ai/dist/converters/github.d.ts +18 -0
  315. package/vendor/markit-ai/dist/converters/github.js +148 -0
  316. package/vendor/markit-ai/dist/converters/html.d.ts +6 -0
  317. package/vendor/markit-ai/dist/converters/html.js +30 -0
  318. package/vendor/markit-ai/dist/converters/image.d.ts +6 -0
  319. package/vendor/markit-ai/dist/converters/image.js +124 -0
  320. package/vendor/markit-ai/dist/converters/ipynb.d.ts +6 -0
  321. package/vendor/markit-ai/dist/converters/ipynb.js +75 -0
  322. package/vendor/markit-ai/dist/converters/iwork.d.ts +20 -0
  323. package/vendor/markit-ai/dist/converters/iwork.js +391 -0
  324. package/vendor/markit-ai/dist/converters/json.d.ts +6 -0
  325. package/vendor/markit-ai/dist/converters/json.js +21 -0
  326. package/vendor/markit-ai/dist/converters/pdf/columns.d.ts +35 -0
  327. package/vendor/markit-ai/dist/converters/pdf/columns.js +93 -0
  328. package/vendor/markit-ai/dist/converters/pdf/extract.d.ts +19 -0
  329. package/vendor/markit-ai/dist/converters/pdf/extract.js +514 -0
  330. package/vendor/markit-ai/dist/converters/pdf/grid.d.ts +25 -0
  331. package/vendor/markit-ai/dist/converters/pdf/grid.js +795 -0
  332. package/vendor/markit-ai/dist/converters/pdf/headers.d.ts +24 -0
  333. package/vendor/markit-ai/dist/converters/pdf/headers.js +108 -0
  334. package/vendor/markit-ai/dist/converters/pdf/index.d.ts +19 -0
  335. package/vendor/markit-ai/dist/converters/pdf/index.js +136 -0
  336. package/vendor/markit-ai/dist/converters/pdf/mupdf-loader.js +9 -0
  337. package/vendor/markit-ai/dist/converters/pdf/render.d.ts +24 -0
  338. package/vendor/markit-ai/dist/converters/pdf/render.js +513 -0
  339. package/vendor/markit-ai/dist/converters/pdf/types.d.ts +75 -0
  340. package/vendor/markit-ai/dist/converters/pdf/types.js +1 -0
  341. package/vendor/markit-ai/dist/converters/plain-text.d.ts +6 -0
  342. package/vendor/markit-ai/dist/converters/plain-text.js +87 -0
  343. package/vendor/markit-ai/dist/converters/pptx.d.ts +8 -0
  344. package/vendor/markit-ai/dist/converters/pptx.js +289 -0
  345. package/vendor/markit-ai/dist/converters/rss.d.ts +11 -0
  346. package/vendor/markit-ai/dist/converters/rss.js +138 -0
  347. package/vendor/markit-ai/dist/converters/wikipedia.d.ts +6 -0
  348. package/vendor/markit-ai/dist/converters/wikipedia.js +33 -0
  349. package/vendor/markit-ai/dist/converters/xlsx.d.ts +8 -0
  350. package/vendor/markit-ai/dist/converters/xlsx.js +147 -0
  351. package/vendor/markit-ai/dist/converters/xml.d.ts +6 -0
  352. package/vendor/markit-ai/dist/converters/xml.js +18 -0
  353. package/vendor/markit-ai/dist/converters/yaml.d.ts +6 -0
  354. package/vendor/markit-ai/dist/converters/yaml.js +17 -0
  355. package/vendor/markit-ai/dist/converters/zip.d.ts +8 -0
  356. package/vendor/markit-ai/dist/converters/zip.js +57 -0
  357. package/vendor/markit-ai/dist/index.d.ts +30 -0
  358. package/vendor/markit-ai/dist/index.js +26 -0
  359. package/vendor/markit-ai/dist/main.d.ts +2 -0
  360. package/vendor/markit-ai/dist/main.js +191 -0
  361. package/vendor/markit-ai/dist/markit.d.ts +45 -0
  362. package/vendor/markit-ai/dist/markit.js +267 -0
  363. package/vendor/markit-ai/dist/plugins/api.d.ts +7 -0
  364. package/vendor/markit-ai/dist/plugins/api.js +42 -0
  365. package/vendor/markit-ai/dist/plugins/index.d.ts +4 -0
  366. package/vendor/markit-ai/dist/plugins/index.js +3 -0
  367. package/vendor/markit-ai/dist/plugins/installer.d.ts +25 -0
  368. package/vendor/markit-ai/dist/plugins/installer.js +176 -0
  369. package/vendor/markit-ai/dist/plugins/loader.d.ts +6 -0
  370. package/vendor/markit-ai/dist/plugins/loader.js +61 -0
  371. package/vendor/markit-ai/dist/plugins/types.d.ts +25 -0
  372. package/vendor/markit-ai/dist/plugins/types.js +1 -0
  373. package/vendor/markit-ai/dist/providers/anthropic.d.ts +2 -0
  374. package/vendor/markit-ai/dist/providers/anthropic.js +47 -0
  375. package/vendor/markit-ai/dist/providers/index.d.ts +21 -0
  376. package/vendor/markit-ai/dist/providers/index.js +56 -0
  377. package/vendor/markit-ai/dist/providers/openai.d.ts +2 -0
  378. package/vendor/markit-ai/dist/providers/openai.js +76 -0
  379. package/vendor/markit-ai/dist/providers/types.d.ts +26 -0
  380. package/vendor/markit-ai/dist/providers/types.js +1 -0
  381. package/vendor/markit-ai/dist/types.d.ts +36 -0
  382. package/vendor/markit-ai/dist/types.js +1 -0
  383. package/vendor/markit-ai/dist/utils/exit-codes.d.ts +4 -0
  384. package/vendor/markit-ai/dist/utils/exit-codes.js +4 -0
  385. package/vendor/markit-ai/dist/utils/output.d.ts +22 -0
  386. package/vendor/markit-ai/dist/utils/output.js +31 -0
  387. package/vendor/markit-ai/dist/utils/turndown.d.ts +8 -0
  388. package/vendor/markit-ai/dist/utils/turndown.js +70 -0
  389. package/vendor/markit-ai/package.json +74 -0
  390. package/vendor/markit-ai.patch +49 -0
@@ -155,7 +155,12 @@ import {
155
155
  MODEL_ONBOARDING_PROVIDER_PRESET_COMMAND,
156
156
  MODEL_ONBOARDING_SETUP_COMMAND,
157
157
  } from "../../setup/model-onboarding-guidance";
158
- import { addApiCompatibleProvider, formatProviderSetupResult } from "../../setup/provider-onboarding";
158
+ import {
159
+ addApiCompatibleProvider,
160
+ formatProviderSetupResult,
161
+ probeOpenAIModelsList,
162
+ reloadAndRefreshDiscoveryCatalog,
163
+ } from "../../setup/provider-onboarding";
159
164
  import { getThinkingLevelMetadata } from "../../thinking";
160
165
  import {
161
166
  isConfigurableSearchProviderId,
@@ -1821,15 +1826,48 @@ export class SelectorController {
1821
1826
  this.showSelector(done => {
1822
1827
  let wizard: CustomProviderWizardComponent;
1823
1828
  const submit = async (input: CustomProviderWizardSubmit): Promise<void> => {
1829
+ // Component-owned generation: revision or cancel after submit
1830
+ // start invalidates this attempt. Both completion branches
1831
+ // check it so a stale refresh cannot report success or
1832
+ // rerender over inputs the user has since revised.
1833
+ const generation = wizard.currentSubmitGeneration();
1834
+ const isCurrentSubmission = (): boolean => wizard.isSubmitCurrent(generation);
1824
1835
  try {
1825
- const result = await addApiCompatibleProvider(input);
1826
- await this.ctx.session.modelRegistry.refresh("offline", this.ctx.session.credentialSessionId);
1836
+ const result = await addApiCompatibleProvider({
1837
+ ...input,
1838
+ authStorage: this.ctx.session.modelRegistry.authStorage,
1839
+ });
1840
+ let recoveryHint: string | null = null;
1841
+ if (result.discoveryEnabled && !result.preset) {
1842
+ // A discovery-only add has no static models and no cache yet,
1843
+ // so an offline reload alone leaves an empty catalog. Refresh
1844
+ // only the new provider online; a hint is surfaced instead
1845
+ // of unconditional success when it stays unavailable.
1846
+ recoveryHint = await reloadAndRefreshDiscoveryCatalog(
1847
+ this.ctx.session.modelRegistry,
1848
+ result.providerId,
1849
+ this.ctx.session.credentialSessionId,
1850
+ );
1851
+ } else {
1852
+ await this.ctx.session.modelRegistry.refresh("offline", this.ctx.session.credentialSessionId);
1853
+ }
1827
1854
  await this.ctx.notifyConfigChanged?.();
1828
- this.ctx.showStatus(formatProviderSetupResult(result));
1855
+ // A late settle after Esc-cancel or a mid-submit revision
1856
+ // must not drive completion UI: done() restores the
1857
+ // composer and could close a selector the user opened
1858
+ // after dismissal, and a stale refresh must not report
1859
+ // success over revised inputs.
1860
+ if (!isCurrentSubmission()) return;
1861
+ this.ctx.showStatus(
1862
+ recoveryHint
1863
+ ? `${formatProviderSetupResult(result)}\n${recoveryHint}`
1864
+ : formatProviderSetupResult(result),
1865
+ );
1829
1866
  wizard.complete();
1830
1867
  done();
1831
1868
  this.ctx.ui.requestRender();
1832
1869
  } catch (err) {
1870
+ if (!isCurrentSubmission()) return;
1833
1871
  const message = err instanceof Error ? err.message : String(err);
1834
1872
  wizard.setSubmitError(`Provider setup failed: ${message}`);
1835
1873
  }
@@ -1843,6 +1881,9 @@ export class SelectorController {
1843
1881
  this.ctx.ui.requestRender();
1844
1882
  },
1845
1883
  () => this.ctx.ui.requestRender(),
1884
+ {
1885
+ discoverModels: async request => probeOpenAIModelsList(request),
1886
+ },
1846
1887
  );
1847
1888
  return { component: wizard, focus: wizard };
1848
1889
  });
@@ -3070,36 +3111,138 @@ export class SelectorController {
3070
3111
  });
3071
3112
  }
3072
3113
 
3073
- showUserMessageSelector(): void {
3074
- const userMessages = this.ctx.session.getUserMessagesForBranching();
3114
+ #forkBusyReason(): string | undefined {
3115
+ if (this.ctx.session.isStreaming) {
3116
+ return "Wait for the current response to finish or abort it before forking.";
3117
+ }
3118
+ if (this.ctx.session.isCompacting) {
3119
+ return "Wait for compaction to finish or abort it before forking.";
3120
+ }
3121
+ if (this.ctx.hasPendingSubmission()) {
3122
+ return "Wait for the pending message to be submitted or cancel it before forking.";
3123
+ }
3124
+ if (this.ctx.bashComponent || this.ctx.pythonComponent) {
3125
+ return "Wait for the foreground command to finish or cancel it before forking.";
3126
+ }
3127
+ return undefined;
3128
+ }
3075
3129
 
3130
+ showUserMessageSelector(onCommitted?: () => void): void {
3131
+ const openedSessionId = this.ctx.sessionManager.getSessionId();
3132
+ const openedSessionFile = this.ctx.sessionManager.getSessionFile();
3133
+ if (!openedSessionFile) {
3134
+ this.ctx.showError("Fork requires a persisted session");
3135
+ return;
3136
+ }
3137
+ const busyReason = this.#forkBusyReason();
3138
+ if (busyReason) {
3139
+ this.ctx.showWarning(busyReason);
3140
+ return;
3141
+ }
3142
+
3143
+ const userMessages = this.ctx.session.getUserMessagesForBranching();
3076
3144
  if (userMessages.length === 0) {
3077
3145
  this.ctx.showStatus("No messages to branch from");
3078
3146
  return;
3079
3147
  }
3080
3148
 
3149
+ this.ctx.goalModeController.cancelContinuation();
3150
+ // Close the side-chat composer before the picker takes ownership, including
3151
+ // paths that cancel, fail, or stop while branch() is pending.
3152
+ if (this.ctx.hasActiveBtw()) this.ctx.handleBtwEscape();
3153
+
3081
3154
  this.showSelector(done => {
3155
+ let selectionInFlight = false;
3156
+ const closeWithoutBranch = (message: string, error = false): void => {
3157
+ done();
3158
+ if (error) {
3159
+ this.ctx.showError(message);
3160
+ } else {
3161
+ this.ctx.showStatus(message);
3162
+ }
3163
+ this.ctx.goalModeController.scheduleContinuation();
3164
+ this.ctx.ui.requestRender();
3165
+ };
3082
3166
  const selector = new UserMessageSelectorComponent(
3083
3167
  userMessages.map(m => ({ id: m.entryId, text: m.text })),
3084
3168
  async entryId => {
3085
- const result = await this.ctx.session.branch(entryId);
3086
- if (result.cancelled) {
3087
- // Hook cancelled the branch
3088
- done();
3089
- this.ctx.ui.requestRender();
3169
+ if (selectionInFlight) return;
3170
+ selectionInFlight = true;
3171
+
3172
+ if (
3173
+ this.ctx.sessionManager.getSessionId() !== openedSessionId ||
3174
+ this.ctx.sessionManager.getSessionFile() !== openedSessionFile
3175
+ ) {
3176
+ closeWithoutBranch("Fork cancelled because the active session changed", true);
3177
+ return;
3178
+ }
3179
+ const busyReason = this.#forkBusyReason();
3180
+ if (busyReason) {
3181
+ closeWithoutBranch(busyReason);
3090
3182
  return;
3091
3183
  }
3092
- this.ctx.resetIrcSidebarSession();
3093
3184
 
3094
- this.ctx.rebuildInitialMessages("replace-identity");
3095
- this.ctx.editor.setText(result.selectedText);
3185
+ let selectedText = userMessages.find(message => message.entryId === entryId)!.text;
3186
+ let branchFailure: unknown;
3187
+ try {
3188
+ const result = await this.ctx.session.branch(entryId);
3189
+ if (this.ctx.isStopped?.()) return;
3190
+ if (result.cancelled) {
3191
+ closeWithoutBranch("Fork cancelled");
3192
+ return;
3193
+ }
3194
+ selectedText = result.selectedText;
3195
+ } catch (error) {
3196
+ if (this.ctx.isStopped?.()) return;
3197
+ const committed =
3198
+ this.ctx.sessionManager.getSessionId() !== openedSessionId ||
3199
+ this.ctx.sessionManager.getSessionFile() !== openedSessionFile;
3200
+ if (!committed) {
3201
+ closeWithoutBranch(`Fork failed: ${error instanceof Error ? error.message : String(error)}`, true);
3202
+ return;
3203
+ }
3204
+ // The successor is already durable. Never describe this as a
3205
+ // cancelled transition or roll it back to the parent's UI.
3206
+ branchFailure = error;
3207
+ }
3208
+
3209
+ try {
3210
+ onCommitted?.();
3211
+ } catch (error) {
3212
+ branchFailure ??= error;
3213
+ }
3214
+ try {
3215
+ this.ctx.resetIrcSidebarSession();
3216
+ this.ctx.resetObserverRegistry();
3217
+ this.#refreshSessionTerminalTitle();
3218
+ this.ctx.statusLine.invalidate();
3219
+ this.ctx.statusLine.setSessionStartTime(Date.now());
3220
+ this.ctx.updateEditorTopBorder();
3221
+ this.ctx.updateEditorBorderColor();
3222
+ this.ctx.rebuildInitialMessages("replace-identity");
3223
+ await this.ctx.reloadTodos();
3224
+ } catch (error) {
3225
+ branchFailure ??= error;
3226
+ }
3227
+ if (this.ctx.isStopped?.()) return;
3228
+ this.ctx.editor.setText(selectedText);
3096
3229
  done();
3097
- this.ctx.showStatus("Branched to new session");
3230
+ if (branchFailure !== undefined) {
3231
+ this.ctx.showError(
3232
+ `Fork created, but session setup failed: ${branchFailure instanceof Error ? branchFailure.message : String(branchFailure)}`,
3233
+ );
3234
+ } else {
3235
+ this.ctx.showStatus("Forked to a new session; edit the selected prompt to continue");
3236
+ }
3237
+ // Do not schedule goal continuation over the selected prompt draft.
3238
+ this.ctx.ui.requestRender();
3098
3239
  },
3099
3240
  () => {
3100
3241
  done();
3242
+ this.ctx.goalModeController.scheduleContinuation();
3101
3243
  this.ctx.ui.requestRender();
3102
3244
  },
3245
+ () => this.ctx.ui.terminal.rows,
3103
3246
  );
3104
3247
  return { component: selector, focus: selector.getMessageList() };
3105
3248
  });
@@ -3274,6 +3417,9 @@ export class SelectorController {
3274
3417
  });
3275
3418
  }
3276
3419
  },
3420
+ undefined,
3421
+ undefined,
3422
+ (session, starred) => this.ctx.sessionManager.setSessionStarredForPicker(session, starred),
3277
3423
  );
3278
3424
  selector.setOnRequestRender(() => this.ctx.ui.requestRender());
3279
3425
  return { component: selector, focus: selector };
@@ -2265,10 +2265,24 @@ export class InteractiveMode implements InteractiveModeContext {
2265
2265
  }
2266
2266
 
2267
2267
  #prepareSessionSwitch(cleanupPreviousSessionUi?: () => void): void {
2268
- this.#btwController.dispose();
2269
- if (cleanupPreviousSessionUi) cleanupPreviousSessionUi();
2270
- else this.#extensionUiController.clearExtensionTerminalInputListeners();
2271
- this.#planModeController.clearReview();
2268
+ const errors: unknown[] = [];
2269
+ try {
2270
+ this.#btwController.dispose();
2271
+ } catch (error) {
2272
+ errors.push(error);
2273
+ }
2274
+ try {
2275
+ if (cleanupPreviousSessionUi) cleanupPreviousSessionUi();
2276
+ else this.#extensionUiController.clearExtensionTerminalInputListeners();
2277
+ } catch (error) {
2278
+ errors.push(error);
2279
+ }
2280
+ try {
2281
+ this.#planModeController.clearReview();
2282
+ } catch (error) {
2283
+ errors.push(error);
2284
+ }
2285
+ if (errors.length > 0) throw new AggregateError(errors, "Previous session UI cleanup failed");
2272
2286
  }
2273
2287
 
2274
2288
  async handleClearCommand(): Promise<boolean> {
@@ -2291,7 +2305,6 @@ export class InteractiveMode implements InteractiveModeContext {
2291
2305
  }
2292
2306
 
2293
2307
  handleForkCommand(): Promise<void> {
2294
- this.#btwController.dispose();
2295
2308
  return this.#commandController.handleForkCommand();
2296
2309
  }
2297
2310
 
@@ -2299,7 +2312,7 @@ export class InteractiveMode implements InteractiveModeContext {
2299
2312
  return this.#commandController.handleMoveCommand(targetPath);
2300
2313
  }
2301
2314
 
2302
- handleRenameCommand(title: string): Promise<void> {
2315
+ handleRenameCommand(title?: string): Promise<void> {
2303
2316
  return this.#commandController.handleRenameCommand(title);
2304
2317
  }
2305
2318
 
@@ -2564,7 +2577,8 @@ export class InteractiveMode implements InteractiveModeContext {
2564
2577
  }
2565
2578
 
2566
2579
  showUserMessageSelector(): void {
2567
- this.#selectorController.showUserMessageSelector();
2580
+ const cleanupPreviousSessionUi = this.#extensionUiController.captureSessionUiCleanup();
2581
+ this.#selectorController.showUserMessageSelector(() => this.#prepareSessionSwitch(cleanupPreviousSessionUi));
2568
2582
  }
2569
2583
 
2570
2584
  showTreeSelector(): void {
@@ -123,6 +123,7 @@ export async function initializeExtensions(session: AgentSession, options: Initi
123
123
  getCredentialSessionId: () => session.credentialSessionId,
124
124
  isIdle: () => !session.isStreaming,
125
125
  getActivePromptHandle: () => session.activePromptHandle,
126
+ getSessionWorkLease: () => session.sessionWorkLease,
126
127
  abort: () => session.abort(),
127
128
  abortPromptAndWait: (handle, abortOptions) => session.abortPromptAndWait(handle, abortOptions),
128
129
  hasPendingMessages: () => session.queuedMessageCount > 0,
@@ -24,6 +24,7 @@ import type {
24
24
  WorkflowGateOption,
25
25
  WorkflowGateQueryRecord,
26
26
  WorkflowGateResolution,
27
+ WorkflowGateResolutionDiagnostic,
27
28
  WorkflowGateResponse,
28
29
  WorkflowGateValidationError,
29
30
  WorkflowStage,
@@ -35,6 +36,9 @@ export type PersistedResolutionOrigin =
35
36
  | { kind: "generic"; channel: "sdk" | "other" }
36
37
  | { kind: "telegram_notification"; interactionActionId: string };
37
38
 
39
+ /** Keep accepted diagnostics below the coordinator's cumulative Q12 snapshot cap. */
40
+ export const MAX_ACCEPTED_WORKFLOW_GATE_QUERY_RECORDS = 32;
41
+
38
42
  export type PersistedAckPolicy =
39
43
  | { kind: "none"; reason: "non_telegram" | "semantic_noncommit" | "legacy_unproven" }
40
44
  | {
@@ -152,7 +156,7 @@ export class BrokerWorkflowGateEmitter implements WorkflowGateEmitter {
152
156
  readonly #emitterHooks: Pick<BrokerHooks, "advance">;
153
157
  #runtimeTurnProvider: (() => string | undefined) | undefined;
154
158
 
155
- constructor(runId: string, store: GateStore, emitterHooks: Pick<BrokerHooks, "advance"> = {}) {
159
+ constructor(runId: string, store: GateStore, emitterHooks: Pick<BrokerHooks, "advance" | "continuationLost"> = {}) {
156
160
  this.#runId = runId;
157
161
  this.#store = store;
158
162
  this.#emitterHooks = emitterHooks;
@@ -164,6 +168,7 @@ export class BrokerWorkflowGateEmitter implements WorkflowGateEmitter {
164
168
  completeAccepted: record => this.#completeAccepted(record),
165
169
  finalizeAccepted: record => this.#finalizeAccepted(record),
166
170
  terminalizeAccepted: record => this.#terminalizeAccepted(record),
171
+ continuationLost: record => emitterHooks.continuationLost?.(record),
167
172
  });
168
173
  }
169
174
 
@@ -1147,6 +1152,8 @@ export type GateAuditEvent =
1147
1152
  | { event: "gate_response_accepted"; gate_id: string; answer_hash: string }
1148
1153
  | { event: "gate_response_rejected"; gate_id: string; answer_hash: string }
1149
1154
  | { event: "gate_response_idempotent_replay"; gate_id: string }
1155
+ /** An idempotent replay refused because this runtime cannot prove the continuation ran. */
1156
+ | { event: "gate_response_replay_unproven"; gate_id: string }
1150
1157
  | { event: "gate_response_idempotency_conflict"; gate_id: string }
1151
1158
  | { event: "gate_response_already_resolved"; gate_id: string }
1152
1159
  | { event: "gate_response_unknown_gate"; gate_id: string }
@@ -1171,6 +1178,8 @@ export interface BrokerHooks {
1171
1178
  terminalizeAccepted?(record: PersistedGate): WorkflowGateTerminalProof | Promise<WorkflowGateTerminalProof>;
1172
1179
  /** Runs only after a successful advance has been durably marked advanced. */
1173
1180
  completeAccepted?(record: PersistedGate): void | Promise<void>;
1181
+ /** Notifies the owning runtime when the accepted answer cannot reach its continuation. */
1182
+ continuationLost?(record: PersistedGate): void;
1174
1183
  /** Append-only audit sink. */
1175
1184
  audit?(event: GateAuditEvent): void;
1176
1185
  }
@@ -1222,6 +1231,14 @@ export class WorkflowGateBroker {
1222
1231
  private readonly gateLocks = new Map<string, Promise<void>>();
1223
1232
  private readonly continuations = new Map<string, GateContinuation>();
1224
1233
  readonly #terminalProofs = new Map<string, WorkflowGateTerminalProof>();
1234
+ /**
1235
+ * Gates whose `completeAccepted` hook threw after `advanced:true` was already
1236
+ * committed, so the durable record claims completion the continuation never
1237
+ * received. In-memory by design: the stranded turn belongs to this process's
1238
+ * waiter, so a restart cannot resolve it either way and must not inherit a
1239
+ * claim it cannot honor (#5599).
1240
+ */
1241
+ readonly #continuationLost = new Set<string>();
1225
1242
 
1226
1243
  private async withGateLock<T>(gateId: string, operation: () => Promise<T>): Promise<T> {
1227
1244
  const previous = this.gateLocks.get(gateId) ?? Promise.resolve();
@@ -1282,6 +1299,34 @@ export class WorkflowGateBroker {
1282
1299
  `idempotency_conflict: gate ${response.gate_id} resolved with a different body`,
1283
1300
  );
1284
1301
  if (response.idempotency_key !== undefined && sameKey && sameBody) {
1302
+ // A record whose `completeAccepted` threw is durably indistinguishable from a
1303
+ // genuinely completed one: `advanced:true` is committed before the waiter is
1304
+ // resolved, so the shape below matches either way. Reporting `completed` there
1305
+ // told `resolveSdkWorkflowGate`'s catch path to return a successful resolution
1306
+ // for a turn whose continuation was never resolved — `ok:true status:"accepted"`
1307
+ // with an empty pending-gate list and a prompt stuck `in_flight` forever, with
1308
+ // no recovery path because `recover()` skips advanced records (#5599).
1309
+ //
1310
+ // Downgrading to `accepted_incomplete` routes it through the existing
1311
+ // recover-then-recheck branch and, when that cannot resolve it, surfaces the
1312
+ // documented `terminal_uncertain` instead of a false success.
1313
+ //
1314
+ // TWO conditions, because the loss cannot be persisted: an `accepted` record
1315
+ // may not carry a `lifecycle` and a `quarantined` one must be `advanced:false`,
1316
+ // so the durable shape has nowhere to record it.
1317
+ //
1318
+ // 1. This runtime saw the hook throw.
1319
+ if (this.#continuationLost.has(response.gate_id)) return { kind: "accepted_incomplete" };
1320
+ // 2. The record belongs to a PREVIOUS runtime. A continuation waiter is
1321
+ // process-local and cannot survive a restart, so this process can never
1322
+ // prove the prior turn was resolved — and the in-memory set above is empty
1323
+ // after a restart, which is exactly how the first fix still handed back a
1324
+ // false `completed` on a cross-restart idempotent retry (#5599 review).
1325
+ // Fail closed instead. The cost is telling a retry "uncertain" about a gate
1326
+ // that did complete under the dead runtime; that is the honest answer
1327
+ // regardless, because the turn it belonged to died with that process and no
1328
+ // retry can continue it.
1329
+ if (record.ownerInstanceId !== this.instanceId) return { kind: "accepted_incomplete" };
1285
1330
  if (record.terminalized === true && record.advanced === true && record.resolution)
1286
1331
  return { kind: "completed", resolution: record.resolution };
1287
1332
  return { kind: "accepted_incomplete" };
@@ -1311,6 +1356,17 @@ export class WorkflowGateBroker {
1311
1356
  return this.continuations.get(gateId)?.isLive(gateId) === true;
1312
1357
  }
1313
1358
 
1359
+ private recordContinuationLoss(gateId: string): void {
1360
+ this.#continuationLost.add(gateId);
1361
+ const lost = this.store.get(gateId);
1362
+ if (!lost) return;
1363
+ try {
1364
+ this.hooks.continuationLost?.(lost);
1365
+ } catch {
1366
+ // A settlement notification must never replace the original resolution error.
1367
+ }
1368
+ }
1369
+
1314
1370
  hasRecoverableAcceptedGate(): boolean {
1315
1371
  return this.store
1316
1372
  .list()
@@ -1395,8 +1451,10 @@ export class WorkflowGateBroker {
1395
1451
  .filter(
1396
1452
  (
1397
1453
  record,
1398
- ): record is PersistedGate & { status: "quarantined"; lifecycle: WorkflowGateDiagnostic["lifecycle"] } =>
1399
- record.status === "quarantined" && record.lifecycle !== undefined,
1454
+ ): record is PersistedGate & {
1455
+ status: "quarantined";
1456
+ lifecycle: WorkflowGateDiagnostic["lifecycle"];
1457
+ } => record.status === "quarantined" && record.lifecycle !== undefined,
1400
1458
  )
1401
1459
  .sort(
1402
1460
  (left, right) =>
@@ -1408,6 +1466,7 @@ export class WorkflowGateBroker {
1408
1466
  id: `diagnostic:${record.gate.gate_id}`,
1409
1467
  tag: "quarantined",
1410
1468
  lifecycle: record.lifecycle,
1469
+ answer_recorded: Object.hasOwn(record, "answer"),
1411
1470
  }));
1412
1471
  }
1413
1472
 
@@ -1421,8 +1480,38 @@ export class WorkflowGateBroker {
1421
1480
  this.hasLiveContinuation(record.gate.gate_id),
1422
1481
  )
1423
1482
  .sort(compareGates)
1424
- .map(record => ({ ...record.gate, id: `pending:${record.gate.gate_id}`, tag: "pending" }));
1425
- return [...pending, ...this.listGateDiagnostics()];
1483
+ .map(record => ({
1484
+ ...record.gate,
1485
+ id: `pending:${record.gate.gate_id}`,
1486
+ tag: "pending" as const,
1487
+ answer_recorded: false as const,
1488
+ }));
1489
+ const accepted: WorkflowGateResolutionDiagnostic[] = this.store
1490
+ .list()
1491
+ .filter((record): record is PersistedGate & { status: "accepted" } => record.status === "accepted")
1492
+ .sort(
1493
+ (left, right) =>
1494
+ (right.resolution?.resolved_at ?? "").localeCompare(left.resolution?.resolved_at ?? "") ||
1495
+ right.gate.gate_id.localeCompare(left.gate.gate_id),
1496
+ )
1497
+ .slice(0, MAX_ACCEPTED_WORKFLOW_GATE_QUERY_RECORDS)
1498
+ .map(record => ({
1499
+ ...record.gate,
1500
+ id: `diagnostic:${record.gate.gate_id}`,
1501
+ tag: "accepted" as const,
1502
+ answer_recorded: true as const,
1503
+ resolved_at: record.resolution?.resolved_at ?? record.gate.created_at,
1504
+ post_accept_disposition: this.#continuationLost.has(record.gate.gate_id)
1505
+ ? "continuation_lost"
1506
+ : record.advanced
1507
+ ? record.ownerInstanceId === this.instanceId
1508
+ ? "advanced"
1509
+ : "unknown"
1510
+ : record.terminalized === true
1511
+ ? "terminalized"
1512
+ : "accepted",
1513
+ }));
1514
+ return [...pending, ...accepted, ...this.listGateDiagnostics()];
1426
1515
  }
1427
1516
 
1428
1517
  /** Open and emit a gate. The pending record is persisted BEFORE emission. */
@@ -1516,6 +1605,17 @@ export class WorkflowGateBroker {
1516
1605
  const sameBody = record.responseHash === responseHash;
1517
1606
  const sameKey = record.idempotencyKey === response.idempotency_key;
1518
1607
  if (response.idempotency_key !== undefined && sameKey && sameBody) {
1608
+ // Same provenance rule as `lookupCompletedResolution`: an idempotent replay must
1609
+ // not hand back an accepted resolution for a continuation this runtime cannot
1610
+ // prove was resolved. Without this, a direct `resolveGate()` retry bypassed the
1611
+ // lookup entirely and reproduced the original false success (#5599 review).
1612
+ if (this.#continuationLost.has(response.gate_id) || record.ownerInstanceId !== this.instanceId) {
1613
+ this.hooks.audit?.({ event: "gate_response_replay_unproven", gate_id: response.gate_id });
1614
+ throw new WorkflowGateBrokerError(
1615
+ "unknown_gate",
1616
+ `accepted gate ${response.gate_id} cannot be replayed: this runtime cannot prove its continuation was resolved`,
1617
+ );
1618
+ }
1519
1619
  this.hooks.audit?.({ event: "gate_response_idempotent_replay", gate_id: response.gate_id });
1520
1620
  return record.resolution as WorkflowGateResolution;
1521
1621
  }
@@ -1609,7 +1709,16 @@ export class WorkflowGateBroker {
1609
1709
  `accepted gate ${response.gate_id} lost its continuation before advance completed`,
1610
1710
  );
1611
1711
  this.store.put({ ...latest, advanced: true });
1612
- await this.hooks.completeAccepted?.(this.store.get(response.gate_id) as PersistedGate);
1712
+ // `advanced:true` is already durable, so a throw here cannot be undone — but it
1713
+ // must not be reported as a completed resolution either. Mark the loss before
1714
+ // rethrowing so `lookupCompletedResolution` stops claiming completion for a
1715
+ // continuation that was never resolved (#5599).
1716
+ try {
1717
+ await this.hooks.completeAccepted?.(this.store.get(response.gate_id) as PersistedGate);
1718
+ } catch (error) {
1719
+ this.recordContinuationLoss(response.gate_id);
1720
+ throw error;
1721
+ }
1613
1722
  this.continuations.get(response.gate_id)?.release?.(response.gate_id);
1614
1723
  this.continuations.delete(response.gate_id);
1615
1724
  return resolution;
@@ -1659,7 +1768,15 @@ export class WorkflowGateBroker {
1659
1768
  if (latest?.status !== "accepted" || latest.advanced || !this.hasLiveContinuation(listed.gate.gate_id))
1660
1769
  return;
1661
1770
  this.store.put({ ...latest, advanced: true });
1662
- await this.hooks.completeAccepted?.(this.store.get(latest.gate.gate_id) as PersistedGate);
1771
+ // Same durable-commit-then-resolve ordering as `resolve()`; mark the
1772
+ // loss so a recovery attempt cannot leave behind a record that claims
1773
+ // completion its continuation never received (#5599).
1774
+ try {
1775
+ await this.hooks.completeAccepted?.(this.store.get(latest.gate.gate_id) as PersistedGate);
1776
+ } catch (error) {
1777
+ this.recordContinuationLoss(latest.gate.gate_id);
1778
+ throw error;
1779
+ }
1663
1780
  this.continuations.get(latest.gate.gate_id)?.release?.(latest.gate.gate_id);
1664
1781
  this.continuations.delete(latest.gate.gate_id);
1665
1782
  this.hooks.audit?.({ event: "gate_advance_recovered", gate_id: latest.gate.gate_id });
@@ -375,12 +375,26 @@ export interface WorkflowGateDiagnostic extends WorkflowGate {
375
375
  id: string;
376
376
  tag: "quarantined";
377
377
  lifecycle: WorkflowGateLifecycle;
378
+ /** Whether the durable broker retained an answer for this gate. */
379
+ answer_recorded: boolean;
380
+ }
381
+
382
+ /** Durable acceptance evidence for a gate that is no longer pending. */
383
+ export interface WorkflowGateResolutionDiagnostic extends WorkflowGate {
384
+ id: string;
385
+ tag: "accepted";
386
+ /** True when the accepted record contains the answer body. */
387
+ answer_recorded: true;
388
+ resolved_at: string;
389
+ /** Single post-accept disposition; raw answers and derived answer values stay private. */
390
+ post_accept_disposition: "accepted" | "terminalized" | "advanced" | "continuation_lost" | "unknown";
378
391
  }
379
392
 
380
393
  /** Stable Q12 row preserving the root WorkflowGate shape. */
381
394
  export type WorkflowGateQueryRecord =
382
- | (WorkflowGate & { id: string; tag: "pending"; lifecycle?: undefined })
383
- | WorkflowGateDiagnostic;
395
+ | (WorkflowGate & { id: string; tag: "pending"; lifecycle?: undefined; answer_recorded: false })
396
+ | WorkflowGateDiagnostic
397
+ | WorkflowGateResolutionDiagnostic;
384
398
 
385
399
  /** Inbound: the agent's answer to a workflow gate. */
386
400
  export interface WorkflowGateResponse {
@@ -409,7 +409,7 @@ export interface InteractiveModeContext {
409
409
  handleHandoffCommand(customInstructions?: string): Promise<void>;
410
410
  handleContributionPrepCommand(customInstructions?: string): Promise<void>;
411
411
  handleMoveCommand(targetPath: string): Promise<void>;
412
- handleRenameCommand(title: string): Promise<void>;
412
+ handleRenameCommand(title?: string): Promise<void>;
413
413
  handleMemoryCommand(text: string): Promise<void>;
414
414
  handleSTTToggle(): Promise<void>;
415
415
  executeCompaction(
@@ -490,7 +490,7 @@ export interface InteractiveModeContext {
490
490
  >;
491
491
  goalModeController: Pick<
492
492
  import("./controllers/goal-mode-controller").GoalModeController,
493
- "enabled" | "paused" | "handleCommand"
493
+ "enabled" | "paused" | "handleCommand" | "cancelContinuation" | "scheduleContinuation"
494
494
  >;
495
495
  setHookWidget(key: string, content: ExtensionWidgetContent, options?: ExtensionWidgetOptions): void;
496
496
  setHookStatus(key: string, text: string | undefined): void;
@@ -5,6 +5,7 @@ Routing:
5
5
  - Every task that requires a rendered page, authenticated/private browser state, live tabs, browser UI, screenshots, downloads behind cookies, history, saved credentials, or profile data MUST use Bash to invoke the installed Aside CLI.
6
6
  - Default to `aside repl '<JavaScript>'` for deterministic Playwright inspection and actions, even when the answer is unknown but the procedure is discoverable from `snapshot(page, { interactive: true })`.
7
7
  - Use `aside exec '<prompt>'` only for runtime judgment, source-heavy research, browser-history search, MFA or opaque password autofill, approval/notification waits, long monitoring, multi-site synthesis, routines, or work worth a second model. Continue with `aside exec --session <id> '<follow-up>'`. Use `--account`, `--model`, `--provider`, `--speed`, or `--effort` only when the task requires overriding user defaults.
8
+ - Declare every Aside invocation on the Bash call itself with the structured `activity` argument: `{"kind":"browser","provider":"aside","mode":"repl"}` for `aside repl`, and `{"kind":"browser","provider":"aside","mode":"exec"}` for `aside exec` including `--session <id>` follow-ups. The declaration names the operation, not the command spelling: send it unchanged across wrappers, env prefixes, absolute CLI paths, quoting, and multiline commands, and omit it on Bash calls that do not invoke Aside.
8
9
  - Cookie-free public HTTP content that does not require rendered or authenticated browser state may use GJC `read` directly.
9
10
 
10
11
  Deterministic procedure:
@@ -1,2 +1,2 @@
1
- Generate a 3-6 word title for a coding session from the user's first message. Capture the main task or topic.
1
+ Generate a 3-6 word title for a coding session from the supplied user message or conversation digest. If multiple messages are supplied, identify the primary/current task from the digest, weighting the newest substantive message highest; do not assume the first message is the task. If one message is supplied, capture its main task or topic.
2
2
  Output ONLY the title. No quotes or trailing punctuation.
@@ -17,7 +17,7 @@ Executes bash command in shell session for terminal operations like git, bun, ca
17
17
  - Use `async: true` for long-running commands when you don't need immediate output; the call returns a background job ID and the result is delivered automatically as a follow-up.
18
18
  {{/if}}
19
19
  {{#if foregroundFoldEnabled}}
20
- - In the interactive TUI, the user can press the fold chord twice (default `Alt+Shift+B`, plus `Cmd+B` on macOS; remappable via the `app.tool.backgroundFold` keybinding) while a foreground command is still running to fold it into a background job. All three command surfaces fold: managed non-PTY bash, editor/ACP client-terminal commands, and PTY-mode commands. A folded command keeps its original timeout and is never killed or restarted by folding; a folded PTY continues output-only, so it stops accepting input. The turn then ends cleanly and a later turn resumes automatically with the command's result, so the interrupted task is finished rather than abandoned. `task`/`subagent` waits are deliberately NOT foldable. Do not instruct users to use raw shell `Ctrl+Z`/`bg` inside the GJC TUI; ownership and output routing are not safe there.
20
+ - In the interactive TUI, the user can press the fold chord twice (default `Alt+Shift+B`, plus `Cmd+B` on macOS; remappable via the `app.tool.backgroundFold` keybinding) while a foreground command is still running to fold it into a background job. All three command surfaces fold: managed non-PTY bash, editor/ACP client-terminal commands, and PTY-mode commands. A folded command keeps its original timeout and is never killed or restarted by folding; a folded PTY continues output-only, so it stops accepting input. The turn then ends cleanly and a later turn resumes automatically with the command's result, so the interrupted task is finished rather than abandoned. The `job` tool's own await uses the same steer-fold behavior and grace window; `task`/`subagent` waits are deliberately NOT foldable. Do not instruct users to use raw shell `Ctrl+Z`/`bg` inside the GJC TUI; ownership and output routing are not safe there.
21
21
  - A user steer folds the same way: when the user sends a message while a foreground command has already run for at least 2 seconds, the command is folded into a background job and this call returns the background-start result plus the line `Folded into background job <id> because a user steer arrived; the command keeps running with its original timeout and its result will wake a later turn.` The steer is then delivered at this tool boundary, so handle it next; do not re-run the folded command. Steers that arrive within the first 2 seconds let the command finish normally. This applies only while `busyPromptMode` is `steer`; `toolInterruptPolicy` is not a gate, since a fold never kills the command.
22
22
  {{/if}}
23
23
  </instruction>
@@ -2,7 +2,7 @@ Inspects, waits, or cancels async jobs.
2
2
 
3
3
  Background job results are delivered automatically when complete. Jobs that back task subagents should be controlled via the `subagent` tool when it is available; use `job` for non-subagent jobs (async bash, monitors) and as a compatibility fallback. Running job output stays quiet by default to avoid flooding the conversation; use `tail` when you explicitly want to show/reopen retained output. Reach for this tool only when you need to inspect or intervene.
4
4
 
5
- In the interactive TUI, a running foreground command can be folded into a background job by pressing the fold chord twice (default `Alt+Shift+B`, plus `Cmd+B` on macOS; remappable via `app.tool.backgroundFold`), or automatically when the user sends a steer after the command has run for at least 2 seconds (with `busyPromptMode=steer` (`toolInterruptPolicy` is not a gate)). This covers managed non-PTY bash, editor/ACP client-terminal commands, and PTY-mode commands. A folded job keeps its original deadline, is never killed or restarted by folding, and its result wakes a later turn automatically; a folded PTY continues output-only and no longer accepts input. Job listings expose `foldReason` (`steer`, `chord`, `timer`, or `sdk_control`) beside `backgrounded` so you can tell why a job left the foreground. `task`/`subagent` waits are not foldable. Raw shell `Ctrl+Z`/`bg` is not the supported path inside GJC because it bypasses job ownership and output-routing contracts.
5
+ In the interactive TUI, a running foreground command can be folded into a background job by pressing the fold chord twice (default `Alt+Shift+B`, plus `Cmd+B` on macOS; remappable via `app.tool.backgroundFold`), or automatically when the user sends a steer after the command has run for at least 2 seconds (with `busyPromptMode=steer` (`toolInterruptPolicy` is not a gate)). This covers managed non-PTY bash, editor/ACP client-terminal commands, and PTY-mode commands. A folded job keeps its original deadline, is never killed or restarted by folding, and its result wakes a later turn automatically; a folded PTY continues output-only and no longer accepts input. A `job` await also folds after the same 2-second grace window when a steer arrives, returning immediately with the still-running job id(s) while those jobs keep their original deadlines and wake a later turn with their results. Job listings expose `foldReason` (`steer`, `chord`, `timer`, or `sdk_control`) beside `backgrounded` so you can tell why a job left the foreground. `task`/`subagent` waits are not foldable. Raw shell `Ctrl+Z`/`bg` is not the supported path inside GJC because it bypasses job ownership and output-routing contracts.
6
6
 
7
7
  # Operations
8
8
 
@@ -73,6 +73,8 @@ For `.sqlite`, `.sqlite3`, `.db`, `.db3`:
73
73
 
74
74
  `agent://<id>`, `artifact://<id>`, `rule://<name>`, and `local://<name>.md` resolve transparently and accept the same line selectors as filesystem paths. Use `artifact://<id>` to recover full output that a previous bash/eval/tool result spilled or truncated.
75
75
 
76
+ Bundled skills have no filesystem home, so the skill tool and skill discovery report them as `embedded:gjc/skills/<name>/SKILL.md`; read that identifier verbatim. Bundled skill fragments, when surfaced, likewise use `embedded:gjc/skill-fragments/...` identifiers.
77
+
76
78
  <critical>
77
79
  - Always include `path`; never call `read` with `{}`.
78
80
  - For line ranges, append the selector to `path`.