@gajae-code/coding-agent 0.10.1 → 0.11.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 (474) hide show
  1. package/CHANGELOG.md +70 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/cli/args.d.ts +4 -5
  4. package/dist/types/cli/daemon-cli.d.ts +12 -1
  5. package/dist/types/cli/notify-cli.d.ts +21 -1
  6. package/dist/types/cli.d.ts +3 -0
  7. package/dist/types/commands/daemon.d.ts +39 -0
  8. package/dist/types/commands/launch.d.ts +3 -0
  9. package/dist/types/commands/notify.d.ts +28 -1
  10. package/dist/types/commands/sdk.d.ts +33 -0
  11. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  12. package/dist/types/config/model-profile-activation.d.ts +35 -15
  13. package/dist/types/config/model-profiles.d.ts +11 -5
  14. package/dist/types/config/model-registry.d.ts +3 -3
  15. package/dist/types/config/model-resolver.d.ts +39 -6
  16. package/dist/types/config/model-selector-value.d.ts +17 -0
  17. package/dist/types/config/models-config-schema.d.ts +10 -6
  18. package/dist/types/config/settings-schema.d.ts +133 -6
  19. package/dist/types/config/settings.d.ts +63 -35
  20. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  21. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  22. package/dist/types/daemon/builtin.d.ts +6 -5
  23. package/dist/types/daemon/control-types.d.ts +1 -1
  24. package/dist/types/discovery/mcp-json.d.ts +12 -1
  25. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  26. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  27. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  28. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  29. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  30. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  31. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  32. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  33. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  34. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  35. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  36. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  37. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  38. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  39. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  40. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  41. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  42. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  43. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  44. package/dist/types/harness-control-plane/types.d.ts +3 -4
  45. package/dist/types/lsp/index.d.ts +1 -1
  46. package/dist/types/main.d.ts +32 -38
  47. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  48. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  49. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  50. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  51. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  52. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  53. package/dist/types/modes/components/gajae-pet-widget.d.ts +1 -0
  54. package/dist/types/modes/components/model-selector.d.ts +1 -0
  55. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  56. package/dist/types/modes/components/pet-capability.d.ts +37 -0
  57. package/dist/types/modes/components/pet-selector.d.ts +1 -1
  58. package/dist/types/modes/components/settings-selector.d.ts +15 -4
  59. package/dist/types/modes/components/welcome.d.ts +1 -1
  60. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  61. package/dist/types/modes/index.d.ts +0 -4
  62. package/dist/types/modes/interactive-mode.d.ts +5 -1
  63. package/dist/types/modes/runtime-init.d.ts +2 -2
  64. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  65. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  66. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  67. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  68. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  69. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +169 -30
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  72. package/dist/types/modes/types.d.ts +16 -1
  73. package/dist/types/runtime-mcp/client.d.ts +2 -0
  74. package/dist/types/runtime-mcp/config.d.ts +5 -1
  75. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  76. package/dist/types/runtime-mcp/types.d.ts +4 -0
  77. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  78. package/dist/types/sdk/acp/index.d.ts +2 -0
  79. package/dist/types/sdk/broker/broker.d.ts +53 -0
  80. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  81. package/dist/types/sdk/broker/ensure.d.ts +33 -0
  82. package/dist/types/sdk/broker/identity.d.ts +3 -0
  83. package/dist/types/sdk/broker/index.d.ts +8 -0
  84. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  85. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  86. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  87. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  88. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  89. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  90. package/dist/types/sdk/broker/transport.d.ts +9 -0
  91. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  92. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  93. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  94. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  95. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  96. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  97. package/dist/types/sdk/bus/config.d.ts +274 -0
  98. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  99. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  100. package/dist/types/sdk/bus/discord-daemon.d.ts +45 -0
  101. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  102. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  103. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  104. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  105. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  107. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  108. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  109. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  110. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  111. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  112. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  113. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  114. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  115. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  116. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  117. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  118. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  119. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +55 -17
  121. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  122. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  123. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  124. package/dist/types/sdk/cli/index.d.ts +1 -0
  125. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  126. package/dist/types/sdk/client/client.d.ts +1 -0
  127. package/dist/types/sdk/client/discovery.d.ts +27 -0
  128. package/dist/types/sdk/client/index.d.ts +2 -0
  129. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  130. package/dist/types/sdk/host/control/index.d.ts +2 -0
  131. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  132. package/dist/types/sdk/host/events.d.ts +35 -0
  133. package/dist/types/sdk/host/host.d.ts +35 -0
  134. package/dist/types/sdk/host/index.d.ts +4 -0
  135. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  136. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  137. package/dist/types/sdk/host/query/index.d.ts +3 -0
  138. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  139. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  140. package/dist/types/sdk/host/types.d.ts +32 -0
  141. package/dist/types/sdk/index.d.ts +6 -0
  142. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  143. package/dist/types/sdk/mcp/index.d.ts +1 -0
  144. package/dist/types/sdk/mcp/server.d.ts +37 -0
  145. package/dist/types/sdk/models.d.ts +44 -0
  146. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  147. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  148. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  149. package/dist/types/sdk/startup-capability.d.ts +50 -0
  150. package/dist/types/session/agent-session.d.ts +114 -21
  151. package/dist/types/session/default-model-selection.d.ts +25 -0
  152. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  153. package/dist/types/session/session-manager.d.ts +58 -1
  154. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  155. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  156. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  157. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  158. package/dist/types/tools/browser/launch.d.ts +22 -0
  159. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  160. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  161. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  162. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  163. package/dist/types/tools/browser/registry.d.ts +19 -0
  164. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  165. package/dist/types/tools/index.d.ts +8 -8
  166. package/package.json +34 -13
  167. package/scripts/build-sdk-package-smoke.ts +94 -0
  168. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  169. package/scripts/compile-args.ts +4 -2
  170. package/scripts/g005-daemon-smoke.ts +4 -5
  171. package/scripts/g011-daemon-path-smoke.ts +5 -5
  172. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  173. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  174. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  175. package/scripts/manifest-schema.ts +124 -0
  176. package/scripts/run-test-manifest.ts +153 -0
  177. package/scripts/run-threat-model-check.ts +157 -0
  178. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  179. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  180. package/src/append-only-mode.ts +1 -1
  181. package/src/cli/args.ts +43 -12
  182. package/src/cli/auth-gateway-cli.ts +2 -2
  183. package/src/cli/config-cli.ts +2 -1
  184. package/src/cli/daemon-cli.ts +63 -14
  185. package/src/cli/list-models.ts +1 -1
  186. package/src/cli/notify-cli.ts +288 -286
  187. package/src/cli.ts +21 -2
  188. package/src/commands/daemon.ts +50 -6
  189. package/src/commands/harness.ts +93 -36
  190. package/src/commands/launch.ts +5 -2
  191. package/src/commands/mcp-serve.ts +19 -12
  192. package/src/commands/notify.ts +36 -3
  193. package/src/commands/sdk.ts +426 -0
  194. package/src/commit/agentic/agent.ts +1 -0
  195. package/src/config/atomic-yaml-patch.ts +423 -0
  196. package/src/config/model-profile-activation.ts +240 -89
  197. package/src/config/model-profiles.ts +37 -34
  198. package/src/config/model-registry.ts +51 -26
  199. package/src/config/model-resolver.ts +138 -51
  200. package/src/config/model-selector-value.ts +50 -0
  201. package/src/config/models-config-schema.ts +14 -21
  202. package/src/config/settings-schema.ts +128 -10
  203. package/src/config/settings.ts +1120 -158
  204. package/src/coordinator-mcp/model-preset.ts +74 -20
  205. package/src/coordinator-mcp/server.ts +1597 -3052
  206. package/src/daemon/builtin.ts +8 -5
  207. package/src/daemon/control-types.ts +1 -1
  208. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  209. package/src/discovery/mcp-json.ts +327 -20
  210. package/src/extensibility/custom-tools/types.ts +1 -1
  211. package/src/extensibility/extensions/compact-handler.ts +3 -3
  212. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  213. package/src/extensibility/extensions/loader.ts +69 -5
  214. package/src/extensibility/extensions/runner.ts +112 -4
  215. package/src/extensibility/extensions/types.ts +176 -17
  216. package/src/extensibility/hooks/types.ts +1 -1
  217. package/src/extensibility/slash-commands.ts +3 -3
  218. package/src/gjc-runtime/launch-tmux.ts +170 -86
  219. package/src/gjc-runtime/psmux-detect.ts +82 -4
  220. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  221. package/src/gjc-runtime/team-runtime.ts +54 -35
  222. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  223. package/src/gjc-runtime/tmux-owner-isolation.ts +5 -2
  224. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  225. package/src/gjc-runtime/ultragoal-guard.ts +53 -6
  226. package/src/gjc-runtime/ultragoal-runtime.ts +155 -3
  227. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  228. package/src/harness-control-plane/operate.ts +9 -9
  229. package/src/harness-control-plane/owner.ts +283 -39
  230. package/src/harness-control-plane/receipts.ts +0 -1
  231. package/src/harness-control-plane/sdk-transport.ts +395 -0
  232. package/src/harness-control-plane/session-transport.ts +94 -0
  233. package/src/harness-control-plane/types.ts +1 -1
  234. package/src/internal-urls/docs-index.generated.ts +36 -37
  235. package/src/lsp/client.ts +42 -6
  236. package/src/lsp/index.ts +2 -2
  237. package/src/main.ts +299 -204
  238. package/src/modes/DESIGN.md +258 -0
  239. package/src/modes/acp/acp-agent.ts +1228 -2612
  240. package/src/modes/acp/acp-client-bridge.ts +2 -20
  241. package/src/modes/acp/acp-event-mapper.ts +18 -2
  242. package/src/modes/acp/acp-mode.ts +8 -36
  243. package/src/modes/acp/permission-mode.ts +25 -0
  244. package/src/modes/acp/startup-options.ts +6 -0
  245. package/src/modes/components/agent-dashboard.ts +37 -17
  246. package/src/modes/components/custom-editor.ts +1 -0
  247. package/src/modes/components/gajae-pet-widget.ts +169 -20
  248. package/src/modes/components/model-selector.ts +93 -35
  249. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  250. package/src/modes/components/pet-capability.ts +115 -0
  251. package/src/modes/components/pet-selector.ts +4 -6
  252. package/src/modes/components/settings-selector.ts +86 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +1 -2
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +357 -12
  257. package/src/modes/controllers/input-controller.ts +43 -13
  258. package/src/modes/controllers/selector-controller.ts +671 -44
  259. package/src/modes/index.ts +0 -22
  260. package/src/modes/interactive-mode.ts +108 -24
  261. package/src/modes/runtime-init.ts +298 -6
  262. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  263. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  264. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  265. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  266. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  267. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1254 -87
  268. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  269. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  270. package/src/modes/types.ts +16 -1
  271. package/src/runtime-mcp/client.ts +94 -19
  272. package/src/runtime-mcp/config.ts +27 -15
  273. package/src/runtime-mcp/manager.ts +343 -105
  274. package/src/runtime-mcp/oauth-flow.ts +42 -12
  275. package/src/runtime-mcp/transports/http.ts +49 -19
  276. package/src/runtime-mcp/transports/stdio.ts +47 -28
  277. package/src/runtime-mcp/types.ts +10 -0
  278. package/src/sdk/acp/adapter.ts +418 -0
  279. package/src/sdk/acp/index.ts +2 -0
  280. package/src/sdk/broker/broker.ts +642 -0
  281. package/src/sdk/broker/discovery.ts +94 -0
  282. package/src/sdk/broker/ensure.ts +249 -0
  283. package/src/sdk/broker/identity.ts +42 -0
  284. package/src/sdk/broker/index.ts +8 -0
  285. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  286. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  287. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  288. package/src/sdk/broker/lifecycle.ts +2157 -0
  289. package/src/sdk/broker/process-incarnation.ts +159 -0
  290. package/src/sdk/broker/runtime.ts +164 -0
  291. package/src/sdk/broker/session-index.ts +318 -0
  292. package/src/sdk/broker/state-version.ts +23 -0
  293. package/src/sdk/broker/transport.ts +125 -0
  294. package/src/sdk/bus/chat-command-policy.ts +107 -0
  295. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  296. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  297. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  298. package/src/sdk/bus/chat-effect-journal.ts +353 -0
  299. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  300. package/src/sdk/bus/config.ts +433 -0
  301. package/src/sdk/bus/conversation-store.ts +391 -0
  302. package/src/sdk/bus/discord-conversation.ts +85 -0
  303. package/src/sdk/bus/discord-daemon.ts +2275 -0
  304. package/src/sdk/bus/discord-live-provider.ts +521 -0
  305. package/src/sdk/bus/discord-provider.ts +56 -0
  306. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  307. package/src/sdk/bus/index.ts +3943 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  309. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  310. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  311. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  312. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  313. package/src/sdk/bus/natives-augment.d.ts +38 -0
  314. package/src/sdk/bus/notification-orchestration.ts +535 -0
  315. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  316. package/src/sdk/bus/session-control.ts +333 -0
  317. package/src/sdk/bus/slack-conversation.ts +74 -0
  318. package/src/sdk/bus/slack-daemon.ts +2144 -0
  319. package/src/sdk/bus/slack-live-provider.ts +380 -0
  320. package/src/sdk/bus/slack-provider.ts +76 -0
  321. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  322. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  323. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  324. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  325. package/src/{notifications → sdk/bus}/telegram-daemon.ts +502 -54
  326. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  327. package/src/sdk/bus/telegram-setup.ts +663 -0
  328. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  329. package/src/sdk/cli/index.ts +1 -0
  330. package/src/sdk/cli/session-cli.ts +275 -0
  331. package/src/sdk/client/client.ts +1 -0
  332. package/src/sdk/client/discovery.ts +108 -0
  333. package/src/sdk/client/index.ts +2 -0
  334. package/src/sdk/host/control/dispatch.ts +367 -0
  335. package/src/sdk/host/control/index.ts +10 -0
  336. package/src/sdk/host/control/operations.ts +63 -0
  337. package/src/sdk/host/events.ts +91 -0
  338. package/src/sdk/host/host.ts +296 -0
  339. package/src/sdk/host/index.ts +4 -0
  340. package/src/sdk/host/query/cursor.ts +189 -0
  341. package/src/sdk/host/query/handlers.ts +533 -0
  342. package/src/sdk/host/query/index.ts +3 -0
  343. package/src/sdk/host/query/revision-store.ts +1126 -0
  344. package/src/sdk/host/reverse-leases.ts +325 -0
  345. package/src/sdk/host/types.ts +29 -0
  346. package/src/sdk/index.ts +13 -0
  347. package/src/sdk/lifecycle-session.ts +39 -0
  348. package/src/sdk/mcp/index.ts +1 -0
  349. package/src/sdk/mcp/server.ts +332 -0
  350. package/src/sdk/models.ts +168 -0
  351. package/src/sdk/protocol/adapter-validation.ts +48 -0
  352. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  353. package/src/sdk/protocol/operation-registry.ts +312 -0
  354. package/src/{sdk.ts → sdk/session.ts} +339 -212
  355. package/src/sdk/startup-capability.ts +189 -0
  356. package/src/session/agent-session.ts +2470 -866
  357. package/src/session/default-model-selection.ts +93 -0
  358. package/src/session/fallback-chain-controller.ts +136 -0
  359. package/src/session/session-manager.ts +447 -13
  360. package/src/session/session-storage.ts +8 -1
  361. package/src/setup/credential-auto-import.ts +290 -35
  362. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  363. package/src/slash-commands/builtin-registry.ts +33 -30
  364. package/src/task/executor.ts +62 -13
  365. package/src/tools/ask-answer-registry.ts +1 -1
  366. package/src/tools/ask.ts +13 -8
  367. package/src/tools/browser/STEALTH-THIRD-PARTY-NOTICES.md +26 -0
  368. package/src/tools/browser/benchmark/detector-report.ts +157 -0
  369. package/src/tools/browser/benchmark/run-suite.ts +39 -0
  370. package/src/tools/browser/launch.ts +124 -19
  371. package/src/tools/browser/profile-discovery.ts +63 -0
  372. package/src/tools/browser/profile-posture.ts +59 -0
  373. package/src/tools/browser/profile-reuse.ts +102 -0
  374. package/src/tools/browser/profile-warmup.ts +109 -0
  375. package/src/tools/browser/registry.ts +87 -11
  376. package/src/tools/browser/tab-protocol.ts +1 -0
  377. package/src/tools/browser/tab-supervisor.ts +1 -0
  378. package/src/tools/browser/tab-worker.ts +1 -1
  379. package/src/tools/browser.ts +6 -0
  380. package/src/tools/index.ts +8 -8
  381. package/src/tools/puppeteer/14_stealth_permissions.txt +57 -0
  382. package/src/tools/puppeteer/15_stealth_webrtc.txt +60 -0
  383. package/src/tools/telegram-send.ts +2 -2
  384. package/vendor/insane-search/MANIFEST.json +2 -1
  385. package/vendor/insane-search/engine/bias_check.py +4 -1
  386. package/vendor/insane-search/engine/phase0.py +26 -1
  387. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  388. package/dist/types/modes/bridge/auth.d.ts +0 -12
  389. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  390. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  391. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  392. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  393. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  394. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  395. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  396. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  397. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  398. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  399. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  400. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  401. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  402. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  403. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  404. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  405. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  406. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  407. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  408. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  409. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  410. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  411. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  412. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  413. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  414. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  415. package/dist/types/notifications/config.d.ts +0 -132
  416. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  417. package/src/modes/bridge/auth.ts +0 -41
  418. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  419. package/src/modes/bridge/bridge-mode.ts +0 -675
  420. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  421. package/src/modes/bridge/event-stream.ts +0 -70
  422. package/src/modes/rpc/host-tools.ts +0 -1
  423. package/src/modes/rpc/host-uris.ts +0 -1
  424. package/src/modes/rpc/rpc-client.ts +0 -1166
  425. package/src/modes/rpc/rpc-mode.ts +0 -1029
  426. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  427. package/src/modes/rpc/rpc-types.ts +0 -637
  428. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  429. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  430. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  431. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  432. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  433. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  434. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  435. package/src/modes/shared/agent-wire/responses.ts +0 -17
  436. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  437. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  438. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  439. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  440. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  441. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  442. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  443. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  444. package/src/notifications/config.ts +0 -219
  445. package/src/notifications/index.ts +0 -1835
  446. package/src/notifications/telegram-daemon-cli.ts +0 -243
  447. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  448. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  449. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  450. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  462. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  463. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -7,7 +7,10 @@ import { safeStderrWrite } from "@gajae-code/utils/safe-stderr";
7
7
  import type { Args } from "../cli/args";
8
8
  import { tmuxRuntimeSessionPath } from "./session-layout";
9
9
  import {
10
+ GJC_COORDINATOR_SESSION_BRANCH_ENV,
10
11
  GJC_COORDINATOR_SESSION_ID_ENV,
12
+ GJC_COORDINATOR_SESSION_LAUNCH_ID_ENV,
13
+ GJC_COORDINATOR_SESSION_READINESS_FILE_ENV,
11
14
  GJC_COORDINATOR_SESSION_STATE_FILE_ENV,
12
15
  GJC_TMUX_OWNER_GENERATION_ENV,
13
16
  GJC_TMUX_OWNER_SERVER_KEY_ENV,
@@ -46,18 +49,25 @@ import {
46
49
  type GjcTmuxSessionStatus,
47
50
  proveGjcTmuxSessionMutationTarget,
48
51
  } from "./tmux-sessions";
52
+ import {
53
+ buildWindowsPowerShellInnerCommand,
54
+ GJC_TMUX_LAUNCHED_ENV,
55
+ type WindowsPowerShellInnerCommandOptions,
56
+ } from "./windows-powershell-command";
49
57
 
58
+ export type { WindowsPowerShellInnerCommandOptions };
50
59
  export {
51
60
  buildGjcTmuxExactSessionTarget,
52
61
  buildGjcTmuxProfileCommands,
62
+ buildWindowsPowerShellInnerCommand,
53
63
  GJC_DEFAULT_TMUX_SESSION,
54
64
  GJC_TMUX_COMMAND_ENV,
65
+ GJC_TMUX_LAUNCHED_ENV,
55
66
  GJC_TMUX_MOUSE_ENV,
56
67
  GJC_TMUX_PROFILE_ENV,
57
68
  GJC_TMUX_SESSION_PREFIX,
58
69
  };
59
70
 
60
- export const GJC_TMUX_LAUNCHED_ENV = "GJC_TMUX_LAUNCHED";
61
71
  export const GJC_LAUNCH_POLICY_ENV = "GJC_LAUNCH_POLICY";
62
72
  export const GJC_TMUX_WINDOW_LABEL_MAX_WIDTH = 48;
63
73
 
@@ -163,6 +173,108 @@ function allowsExistingTmuxAttach(parsed: Args, env: NodeJS.ProcessEnv): boolean
163
173
  // value-less resume can show the session picker and valued resume can honor the target.
164
174
  return Boolean(parsed.continue || explicitTmuxSessionName(env));
165
175
  }
176
+ type WindowsPsmuxCompatibilityState = "fresh" | "continuation" | "managed";
177
+
178
+ function windowsPsmuxCompatibilityState(plan: TmuxLaunchPlan, env: NodeJS.ProcessEnv): WindowsPsmuxCompatibilityState {
179
+ const marker = (value: string | undefined): boolean => Boolean(value?.trim());
180
+ if (
181
+ marker(env.GJC_SESSION_ID) ||
182
+ marker(env[GJC_COORDINATOR_SESSION_ID_ENV]) ||
183
+ marker(env[GJC_COORDINATOR_SESSION_BRANCH_ENV]) ||
184
+ marker(env[GJC_COORDINATOR_SESSION_LAUNCH_ID_ENV]) ||
185
+ marker(env[GJC_COORDINATOR_SESSION_READINESS_FILE_ENV]) ||
186
+ marker(env[GJC_COORDINATOR_SESSION_STATE_FILE_ENV]) ||
187
+ marker(env[GJC_TMUX_ACTIVE_SESSION_ENV]) ||
188
+ marker(env[GJC_TMUX_OWNER_GENERATION_ENV]) ||
189
+ marker(env[GJC_TMUX_OWNER_STATE_DIR_ENV]) ||
190
+ marker(env[GJC_TMUX_OWNER_SERVER_KEY_ENV]) ||
191
+ Object.entries(env).some(([key, value]) => key.startsWith("GJC_TEAM_") && marker(value))
192
+ )
193
+ return "managed";
194
+ return plan.attachSessionName ? "continuation" : "fresh";
195
+ }
196
+
197
+ type PsmuxSessionInventory =
198
+ | { kind: "available"; names: ReadonlySet<string> }
199
+ | { kind: "no-server" }
200
+ | { kind: "unverifiable"; result: TmuxSpawnResult };
201
+
202
+ function classifyPsmuxSessionInventory(result: TmuxSpawnResult): PsmuxSessionInventory {
203
+ if (result.exitCode === 0) {
204
+ const names = new Set(
205
+ (result.stdout ?? "")
206
+ .split(/\r?\n/)
207
+ .map(name => name.trim())
208
+ .filter(Boolean),
209
+ );
210
+ return { kind: "available", names };
211
+ }
212
+ const stderr = result.stderr?.trim() ?? "";
213
+ if (/\bno server running\b/i.test(stderr)) return { kind: "no-server" };
214
+ return { kind: "unverifiable", result };
215
+ }
216
+
217
+ function launchWindowsPsmuxCompatibilitySession(
218
+ plan: TmuxLaunchPlan,
219
+ env: NodeJS.ProcessEnv,
220
+ spawnSync: TmuxSpawnSync,
221
+ diagnostic: (message: string) => void,
222
+ ): boolean {
223
+ const options: TmuxSpawnOptions = {
224
+ cwd: plan.cwd,
225
+ env,
226
+ stdin: "pipe",
227
+ stdout: "pipe",
228
+ stderr: "pipe",
229
+ captureStderr: true,
230
+ };
231
+ const attachOptions: TmuxSpawnOptions = { ...options, stdin: "inherit", stdout: "inherit", stderr: "inherit" };
232
+ const state = windowsPsmuxCompatibilityState(plan, env);
233
+ if (state === "managed") {
234
+ diagnostic("psmux cannot provide immutable owner identity; refusing managed session creation.\n");
235
+ throw new Error("gjc_tmux_owner_isolation_native_session_identity_unavailable");
236
+ }
237
+
238
+ const targetName = plan.attachSessionName ?? plan.sessionName;
239
+ const inventory = (): PsmuxSessionInventory =>
240
+ classifyPsmuxSessionInventory(spawnSync(plan.tmuxCommand, ["list-sessions", "-F", "#{session_name}"], options));
241
+
242
+ if (state === "continuation") {
243
+ const existing = inventory();
244
+ const detail = existing.kind === "unverifiable" ? existing.result.stderr : undefined;
245
+ diagnostic(
246
+ formatTmuxLaunchDiagnostic(
247
+ existing.kind === "available" && existing.names.has(targetName)
248
+ ? "existing psmux session is name-only and cannot be attached safely"
249
+ : "existing session target not found",
250
+ detail,
251
+ ),
252
+ );
253
+ return true;
254
+ }
255
+
256
+ const before = inventory();
257
+ if (before.kind === "unverifiable") {
258
+ diagnostic(formatTmuxLaunchDiagnostic("fresh session inventory failed", before.result.stderr));
259
+ return true;
260
+ }
261
+ if (before.kind === "available" && before.names.has(targetName)) {
262
+ diagnostic("tmux fresh session target already exists; preserving session without mutation.\n");
263
+ return true;
264
+ }
265
+ const detachedIndex = plan.newSessionArgs.indexOf("-d");
266
+ const foregroundArgs =
267
+ detachedIndex < 0
268
+ ? plan.newSessionArgs
269
+ : [...plan.newSessionArgs.slice(0, detachedIndex), ...plan.newSessionArgs.slice(detachedIndex + 1)];
270
+ const created = spawnSync(plan.tmuxCommand, foregroundArgs, attachOptions);
271
+ if (created.exitCode !== 0) {
272
+ const wrapperWarning = detectCorruptedGjcWrapper();
273
+ const suffix = wrapperWarning ? ` Wrapper warning: ${wrapperWarning}` : "";
274
+ diagnostic(formatTmuxLaunchDiagnostic("foreground new-session failed", created.stderr) + suffix);
275
+ }
276
+ return true;
277
+ }
166
278
 
167
279
  function findExistingSessionForLaunch(context: {
168
280
  env: NodeJS.ProcessEnv;
@@ -214,20 +326,6 @@ function buildPosixTmuxExitMarkerPrefix(markerPath: string): string {
214
326
  ].join("; ");
215
327
  }
216
328
 
217
- function buildPowerShellTmuxExitMarkerFinally(markerPath: string): string {
218
- const markerDir = path.win32.dirname(markerPath);
219
- return [
220
- "} finally {",
221
- "\ttry {",
222
- `\t\tNew-Item -ItemType Directory -Force -Path ${powershellQuote(markerDir)} -ErrorAction Stop | Out-Null`,
223
- "\t\t$__gjcTmuxExitMarker = @{ schema_version = 1; source = 'tmux_inner_shell'; ended_at = (Get-Date).ToUniversalTime().ToString('o'); exit_code = $__gjcTmuxExitCode } | ConvertTo-Json -Compress",
224
- `\t\tSet-Content -LiteralPath ${powershellQuote(markerPath)} -Value $__gjcTmuxExitMarker -Encoding UTF8 -ErrorAction Stop`,
225
- "\t} catch {",
226
- "\t}",
227
- "}",
228
- ].join("\n");
229
- }
230
-
231
329
  interface CommandResolutionContext {
232
330
  cwd: string;
233
331
  argv: string[];
@@ -258,7 +356,13 @@ function isInteractiveRootLaunch(parsed: Args, tty: TtyState): boolean {
258
356
  }
259
357
 
260
358
  function isBunVirtualPath(value: string | undefined): boolean {
261
- return value?.startsWith("/$bunfs/") === true;
359
+ const normalized = value?.trim().replace(/\\/g, "/").toLowerCase();
360
+ return (
361
+ normalized === "/$bunfs" ||
362
+ normalized?.startsWith("/$bunfs/") === true ||
363
+ normalized === "b:/~bun" ||
364
+ normalized?.startsWith("b:/~bun/") === true
365
+ );
262
366
  }
263
367
 
264
368
  const MAX_TMUX_DIAGNOSTIC_DETAIL_CODE_POINTS = 240;
@@ -347,55 +451,10 @@ function buildEnvAssignments(values: Record<string, string> | undefined): string
347
451
  const entries = Object.entries(values ?? {});
348
452
  return entries.length === 0 ? "" : ` ${entries.map(([key, value]) => `${key}=${shellQuote(value)}`).join(" ")}`;
349
453
  }
350
- function powershellQuote(value: string): string {
351
- return `'${value.replace(/'/g, "''")}'`;
352
- }
353
454
  function stripRootTmuxFlag(rawArgs: string[]): string[] {
354
455
  return rawArgs.filter(arg => arg !== "--tmux");
355
456
  }
356
457
 
357
- function buildWindowsPowerShellInnerCommand(context: CommandResolutionContext, rawArgs: string[]): string {
358
- const command = resolveCurrentGjcCommand(context);
359
- const envLines = Object.entries({ [GJC_TMUX_LAUNCHED_ENV]: "1", ...(context.extraEnv ?? {}) }).map(
360
- ([key, value]) => `$env:${key} = ${powershellQuote(value)}`,
361
- );
362
- // Resolve the inner command and arguments. PowerShell's `&` call operator
363
- // accepts a single command followed by its arguments directly (no script
364
- // block needed). Wrapping the call in `& { ... }` would be invalid because
365
- // adjacent single-quoted tokens inside a script block body are a parser
366
- // error: `& { 'a' 'b' }` fails with "Unexpected token 'b'" because PowerShell
367
- // only concatenates adjacent *double-quoted* strings, and even then only in
368
- // expression position. Emitting the arguments as a comma-separated array
369
- // (`& 'cmd' @('a','b')`) is also rejected because arrays are not valid as
370
- // the second-and-later positional arguments to `&` in command position. The
371
- // correct form is `& 'cmd' 'arg1' 'arg2'` — exactly what the joined
372
- // resolvedCommand + innerArgs produces below.
373
- const resolvedCommand = command.map(powershellQuote).join(" ");
374
- const innerArgs = stripRootTmuxFlag(rawArgs).map(powershellQuote).join(" ");
375
- const invocation = `& ${resolvedCommand} ${innerArgs}`;
376
- const exitLine = "if ($null -ne $LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 }";
377
- const script = context.tmuxExitMarkerPath
378
- ? [
379
- ...envLines,
380
- "$__gjcTmuxExitCode = 1",
381
- "try {",
382
- `\t${invocation}`,
383
- "\tif ($null -ne $LASTEXITCODE) { $__gjcTmuxExitCode = $LASTEXITCODE } else { $__gjcTmuxExitCode = 1 }",
384
- buildPowerShellTmuxExitMarkerFinally(context.tmuxExitMarkerPath),
385
- "exit $__gjcTmuxExitCode",
386
- ].join("\n")
387
- : [...envLines, invocation, exitLine].join("\n");
388
- // Encode the script as UTF-16LE base64 for pwsh -EncodedCommand. Do NOT
389
- // prepend a UTF-16LE BOM (0xFF 0xFE): the BOM survives the decode and is
390
- // inserted as a literal U+FEFF character in front of the first script
391
- // token, which pwsh then reports as a "term not recognized" parse error
392
- // (e.g. "$env:GJC_TMUX_LAUNCHED"). pwsh expects the decoded buffer to
393
- // start with the first character of the script, not with a BOM.
394
- const body = Buffer.from(script, "utf16le");
395
- const encodedCommand = body.toString("base64");
396
- return `pwsh -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encodedCommand}`;
397
- }
398
-
399
458
  export function applyGjcTmuxProfile(context: GjcTmuxProfileContext): GjcTmuxProfileResult {
400
459
  const env = context.env ?? process.env;
401
460
  const branchSlug = context.branch ? buildGjcTmuxSessionSlug(context.branch) : (context.branchSlug ?? null);
@@ -441,19 +500,41 @@ export function applyGjcTmuxProfile(context: GjcTmuxProfileContext): GjcTmuxProf
441
500
  }
442
501
 
443
502
  function resolveCurrentGjcCommand(context: CommandResolutionContext): string[] {
444
- const entrypoint = context.argv[1];
445
- if (!entrypoint) return ["gjc"];
446
- if (isBunVirtualPath(entrypoint)) {
447
- return isBunVirtualPath(context.execPath) ? ["gjc"] : [context.execPath];
448
- }
449
503
  const pathModule = pathModuleForPlatform(context.platform);
450
- const resolvedEntrypoint = pathModule.isAbsolute(entrypoint)
451
- ? entrypoint
452
- : pathModule.resolve(context.cwd, entrypoint);
453
- if (entrypoint.endsWith(".ts") || entrypoint.endsWith(".js") || entrypoint.endsWith(".mjs")) {
454
- return [context.execPath, resolvedEntrypoint];
504
+ const isRealAbsolutePath = (value: string | undefined): value is string => {
505
+ const normalized = value?.trim();
506
+ if (!normalized || isBunVirtualPath(normalized)) return false;
507
+ return pathModule.isAbsolute(normalized) || path.isAbsolute(normalized);
508
+ };
509
+ const isGjcExecutable = (value: string | undefined): value is string =>
510
+ isRealAbsolutePath(value) && /^gjc(?:[._-]|$)/i.test(pathModule.basename(value.trim()));
511
+
512
+ const runtime = context.argv[0]?.trim();
513
+ const entrypoint = context.argv[1]?.trim();
514
+ if (entrypoint && !isBunVirtualPath(entrypoint) && /\.(?:[cm]?[jt]s)$/i.test(entrypoint)) {
515
+ const executable = isRealAbsolutePath(runtime)
516
+ ? runtime
517
+ : isRealAbsolutePath(context.execPath)
518
+ ? context.execPath.trim()
519
+ : undefined;
520
+ if (!executable)
521
+ throw new Error(
522
+ "Unable to determine the current GJC source runtime for tmux launch; invoke GJC through an absolute runtime path.",
523
+ );
524
+ const resolvedEntrypoint = pathModule.isAbsolute(entrypoint)
525
+ ? entrypoint
526
+ : pathModule.resolve(context.cwd, entrypoint);
527
+ return [executable, resolvedEntrypoint];
455
528
  }
456
- return [resolvedEntrypoint];
529
+
530
+ const executable =
531
+ (isGjcExecutable(entrypoint) ? entrypoint : undefined) ??
532
+ (isGjcExecutable(runtime) ? runtime : undefined) ??
533
+ (isGjcExecutable(context.execPath) ? context.execPath.trim() : undefined);
534
+ if (executable) return [executable];
535
+ throw new Error(
536
+ "Unable to determine the current GJC executable for tmux launch; Bun virtual paths and PATH fallback are not accepted.",
537
+ );
457
538
  }
458
539
  function isWindowsPlatform(platform: NodeJS.Platform | undefined): boolean {
459
540
  return platform === "win32";
@@ -463,7 +544,13 @@ function pathModuleForPlatform(platform: NodeJS.Platform | undefined): typeof pa
463
544
  }
464
545
 
465
546
  function buildInnerCommand(context: CommandResolutionContext, rawArgs: string[]): string {
466
- if (isWindowsPlatform(context.platform)) return buildWindowsPowerShellInnerCommand(context, rawArgs);
547
+ if (isWindowsPlatform(context.platform))
548
+ return buildWindowsPowerShellInnerCommand({
549
+ command: resolveCurrentGjcCommand(context),
550
+ args: stripRootTmuxFlag(rawArgs),
551
+ environment: context.extraEnv,
552
+ tmuxExitMarkerPath: context.tmuxExitMarkerPath,
553
+ });
467
554
  const command = resolveCurrentGjcCommand(context);
468
555
  const quoted = [...command, ...stripRootTmuxFlag(rawArgs)].map(shellQuote).join(" ");
469
556
  const invocation = `env ${GJC_TMUX_LAUNCHED_ENV}=1${buildEnvAssignments(context.extraEnv)} ${quoted}`;
@@ -1175,12 +1262,17 @@ export function launchDefaultTmuxIfNeeded(context: TmuxLaunchContext): boolean {
1175
1262
  // window rename and provider refusal so inapplicable root launches reach main
1176
1263
  // unchanged, while unsupported managed launches fail before any tmux mutation.
1177
1264
  const plan = buildDefaultTmuxLaunchPlan(context);
1178
- if (plan?.isPsmux) {
1179
- (context.diagnosticWriter ?? safeStderrWrite)(
1180
- "psmux cannot provide immutable owner identity; refusing managed session creation.\n",
1181
- );
1182
- throw new Error("gjc_tmux_owner_isolation_native_session_identity_unavailable");
1265
+ if (!plan && env.TMUX && (context.platform ?? process.platform) === "win32") {
1266
+ const ambientProvider = resolveGjcTmuxBinary({ platform: "win32", env });
1267
+ if (ambientProvider.isPsmux) return false;
1183
1268
  }
1269
+ if (plan?.isPsmux && plan.platform === "win32" && !env.TMUX)
1270
+ return launchWindowsPsmuxCompatibilitySession(
1271
+ plan,
1272
+ env,
1273
+ context.spawnSync ?? defaultSpawnSync,
1274
+ context.diagnosticWriter ?? safeStderrWrite,
1275
+ );
1184
1276
  // Direct launches inside an ambient tmux session retain their existing title
1185
1277
  // behavior, but only after managed-launch applicability was ruled out.
1186
1278
  renameExistingTmuxWindowIfNeeded(context);
@@ -1218,14 +1310,6 @@ export function launchDefaultTmuxIfNeeded(context: TmuxLaunchContext): boolean {
1218
1310
  context.ownerIsolationProbe ?? defaultOwnerIsolationProbe(plan, env, rawSpawnSync, context.callerCgroupReader);
1219
1311
  const spawnSync = rawSpawnSync;
1220
1312
  const attachOptions: TmuxSpawnOptions = { ...options };
1221
- // Psmux is rejected before planning any tmux mutation, including an ambient
1222
- // TMUX window rename. Keep this defense in depth guard for future plan seams.
1223
- if (plan.isPsmux) {
1224
- (context.diagnosticWriter ?? safeStderrWrite)(
1225
- "psmux cannot provide immutable owner identity; refusing managed session creation.\n",
1226
- );
1227
- throw new Error("gjc_tmux_owner_isolation_native_session_identity_unavailable");
1228
- }
1229
1313
  const controlOptions: TmuxSpawnOptions = {
1230
1314
  ...options,
1231
1315
  stdin: "pipe",
@@ -1,3 +1,5 @@
1
+ import * as fs from "node:fs";
2
+
1
3
  /**
2
4
  * Windows psmux detection and tmux-binary resolution.
3
5
  *
@@ -45,8 +47,7 @@ const DEFAULT_BINARY_RESOLVER: BinaryResolver = candidate => {
45
47
  if (!candidate) return null;
46
48
  const stripped = candidate.trim().replace(/^["']|["']$/g, "");
47
49
  if (!stripped) return null;
48
- if (Bun.which(stripped)) return stripped;
49
- return null;
50
+ return Bun.which(stripped);
50
51
  };
51
52
 
52
53
  let activeBinaryResolver: BinaryResolver = DEFAULT_BINARY_RESOLVER;
@@ -56,6 +57,25 @@ export function __setBinaryResolverForTests(resolver: BinaryResolver | null): vo
56
57
  activeBinaryResolver = resolver ?? DEFAULT_BINARY_RESOLVER;
57
58
  }
58
59
 
60
+ export type ExecutableIdentityResolver = (path: string) => string | null;
61
+
62
+ const DEFAULT_EXECUTABLE_IDENTITY_RESOLVER: ExecutableIdentityResolver = executablePath => {
63
+ try {
64
+ const realPath = fs.realpathSync.native(executablePath);
65
+ const stat = fs.statSync(realPath);
66
+ return stat.ino === 0 ? realPath.toLowerCase() : `${stat.dev}:${stat.ino}`;
67
+ } catch {
68
+ return null;
69
+ }
70
+ };
71
+
72
+ let activeExecutableIdentityResolver: ExecutableIdentityResolver = DEFAULT_EXECUTABLE_IDENTITY_RESOLVER;
73
+
74
+ /** @internal Test-only seam; production code never calls this. */
75
+ export function __setExecutableIdentityResolverForTests(resolver: ExecutableIdentityResolver | null): void {
76
+ activeExecutableIdentityResolver = resolver ?? DEFAULT_EXECUTABLE_IDENTITY_RESOLVER;
77
+ }
78
+
59
79
  interface CacheEntry {
60
80
  command: string;
61
81
  isPsmux: boolean;
@@ -140,6 +160,62 @@ function detectPsmuxForCommand(command: string, runner: PsmuxSpawnRunner): boole
140
160
  return outputMentionsPsmux(output);
141
161
  }
142
162
 
163
+ function classifyWindowsTmuxAlias(command: string, env: NodeJS.ProcessEnv, runner: PsmuxSpawnRunner): boolean {
164
+ if (isNamedPsmuxCommand(command)) return true;
165
+ try {
166
+ if (detectPsmuxForCommand(command, runner)) return true;
167
+ } catch {
168
+ throw new Error("gjc_tmux_provider_ambiguous: selected Windows tmux command resolution failed");
169
+ }
170
+ if (normalizedCommandBaseName(command) !== "tmux" && !env[GJC_PSMUX_COMMAND_ENV]?.trim()) return false;
171
+
172
+ let selectedPath: string | null;
173
+ try {
174
+ selectedPath = resolveBinaryPath(command);
175
+ } catch {
176
+ throw new Error("gjc_tmux_provider_ambiguous: selected Windows tmux command resolution failed");
177
+ }
178
+ if (!selectedPath) {
179
+ throw new Error("gjc_tmux_provider_ambiguous: selected Windows tmux command could not be resolved");
180
+ }
181
+ const selectedIdentity = activeExecutableIdentityResolver(selectedPath);
182
+ if (!selectedIdentity) {
183
+ throw new Error("gjc_tmux_provider_ambiguous: selected Windows tmux executable identity is unavailable");
184
+ }
185
+
186
+ const explicitCompanion = env[GJC_PSMUX_COMMAND_ENV]?.trim();
187
+ const companions = [
188
+ ...new Set([explicitCompanion, "psmux", "pmux"].filter((value): value is string => Boolean(value))),
189
+ ];
190
+ let matched = false;
191
+ let distinct = false;
192
+ for (const companion of companions) {
193
+ let companionPath: string | null;
194
+ try {
195
+ companionPath = resolveBinaryPath(companion);
196
+ } catch {
197
+ throw new Error(`gjc_tmux_provider_ambiguous: Windows ${companion} command resolution failed`);
198
+ }
199
+ if (!companionPath) {
200
+ if (companion === explicitCompanion)
201
+ throw new Error("gjc_tmux_provider_ambiguous: GJC_PSMUX_COMMAND could not be resolved");
202
+ continue;
203
+ }
204
+ const companionIdentity = activeExecutableIdentityResolver(companionPath);
205
+ if (!companionIdentity) {
206
+ throw new Error(`gjc_tmux_provider_ambiguous: Windows ${companion} executable identity is unavailable`);
207
+ }
208
+ if (companionIdentity === selectedIdentity) matched = true;
209
+ else {
210
+ distinct = true;
211
+ if (companion === explicitCompanion)
212
+ throw new Error("gjc_tmux_provider_ambiguous: GJC_PSMUX_COMMAND selects a different executable");
213
+ }
214
+ }
215
+ if (matched && distinct) throw new Error("gjc_tmux_provider_ambiguous: Windows psmux companion identities conflict");
216
+ return matched;
217
+ }
218
+
143
219
  /**
144
220
  * Decide whether command resolves to a psmux binary by probing its version
145
221
  * output. The result is cached per process unless force is set or
@@ -209,13 +285,15 @@ export function resolveGjcTmuxBinary(options: ResolveGjcTmuxBinaryOptions = {}):
209
285
  const explicit = env.GJC_TMUX_COMMAND?.trim() || env.GJC_TEAM_TMUX_COMMAND?.trim();
210
286
  if (explicit) {
211
287
  const isPsmux =
212
- platform === "win32" && isNamedPsmuxCommand(explicit) ? true : detectPsmux(explicit, { env, runner });
288
+ platform === "win32"
289
+ ? classifyWindowsTmuxAlias(explicit, env, runner)
290
+ : detectPsmux(explicit, { env, runner });
213
291
  return { command: explicit, isPsmux, viaExplicitOverride: true };
214
292
  }
215
293
  if (platform === "win32") {
216
294
  for (const candidate of PSMUX_BINARY_NAMES) {
217
295
  if (resolveBinaryPath(candidate)) {
218
- const isPsmux = isNamedPsmuxCommand(candidate) ? true : detectPsmux(candidate, { env, runner });
296
+ const isPsmux = classifyWindowsTmuxAlias(candidate, env, runner);
219
297
  return { command: candidate, isPsmux, viaExplicitOverride: false };
220
298
  }
221
299
  }
@@ -3,7 +3,7 @@ import * as fsSync from "node:fs";
3
3
  import * as fs from "node:fs/promises";
4
4
  import * as path from "node:path";
5
5
  import type { AssistantMessage } from "@gajae-code/ai";
6
- import { postmortem } from "@gajae-code/utils";
6
+ import { normalizePathForComparison, postmortem } from "@gajae-code/utils";
7
7
  import { sessionRuntimeDir } from "./session-layout";
8
8
  import {
9
9
  isValidOwnerIntent,
@@ -76,6 +76,8 @@ export interface RuntimeStateContext {
76
76
  sessionId: string;
77
77
  cwd: string;
78
78
  sessionFile?: string | null;
79
+ /** Optional platform seam for deterministic cross-platform path identity checks. */
80
+ platform?: NodeJS.Platform;
79
81
  branch?: string | null;
80
82
  /** Public-safe owner metadata used to persist the canonical terminal verdict. */
81
83
  ownerTerminal?: OwnerTerminalContext | null;
@@ -83,6 +85,14 @@ export interface RuntimeStateContext {
83
85
  ownerTerminalMetadataInvalid?: boolean;
84
86
  }
85
87
 
88
+ interface RuntimeStateIdentity {
89
+ sessionId: string;
90
+ cwd: string;
91
+ workdir: string;
92
+ sessionFile: string | null;
93
+ platform: NodeJS.Platform;
94
+ }
95
+
86
96
  interface RuntimeStateSidecarPayload {
87
97
  schema_version?: unknown;
88
98
  session_id?: unknown;
@@ -201,27 +211,27 @@ export async function persistCoordinatorRuntimeInputReady(): Promise<RuntimeInpu
201
211
  }
202
212
  }
203
213
 
204
- function sameResolvedPath(left: string, right: string): boolean {
205
- return path.resolve(left) === path.resolve(right);
214
+ function sameResolvedPath(left: string, right: string, platform: NodeJS.Platform = process.platform): boolean {
215
+ return normalizePathForComparison(left, platform) === normalizePathForComparison(right, platform);
206
216
  }
207
217
 
208
- function normalizedIdentity(context: Pick<RuntimeStateContext, "sessionId" | "cwd" | "sessionFile">): {
209
- sessionId: string;
210
- cwd: string;
211
- workdir: string;
212
- sessionFile: string | null;
213
- } {
218
+ function normalizedIdentity(
219
+ context: Pick<RuntimeStateContext, "sessionId" | "cwd" | "sessionFile" | "platform">,
220
+ ): RuntimeStateIdentity {
214
221
  const explicitStateFile = process.env[GJC_COORDINATOR_SESSION_STATE_FILE_ENV]?.trim();
215
222
  const sessionId = explicitStateFile
216
223
  ? process.env[GJC_COORDINATOR_SESSION_ID_ENV]?.trim() || context.sessionId.trim()
217
224
  : context.sessionId.trim();
218
225
  const cwd = context.cwd.trim();
226
+ const platform = context.platform ?? process.platform;
227
+ const pathApi = platform === "win32" ? path.win32 : path;
219
228
  if (!sessionId || !cwd) throw new PreviousRuntimeStateReadError();
220
229
  return {
221
230
  sessionId,
222
- cwd: path.resolve(cwd),
223
- workdir: path.resolve(cwd),
224
- sessionFile: context.sessionFile == null ? null : path.resolve(context.sessionFile),
231
+ cwd: pathApi.resolve(cwd),
232
+ workdir: pathApi.resolve(cwd),
233
+ sessionFile: context.sessionFile == null ? null : pathApi.resolve(context.sessionFile),
234
+ platform,
225
235
  };
226
236
  }
227
237
 
@@ -268,7 +278,10 @@ export async function readTerminalRuntimeStateMarker(input: {
268
278
  sessionId?: string | null;
269
279
  cwd?: string | null;
270
280
  sessionFile?: string | null;
281
+ platform?: NodeJS.Platform;
271
282
  }): Promise<TerminalRuntimeStateStatus> {
283
+ const platform = input.platform ?? process.platform;
284
+ const pathApi = platform === "win32" ? path.win32 : path;
272
285
  const stateFile = input.stateFile?.trim();
273
286
  const sessionId = input.sessionId?.trim();
274
287
  const cwd = input.cwd?.trim();
@@ -287,15 +300,18 @@ export async function readTerminalRuntimeStateMarker(input: {
287
300
  if (!validRuntimeStateMarker(value)) return { terminal: false, reason: "invalid_state_marker" };
288
301
  const payload = value;
289
302
  if (payload.session_id !== sessionId) return { terminal: false, reason: "session_id_mismatch" };
290
- if (!sameResolvedPath(payload.cwd as string, cwd) || !sameResolvedPath(payload.workdir as string, cwd))
303
+ if (
304
+ !sameResolvedPath(payload.cwd as string, cwd, platform) ||
305
+ !sameResolvedPath(payload.workdir as string, cwd, platform)
306
+ )
291
307
  return { terminal: false, reason: "cwd_mismatch" };
292
- const sessionFile = input.sessionFile == null ? null : path.resolve(input.sessionFile);
308
+ const sessionFile = input.sessionFile == null ? null : pathApi.resolve(input.sessionFile);
293
309
  if (
294
310
  payload.session_file !== sessionFile &&
295
311
  !(
296
312
  typeof payload.session_file === "string" &&
297
313
  typeof sessionFile === "string" &&
298
- sameResolvedPath(payload.session_file, sessionFile)
314
+ sameResolvedPath(payload.session_file, sessionFile, platform)
299
315
  )
300
316
  )
301
317
  return { terminal: false, reason: "session_file_mismatch" };
@@ -484,41 +500,35 @@ function rememberWrittenPayload(stateFile: string, payload: Record<string, unkno
484
500
  lastPayloadByStateFile.delete(stateFile);
485
501
  }
486
502
  }
487
- function shouldPreserveTerminalPayload(
488
- previous: RuntimeStateSidecarPayload,
489
- input: { sessionId: string; cwd: string; sessionFile: string | null },
490
- ): boolean {
503
+ function shouldPreserveTerminalPayload(previous: RuntimeStateSidecarPayload, input: RuntimeStateIdentity): boolean {
491
504
  if (!validRuntimeStateMarker(previous)) return false;
492
505
  if (previous.state !== "completed" && previous.state !== "errored") return false;
493
506
  const source = previous.final_response?.source;
494
507
  if (source !== "agent_end" && source !== "launch_error") return false;
495
508
  return (
496
509
  previous.session_id === input.sessionId &&
497
- sameResolvedPath(previous.cwd as string, input.cwd) &&
498
- sameResolvedPath(previous.workdir as string, input.cwd) &&
510
+ sameResolvedPath(previous.cwd as string, input.cwd, input.platform) &&
511
+ sameResolvedPath(previous.workdir as string, input.cwd, input.platform) &&
499
512
  (previous.session_file === input.sessionFile ||
500
513
  (typeof previous.session_file === "string" &&
501
514
  typeof input.sessionFile === "string" &&
502
- sameResolvedPath(previous.session_file, input.sessionFile)))
515
+ sameResolvedPath(previous.session_file, input.sessionFile, input.platform)))
503
516
  );
504
517
  }
505
518
 
506
- function assertPreviousRuntimeStateIdentity(
507
- previous: Record<string, unknown>,
508
- input: { sessionId: string; cwd: string; sessionFile: string | null },
509
- ): void {
519
+ function assertPreviousRuntimeStateIdentity(previous: Record<string, unknown>, input: RuntimeStateIdentity): void {
510
520
  if (Object.keys(previous).length === 0) return;
511
521
  if (
512
522
  previous.session_id !== input.sessionId ||
513
523
  typeof previous.cwd !== "string" ||
514
524
  typeof previous.workdir !== "string" ||
515
- !sameResolvedPath(previous.cwd, input.cwd) ||
516
- !sameResolvedPath(previous.workdir, input.cwd) ||
525
+ !sameResolvedPath(previous.cwd, input.cwd, input.platform) ||
526
+ !sameResolvedPath(previous.workdir, input.cwd, input.platform) ||
517
527
  (previous.session_file !== input.sessionFile &&
518
528
  !(
519
529
  typeof previous.session_file === "string" &&
520
530
  typeof input.sessionFile === "string" &&
521
- sameResolvedPath(previous.session_file, input.sessionFile)
531
+ sameResolvedPath(previous.session_file, input.sessionFile, input.platform)
522
532
  ))
523
533
  )
524
534
  throw new PreviousRuntimeStateReadError();
@@ -1112,7 +1122,7 @@ export async function persistCoordinatorRuntimeStateFromPostmortem(
1112
1122
  if (shouldPreserveTerminalPayload(previous as RuntimeStateSidecarPayload, identity)) return;
1113
1123
  // The immutable owner verdict remains in its lifecycle artifact; never replace a
1114
1124
  // complete agent terminal payload merely to mirror that verdict here.
1115
- if (process.platform === "linux" && context.ownerTerminalMetadataInvalid) {
1125
+ if (context.ownerTerminalMetadataInvalid) {
1116
1126
  await persistInvalidOwnerTerminalMetadata(
1117
1127
  reason,
1118
1128
  context,
@@ -1122,7 +1132,7 @@ export async function persistCoordinatorRuntimeStateFromPostmortem(
1122
1132
  );
1123
1133
  return;
1124
1134
  }
1125
- if (process.platform === "linux" && context.ownerTerminal) {
1135
+ if (context.ownerTerminal) {
1126
1136
  await persistCoordinatorRuntimeStateFromOwnerTerminalPostmortem(
1127
1137
  reason,
1128
1138
  context,