@gajae-code/coding-agent 0.10.2 → 0.11.1

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 (476) hide show
  1. package/CHANGELOG.md +58 -2
  2. package/dist/types/append-only-mode.d.ts +1 -1
  3. package/dist/types/async/job-manager.d.ts +46 -7
  4. package/dist/types/cli/args.d.ts +4 -5
  5. package/dist/types/cli/daemon-cli.d.ts +12 -1
  6. package/dist/types/cli/notify-cli.d.ts +21 -1
  7. package/dist/types/cli.d.ts +3 -0
  8. package/dist/types/commands/daemon.d.ts +39 -0
  9. package/dist/types/commands/launch.d.ts +3 -0
  10. package/dist/types/commands/notify.d.ts +28 -1
  11. package/dist/types/commands/sdk.d.ts +33 -0
  12. package/dist/types/config/atomic-yaml-patch.d.ts +85 -0
  13. package/dist/types/config/model-profile-activation.d.ts +35 -15
  14. package/dist/types/config/model-profiles.d.ts +11 -5
  15. package/dist/types/config/model-registry.d.ts +3 -3
  16. package/dist/types/config/model-resolver.d.ts +39 -6
  17. package/dist/types/config/model-selector-value.d.ts +17 -0
  18. package/dist/types/config/models-config-schema.d.ts +10 -6
  19. package/dist/types/config/settings-schema.d.ts +133 -6
  20. package/dist/types/config/settings.d.ts +63 -35
  21. package/dist/types/coordinator-mcp/model-preset.d.ts +7 -6
  22. package/dist/types/coordinator-mcp/server.d.ts +6 -49
  23. package/dist/types/daemon/builtin.d.ts +6 -5
  24. package/dist/types/daemon/control-types.d.ts +1 -1
  25. package/dist/types/discovery/mcp-json.d.ts +12 -1
  26. package/dist/types/extensibility/custom-tools/types.d.ts +1 -1
  27. package/dist/types/extensibility/extensions/compact-handler.d.ts +4 -2
  28. package/dist/types/extensibility/extensions/get-commands-handler.d.ts +2 -2
  29. package/dist/types/extensibility/extensions/loader.d.ts +10 -1
  30. package/dist/types/extensibility/extensions/runner.d.ts +3 -3
  31. package/dist/types/extensibility/extensions/types.d.ts +141 -16
  32. package/dist/types/extensibility/hooks/types.d.ts +1 -1
  33. package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -2
  34. package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
  35. package/dist/types/gjc-runtime/session-state-sidecar.d.ts +3 -0
  36. package/dist/types/gjc-runtime/team-runtime.d.ts +3 -4
  37. package/dist/types/gjc-runtime/tmux-owner-isolation-cli.d.ts +13 -0
  38. package/dist/types/gjc-runtime/tmux-sessions.d.ts +4 -1
  39. package/dist/types/gjc-runtime/ultragoal-receipt-freshness.d.ts +11 -0
  40. package/dist/types/gjc-runtime/windows-powershell-command.d.ts +9 -0
  41. package/dist/types/harness-control-plane/operate.d.ts +5 -5
  42. package/dist/types/harness-control-plane/owner.d.ts +18 -4
  43. package/dist/types/harness-control-plane/receipts.d.ts +0 -1
  44. package/dist/types/harness-control-plane/sdk-transport.d.ts +43 -0
  45. package/dist/types/harness-control-plane/session-transport.d.ts +48 -0
  46. package/dist/types/harness-control-plane/types.d.ts +3 -4
  47. package/dist/types/lsp/index.d.ts +1 -1
  48. package/dist/types/main.d.ts +32 -38
  49. package/dist/types/modes/acp/acp-agent.d.ts +224 -53
  50. package/dist/types/modes/acp/acp-client-bridge.d.ts +1 -0
  51. package/dist/types/modes/acp/acp-mode.d.ts +6 -15
  52. package/dist/types/modes/acp/permission-mode.d.ts +4 -0
  53. package/dist/types/modes/acp/startup-options.d.ts +6 -0
  54. package/dist/types/modes/components/agent-dashboard.d.ts +3 -0
  55. package/dist/types/modes/components/model-selector.d.ts +1 -0
  56. package/dist/types/modes/components/notifications-settings-editor.d.ts +135 -0
  57. package/dist/types/modes/components/settings-selector.d.ts +6 -4
  58. package/dist/types/modes/components/welcome.d.ts +1 -1
  59. package/dist/types/modes/controllers/command-controller.d.ts +2 -2
  60. package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -0
  61. package/dist/types/modes/controllers/selector-controller.d.ts +35 -1
  62. package/dist/types/modes/index.d.ts +0 -4
  63. package/dist/types/modes/interactive-mode.d.ts +5 -2
  64. package/dist/types/modes/runtime-init.d.ts +2 -2
  65. package/dist/types/modes/shared/agent-wire/approval-gate.d.ts +6 -9
  66. package/dist/types/modes/shared/agent-wire/deep-interview-gate.d.ts +4 -6
  67. package/dist/types/modes/shared/agent-wire/event-contract.d.ts +6 -6
  68. package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +4 -9
  69. package/dist/types/modes/shared/agent-wire/event-observation.d.ts +1 -1
  70. package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +170 -30
  71. package/dist/types/modes/shared/agent-wire/workflow-gate-schema.d.ts +7 -7
  72. package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +105 -0
  73. package/dist/types/modes/types.d.ts +7 -2
  74. package/dist/types/runtime-mcp/client.d.ts +2 -0
  75. package/dist/types/runtime-mcp/config.d.ts +5 -1
  76. package/dist/types/runtime-mcp/manager.d.ts +8 -1
  77. package/dist/types/runtime-mcp/types.d.ts +4 -0
  78. package/dist/types/sdk/acp/adapter.d.ts +67 -0
  79. package/dist/types/sdk/acp/index.d.ts +2 -0
  80. package/dist/types/sdk/broker/broker.d.ts +53 -0
  81. package/dist/types/sdk/broker/discovery.d.ts +30 -0
  82. package/dist/types/sdk/broker/ensure.d.ts +42 -0
  83. package/dist/types/sdk/broker/identity.d.ts +3 -0
  84. package/dist/types/sdk/broker/index.d.ts +8 -0
  85. package/dist/types/sdk/broker/lifecycle-ledger.d.ts +95 -0
  86. package/dist/types/sdk/broker/lifecycle.d.ts +85 -0
  87. package/dist/types/sdk/broker/process-incarnation.d.ts +14 -0
  88. package/dist/types/sdk/broker/runtime.d.ts +33 -0
  89. package/dist/types/sdk/broker/session-index.d.ts +57 -0
  90. package/dist/types/sdk/broker/state-version.d.ts +8 -0
  91. package/dist/types/sdk/broker/transport.d.ts +9 -0
  92. package/dist/types/sdk/bus/chat-command-policy.d.ts +49 -0
  93. package/dist/types/sdk/bus/chat-daemon-cli.d.ts +21 -0
  94. package/dist/types/sdk/bus/chat-daemon-control.d.ts +111 -0
  95. package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +77 -0
  96. package/dist/types/sdk/bus/chat-effect-journal.d.ts +84 -0
  97. package/dist/types/{notifications → sdk/bus}/config-commands.d.ts +7 -2
  98. package/dist/types/sdk/bus/config.d.ts +274 -0
  99. package/dist/types/sdk/bus/conversation-store.d.ts +72 -0
  100. package/dist/types/sdk/bus/discord-conversation.d.ts +58 -0
  101. package/dist/types/sdk/bus/discord-daemon.d.ts +50 -0
  102. package/dist/types/sdk/bus/discord-live-provider.d.ts +70 -0
  103. package/dist/types/sdk/bus/discord-provider.d.ts +85 -0
  104. package/dist/types/{notifications → sdk/bus}/html-format.d.ts +2 -2
  105. package/dist/types/{notifications → sdk/bus}/index.d.ts +113 -13
  106. package/dist/types/{notifications → sdk/bus}/lifecycle-control-runtime.d.ts +4 -2
  107. package/dist/types/{notifications → sdk/bus}/lifecycle-orchestrator.d.ts +18 -21
  108. package/dist/types/{notifications → sdk/bus}/managed-daemon.d.ts +1 -1
  109. package/dist/types/sdk/bus/native-runtime-compatibility.d.ts +13 -0
  110. package/dist/types/sdk/bus/notification-orchestration.d.ts +170 -0
  111. package/dist/types/{notifications → sdk/bus}/notification-service.d.ts +7 -1
  112. package/dist/types/sdk/bus/session-control.d.ts +83 -0
  113. package/dist/types/sdk/bus/slack-conversation.d.ts +56 -0
  114. package/dist/types/sdk/bus/slack-daemon.d.ts +60 -0
  115. package/dist/types/sdk/bus/slack-live-provider.d.ts +59 -0
  116. package/dist/types/sdk/bus/slack-provider.d.ts +55 -0
  117. package/dist/types/{notifications → sdk/bus}/telegram-cli.d.ts +4 -4
  118. package/dist/types/{notifications → sdk/bus}/telegram-daemon-cli.d.ts +14 -5
  119. package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -0
  120. package/dist/types/{notifications → sdk/bus}/telegram-daemon-control.d.ts +2 -2
  121. package/dist/types/{notifications → sdk/bus}/telegram-daemon.d.ts +78 -17
  122. package/dist/types/{notifications → sdk/bus}/telegram-reference.d.ts +2 -2
  123. package/dist/types/sdk/bus/telegram-setup.d.ts +128 -0
  124. package/dist/types/{notifications → sdk/bus}/topic-registry.d.ts +11 -0
  125. package/dist/types/sdk/cli/index.d.ts +1 -0
  126. package/dist/types/sdk/cli/session-cli.d.ts +19 -0
  127. package/dist/types/sdk/client/client.d.ts +1 -0
  128. package/dist/types/sdk/client/discovery.d.ts +27 -0
  129. package/dist/types/sdk/client/index.d.ts +2 -0
  130. package/dist/types/sdk/host/control/dispatch.d.ts +34 -0
  131. package/dist/types/sdk/host/control/index.d.ts +2 -0
  132. package/dist/types/sdk/host/control/operations.d.ts +65 -0
  133. package/dist/types/sdk/host/events.d.ts +35 -0
  134. package/dist/types/sdk/host/host.d.ts +35 -0
  135. package/dist/types/sdk/host/index.d.ts +4 -0
  136. package/dist/types/sdk/host/query/cursor.d.ts +62 -0
  137. package/dist/types/sdk/host/query/handlers.d.ts +70 -0
  138. package/dist/types/sdk/host/query/index.d.ts +3 -0
  139. package/dist/types/sdk/host/query/revision-store.d.ts +60 -0
  140. package/dist/types/sdk/host/reverse-leases.d.ts +45 -0
  141. package/dist/types/sdk/host/types.d.ts +32 -0
  142. package/dist/types/sdk/index.d.ts +6 -0
  143. package/dist/types/sdk/lifecycle-session.d.ts +14 -0
  144. package/dist/types/sdk/mcp/index.d.ts +1 -0
  145. package/dist/types/sdk/mcp/server.d.ts +37 -0
  146. package/dist/types/sdk/models.d.ts +44 -0
  147. package/dist/types/sdk/protocol/adapter-validation.d.ts +14 -0
  148. package/dist/types/sdk/protocol/operation-registry.d.ts +24 -0
  149. package/dist/types/{sdk.d.ts → sdk/session.d.ts} +44 -38
  150. package/dist/types/sdk/startup-capability.d.ts +50 -0
  151. package/dist/types/session/agent-session.d.ts +114 -21
  152. package/dist/types/session/default-model-selection.d.ts +25 -0
  153. package/dist/types/session/fallback-chain-controller.d.ts +52 -0
  154. package/dist/types/session/session-manager.d.ts +58 -1
  155. package/dist/types/setup/credential-auto-import.d.ts +36 -6
  156. package/dist/types/tools/ask-answer-registry.d.ts +1 -1
  157. package/dist/types/tools/browser/benchmark/detector-report.d.ts +63 -0
  158. package/dist/types/tools/browser/benchmark/run-suite.d.ts +18 -0
  159. package/dist/types/tools/browser/launch.d.ts +22 -0
  160. package/dist/types/tools/browser/profile-discovery.d.ts +31 -0
  161. package/dist/types/tools/browser/profile-posture.d.ts +37 -0
  162. package/dist/types/tools/browser/profile-reuse.d.ts +39 -0
  163. package/dist/types/tools/browser/profile-warmup.d.ts +39 -0
  164. package/dist/types/tools/browser/registry.d.ts +19 -0
  165. package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
  166. package/dist/types/tools/index.d.ts +8 -8
  167. package/dist/types/tools/subagent-render.d.ts +1 -0
  168. package/dist/types/tools/subagent.d.ts +6 -1
  169. package/package.json +34 -13
  170. package/scripts/build-sdk-package-smoke.ts +99 -0
  171. package/scripts/capture-notifications-settings-showcase.ts +435 -0
  172. package/scripts/compile-args.ts +4 -2
  173. package/scripts/g005-daemon-smoke.ts +4 -5
  174. package/scripts/g011-daemon-path-smoke.ts +5 -5
  175. package/scripts/generate-sdk-adapter-parity-manifest.ts +163 -0
  176. package/scripts/generate-sdk-operation-inventory.ts +867 -0
  177. package/scripts/generate-telegram-baseline-manifest.ts +128 -0
  178. package/scripts/manifest-schema.ts +124 -0
  179. package/scripts/run-test-manifest.ts +153 -0
  180. package/scripts/run-threat-model-check.ts +157 -0
  181. package/scripts/verify-gjc-sdk-canonicalization.ts +3467 -0
  182. package/scripts/verify-gjc-sdk-rename.ts +90 -0
  183. package/src/append-only-mode.ts +1 -1
  184. package/src/async/job-manager.ts +406 -63
  185. package/src/cli/args.ts +43 -12
  186. package/src/cli/auth-gateway-cli.ts +2 -2
  187. package/src/cli/config-cli.ts +2 -1
  188. package/src/cli/daemon-cli.ts +63 -14
  189. package/src/cli/list-models.ts +1 -1
  190. package/src/cli/notify-cli.ts +288 -286
  191. package/src/cli.ts +21 -2
  192. package/src/commands/daemon.ts +50 -6
  193. package/src/commands/harness.ts +93 -36
  194. package/src/commands/launch.ts +5 -2
  195. package/src/commands/mcp-serve.ts +19 -12
  196. package/src/commands/notify.ts +36 -3
  197. package/src/commands/sdk.ts +426 -0
  198. package/src/commit/agentic/agent.ts +1 -0
  199. package/src/config/atomic-yaml-patch.ts +423 -0
  200. package/src/config/model-profile-activation.ts +240 -89
  201. package/src/config/model-profiles.ts +18 -15
  202. package/src/config/model-registry.ts +51 -26
  203. package/src/config/model-resolver.ts +138 -51
  204. package/src/config/model-selector-value.ts +50 -0
  205. package/src/config/models-config-schema.ts +14 -21
  206. package/src/config/settings-schema.ts +128 -10
  207. package/src/config/settings.ts +1120 -158
  208. package/src/coordinator-mcp/model-preset.ts +74 -20
  209. package/src/coordinator-mcp/server.ts +1597 -3052
  210. package/src/daemon/builtin.ts +8 -5
  211. package/src/daemon/control-types.ts +1 -1
  212. package/src/defaults/gjc/skills/team/SKILL.md +4 -4
  213. package/src/discovery/mcp-json.ts +327 -20
  214. package/src/extensibility/custom-tools/types.ts +1 -1
  215. package/src/extensibility/extensions/compact-handler.ts +3 -3
  216. package/src/extensibility/extensions/get-commands-handler.ts +2 -2
  217. package/src/extensibility/extensions/loader.ts +69 -5
  218. package/src/extensibility/extensions/runner.ts +112 -4
  219. package/src/extensibility/extensions/types.ts +176 -17
  220. package/src/extensibility/hooks/types.ts +1 -1
  221. package/src/gjc-runtime/launch-tmux.ts +170 -86
  222. package/src/gjc-runtime/psmux-detect.ts +82 -4
  223. package/src/gjc-runtime/session-state-sidecar.ts +41 -31
  224. package/src/gjc-runtime/team-runtime.ts +54 -35
  225. package/src/gjc-runtime/tmux-owner-isolation-cli.ts +53 -17
  226. package/src/gjc-runtime/tmux-owner-isolation.ts +1 -1
  227. package/src/gjc-runtime/tmux-sessions.ts +19 -13
  228. package/src/gjc-runtime/ultragoal-guard.ts +108 -14
  229. package/src/gjc-runtime/ultragoal-receipt-freshness.ts +102 -1
  230. package/src/gjc-runtime/ultragoal-runtime.ts +227 -11
  231. package/src/gjc-runtime/windows-powershell-command.ts +58 -0
  232. package/src/harness-control-plane/operate.ts +9 -9
  233. package/src/harness-control-plane/owner.ts +283 -39
  234. package/src/harness-control-plane/receipts.ts +0 -1
  235. package/src/harness-control-plane/sdk-transport.ts +395 -0
  236. package/src/harness-control-plane/session-transport.ts +94 -0
  237. package/src/harness-control-plane/types.ts +1 -1
  238. package/src/internal-urls/docs-index.generated.ts +34 -35
  239. package/src/lsp/client.ts +42 -6
  240. package/src/lsp/index.ts +2 -2
  241. package/src/main.ts +299 -204
  242. package/src/modes/DESIGN.md +258 -0
  243. package/src/modes/acp/acp-agent.ts +1228 -2612
  244. package/src/modes/acp/acp-client-bridge.ts +2 -20
  245. package/src/modes/acp/acp-event-mapper.ts +18 -2
  246. package/src/modes/acp/acp-mode.ts +8 -36
  247. package/src/modes/acp/permission-mode.ts +25 -0
  248. package/src/modes/acp/startup-options.ts +6 -0
  249. package/src/modes/components/agent-dashboard.ts +37 -17
  250. package/src/modes/components/model-selector.ts +93 -35
  251. package/src/modes/components/notifications-settings-editor.ts +1379 -0
  252. package/src/modes/components/settings-selector.ts +60 -11
  253. package/src/modes/components/welcome.ts +4 -4
  254. package/src/modes/controllers/command-controller.ts +10 -17
  255. package/src/modes/controllers/event-controller.ts +11 -16
  256. package/src/modes/controllers/extension-ui-controller.ts +396 -28
  257. package/src/modes/controllers/selector-controller.ts +674 -36
  258. package/src/modes/index.ts +0 -22
  259. package/src/modes/interactive-mode.ts +87 -36
  260. package/src/modes/runtime-init.ts +298 -6
  261. package/src/modes/shared/agent-wire/approval-gate.ts +9 -11
  262. package/src/modes/shared/agent-wire/deep-interview-gate.ts +10 -11
  263. package/src/modes/shared/agent-wire/event-contract.ts +7 -8
  264. package/src/modes/shared/agent-wire/event-envelope.ts +9 -17
  265. package/src/modes/shared/agent-wire/event-observation.ts +16 -7
  266. package/src/modes/shared/agent-wire/workflow-gate-broker.ts +1258 -87
  267. package/src/modes/shared/agent-wire/workflow-gate-schema.ts +15 -15
  268. package/src/modes/shared/agent-wire/workflow-gate-types.ts +113 -0
  269. package/src/modes/types.ts +7 -2
  270. package/src/runtime-mcp/client.ts +94 -19
  271. package/src/runtime-mcp/config.ts +27 -15
  272. package/src/runtime-mcp/manager.ts +343 -105
  273. package/src/runtime-mcp/oauth-flow.ts +42 -12
  274. package/src/runtime-mcp/transports/http.ts +49 -19
  275. package/src/runtime-mcp/transports/stdio.ts +47 -28
  276. package/src/runtime-mcp/types.ts +10 -0
  277. package/src/sdk/acp/adapter.ts +418 -0
  278. package/src/sdk/acp/index.ts +2 -0
  279. package/src/sdk/broker/broker.ts +642 -0
  280. package/src/sdk/broker/discovery.ts +113 -0
  281. package/src/sdk/broker/ensure.ts +307 -0
  282. package/src/sdk/broker/identity.ts +42 -0
  283. package/src/sdk/broker/index.ts +8 -0
  284. package/src/sdk/broker/internal-source-marker-2178.txt +1 -0
  285. package/src/sdk/broker/internal-source.bunfig.toml +1 -0
  286. package/src/sdk/broker/lifecycle-ledger.ts +286 -0
  287. package/src/sdk/broker/lifecycle.ts +2157 -0
  288. package/src/sdk/broker/process-incarnation.ts +159 -0
  289. package/src/sdk/broker/runtime.ts +164 -0
  290. package/src/sdk/broker/session-index.ts +318 -0
  291. package/src/sdk/broker/state-version.ts +23 -0
  292. package/src/sdk/broker/transport.ts +125 -0
  293. package/src/sdk/bus/chat-command-policy.ts +107 -0
  294. package/src/sdk/bus/chat-daemon-cli.ts +214 -0
  295. package/src/sdk/bus/chat-daemon-control.ts +713 -0
  296. package/src/sdk/bus/chat-daemon-runtime.ts +526 -0
  297. package/src/sdk/bus/chat-effect-journal.ts +355 -0
  298. package/src/{notifications → sdk/bus}/config-commands.ts +39 -10
  299. package/src/sdk/bus/config.ts +433 -0
  300. package/src/sdk/bus/conversation-store.ts +391 -0
  301. package/src/sdk/bus/discord-conversation.ts +85 -0
  302. package/src/sdk/bus/discord-daemon.ts +2292 -0
  303. package/src/sdk/bus/discord-live-provider.ts +521 -0
  304. package/src/sdk/bus/discord-provider.ts +56 -0
  305. package/src/{notifications → sdk/bus}/html-format.ts +2 -2
  306. package/src/sdk/bus/index.ts +3979 -0
  307. package/src/{notifications → sdk/bus}/lifecycle-commands.ts +2 -0
  308. package/src/{notifications → sdk/bus}/lifecycle-control-runtime.ts +225 -196
  309. package/src/{notifications → sdk/bus}/lifecycle-orchestrator.ts +161 -74
  310. package/src/{notifications → sdk/bus}/managed-daemon.ts +2 -2
  311. package/src/sdk/bus/native-runtime-compatibility.ts +42 -0
  312. package/src/sdk/bus/natives-augment.d.ts +38 -0
  313. package/src/sdk/bus/notification-orchestration.ts +535 -0
  314. package/src/{notifications → sdk/bus}/notification-service.ts +106 -12
  315. package/src/sdk/bus/session-control.ts +333 -0
  316. package/src/sdk/bus/slack-conversation.ts +74 -0
  317. package/src/sdk/bus/slack-daemon.ts +2144 -0
  318. package/src/sdk/bus/slack-live-provider.ts +380 -0
  319. package/src/sdk/bus/slack-provider.ts +76 -0
  320. package/src/{notifications → sdk/bus}/telegram-cli.ts +8 -8
  321. package/src/sdk/bus/telegram-daemon-cli.ts +330 -0
  322. package/src/sdk/bus/telegram-daemon-contract.ts +14 -0
  323. package/src/{notifications → sdk/bus}/telegram-daemon-control.ts +4 -4
  324. package/src/{notifications → sdk/bus}/telegram-daemon.ts +603 -63
  325. package/src/{notifications → sdk/bus}/telegram-reference.ts +2 -2
  326. package/src/sdk/bus/telegram-setup.ts +663 -0
  327. package/src/{notifications → sdk/bus}/topic-registry.ts +32 -0
  328. package/src/sdk/cli/index.ts +1 -0
  329. package/src/sdk/cli/session-cli.ts +275 -0
  330. package/src/sdk/client/client.ts +1 -0
  331. package/src/sdk/client/discovery.ts +108 -0
  332. package/src/sdk/client/index.ts +2 -0
  333. package/src/sdk/host/control/dispatch.ts +367 -0
  334. package/src/sdk/host/control/index.ts +10 -0
  335. package/src/sdk/host/control/operations.ts +63 -0
  336. package/src/sdk/host/events.ts +91 -0
  337. package/src/sdk/host/host.ts +296 -0
  338. package/src/sdk/host/index.ts +4 -0
  339. package/src/sdk/host/query/cursor.ts +189 -0
  340. package/src/sdk/host/query/handlers.ts +533 -0
  341. package/src/sdk/host/query/index.ts +3 -0
  342. package/src/sdk/host/query/revision-store.ts +1126 -0
  343. package/src/sdk/host/reverse-leases.ts +325 -0
  344. package/src/sdk/host/types.ts +29 -0
  345. package/src/sdk/index.ts +13 -0
  346. package/src/sdk/lifecycle-session.ts +39 -0
  347. package/src/sdk/mcp/index.ts +1 -0
  348. package/src/sdk/mcp/server.ts +332 -0
  349. package/src/sdk/models.ts +168 -0
  350. package/src/sdk/protocol/adapter-validation.ts +48 -0
  351. package/src/sdk/protocol/operation-inventory.generated.json +5654 -0
  352. package/src/sdk/protocol/operation-registry.ts +312 -0
  353. package/src/{sdk.ts → sdk/session.ts} +339 -212
  354. package/src/sdk/startup-capability.ts +189 -0
  355. package/src/session/agent-session.ts +2650 -944
  356. package/src/session/default-model-selection.ts +93 -0
  357. package/src/session/fallback-chain-controller.ts +136 -0
  358. package/src/session/session-manager.ts +438 -11
  359. package/src/session/session-storage.ts +8 -1
  360. package/src/setup/credential-auto-import.ts +290 -35
  361. package/src/setup/hermes/templates/operator-instructions.v1.md +3 -5
  362. package/src/slash-commands/builtin-registry.ts +2 -1
  363. package/src/task/executor.ts +62 -13
  364. package/src/task/index.ts +26 -16
  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/subagent-render.ts +19 -8
  384. package/src/tools/subagent.ts +84 -32
  385. package/src/tools/telegram-send.ts +2 -2
  386. package/vendor/insane-search/MANIFEST.json +2 -1
  387. package/vendor/insane-search/engine/bias_check.py +4 -1
  388. package/vendor/insane-search/engine/phase0.py +26 -1
  389. package/dist/types/harness-control-plane/rpc-adapter.d.ts +0 -69
  390. package/dist/types/modes/bridge/auth.d.ts +0 -12
  391. package/dist/types/modes/bridge/bridge-client-bridge.d.ts +0 -9
  392. package/dist/types/modes/bridge/bridge-mode.d.ts +0 -47
  393. package/dist/types/modes/bridge/bridge-ui-context.d.ts +0 -88
  394. package/dist/types/modes/bridge/event-stream.d.ts +0 -8
  395. package/dist/types/modes/rpc/host-tools.d.ts +0 -1
  396. package/dist/types/modes/rpc/host-uris.d.ts +0 -1
  397. package/dist/types/modes/rpc/rpc-client.d.ts +0 -299
  398. package/dist/types/modes/rpc/rpc-mode.d.ts +0 -86
  399. package/dist/types/modes/rpc/rpc-socket-security.d.ts +0 -10
  400. package/dist/types/modes/rpc/rpc-types.d.ts +0 -810
  401. package/dist/types/modes/shared/agent-wire/command-contract.d.ts +0 -18
  402. package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +0 -37
  403. package/dist/types/modes/shared/agent-wire/command-validation.d.ts +0 -2
  404. package/dist/types/modes/shared/agent-wire/handshake.d.ts +0 -56
  405. package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +0 -16
  406. package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +0 -17
  407. package/dist/types/modes/shared/agent-wire/protocol.d.ts +0 -25
  408. package/dist/types/modes/shared/agent-wire/responses.d.ts +0 -4
  409. package/dist/types/modes/shared/agent-wire/scopes.d.ts +0 -18
  410. package/dist/types/modes/shared/agent-wire/session-registry.d.ts +0 -25
  411. package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +0 -42
  412. package/dist/types/modes/shared/agent-wire/ui-result.d.ts +0 -27
  413. package/dist/types/modes/shared/agent-wire/unattended-action-policy.d.ts +0 -29
  414. package/dist/types/modes/shared/agent-wire/unattended-audit.d.ts +0 -68
  415. package/dist/types/modes/shared/agent-wire/unattended-run-controller.d.ts +0 -166
  416. package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +0 -127
  417. package/dist/types/notifications/config.d.ts +0 -132
  418. package/src/harness-control-plane/rpc-adapter.ts +0 -290
  419. package/src/modes/bridge/auth.ts +0 -41
  420. package/src/modes/bridge/bridge-client-bridge.ts +0 -47
  421. package/src/modes/bridge/bridge-mode.ts +0 -675
  422. package/src/modes/bridge/bridge-ui-context.ts +0 -200
  423. package/src/modes/bridge/event-stream.ts +0 -70
  424. package/src/modes/rpc/host-tools.ts +0 -1
  425. package/src/modes/rpc/host-uris.ts +0 -1
  426. package/src/modes/rpc/rpc-client.ts +0 -1166
  427. package/src/modes/rpc/rpc-mode.ts +0 -1029
  428. package/src/modes/rpc/rpc-socket-security.ts +0 -115
  429. package/src/modes/rpc/rpc-types.ts +0 -637
  430. package/src/modes/shared/agent-wire/command-contract.ts +0 -18
  431. package/src/modes/shared/agent-wire/command-dispatch.ts +0 -498
  432. package/src/modes/shared/agent-wire/command-validation.ts +0 -181
  433. package/src/modes/shared/agent-wire/handshake.ts +0 -157
  434. package/src/modes/shared/agent-wire/host-tool-bridge.ts +0 -197
  435. package/src/modes/shared/agent-wire/host-uri-bridge.ts +0 -236
  436. package/src/modes/shared/agent-wire/protocol.ts +0 -46
  437. package/src/modes/shared/agent-wire/responses.ts +0 -17
  438. package/src/modes/shared/agent-wire/scopes.ts +0 -94
  439. package/src/modes/shared/agent-wire/session-registry.ts +0 -109
  440. package/src/modes/shared/agent-wire/ui-request-broker.ts +0 -150
  441. package/src/modes/shared/agent-wire/ui-result.ts +0 -48
  442. package/src/modes/shared/agent-wire/unattended-action-policy.ts +0 -365
  443. package/src/modes/shared/agent-wire/unattended-audit.ts +0 -176
  444. package/src/modes/shared/agent-wire/unattended-run-controller.ts +0 -426
  445. package/src/modes/shared/agent-wire/unattended-session.ts +0 -528
  446. package/src/notifications/config.ts +0 -219
  447. package/src/notifications/index.ts +0 -1835
  448. package/src/notifications/telegram-daemon-cli.ts +0 -243
  449. package/src/tools/puppeteer/09_stealth_locale.txt +0 -46
  450. /package/dist/types/{notifications → sdk/bus}/attachment-registry.d.ts +0 -0
  451. /package/dist/types/{notifications → sdk/bus}/chat-adapters.d.ts +0 -0
  452. /package/dist/types/{notifications → sdk/bus}/daemon-paths.d.ts +0 -0
  453. /package/dist/types/{notifications → sdk/bus}/engine.d.ts +0 -0
  454. /package/dist/types/{notifications → sdk/bus}/helpers.d.ts +0 -0
  455. /package/dist/types/{notifications → sdk/bus}/lifecycle-commands.d.ts +0 -0
  456. /package/dist/types/{notifications → sdk/bus}/operator-runtime.d.ts +0 -0
  457. /package/dist/types/{notifications → sdk/bus}/rate-limit-pool.d.ts +0 -0
  458. /package/dist/types/{notifications → sdk/bus}/recent-activity.d.ts +0 -0
  459. /package/dist/types/{notifications → sdk/bus}/reply-sent-store.d.ts +0 -0
  460. /package/dist/types/{notifications → sdk/bus}/rich-draft.d.ts +0 -0
  461. /package/dist/types/{notifications → sdk/bus}/rich-render.d.ts +0 -0
  462. /package/dist/types/{notifications → sdk/bus}/threaded-inbound.d.ts +0 -0
  463. /package/dist/types/{notifications → sdk/bus}/threaded-render.d.ts +0 -0
  464. /package/src/{notifications → sdk/bus}/attachment-registry.ts +0 -0
  465. /package/src/{notifications → sdk/bus}/chat-adapters.ts +0 -0
  466. /package/src/{notifications → sdk/bus}/daemon-paths.ts +0 -0
  467. /package/src/{notifications → sdk/bus}/engine.ts +0 -0
  468. /package/src/{notifications → sdk/bus}/helpers.ts +0 -0
  469. /package/src/{notifications → sdk/bus}/operator-runtime.ts +0 -0
  470. /package/src/{notifications → sdk/bus}/rate-limit-pool.ts +0 -0
  471. /package/src/{notifications → sdk/bus}/recent-activity.ts +0 -0
  472. /package/src/{notifications → sdk/bus}/reply-sent-store.ts +0 -0
  473. /package/src/{notifications → sdk/bus}/rich-draft.ts +0 -0
  474. /package/src/{notifications → sdk/bus}/rich-render.ts +0 -0
  475. /package/src/{notifications → sdk/bus}/threaded-inbound.ts +0 -0
  476. /package/src/{notifications → sdk/bus}/threaded-render.ts +0 -0
@@ -9,6 +9,7 @@ import { DEFAULT_ULTRAGOAL_OBJECTIVE } from "./goal-mode-request";
9
9
  import {
10
10
  computeUltragoalPlanGeneration,
11
11
  findFreshBatchCloseReceipt,
12
+ findLedgerReceiptEvent,
12
13
  requiredUltragoalGoals,
13
14
  validateDeferredMemberReceiptFresh,
14
15
  validateReceiptFreshBase,
@@ -572,16 +573,32 @@ async function writePlan(cwd: string, plan: UltragoalPlan, sessionId?: string |
572
573
 
573
574
  function chooseReceiptKind(
574
575
  plan: UltragoalPlan,
576
+ ledger: readonly UltragoalLedgerEvent[],
575
577
  goal: UltragoalGoal,
576
578
  status: UltragoalGoalStatus,
577
579
  ): UltragoalReceiptKind {
578
580
  if (plan.gjcGoalMode === "per-story") return "per-goal";
579
581
  if (status !== "complete") return "per-goal";
582
+ // A non-final validation-batch member must always carry a per-goal
583
+ // deferred receipt; only the batch's final goal may close the batch and
584
+ // (in aggregate mode) carry the final-aggregate receipt. Without this, a
585
+ // context-stale re-verification replay of a member could mint an invalid
586
+ // final-aggregate receipt with validationBatch.role "deferred-member".
587
+ if (goal.validationBatch && goal.validationBatch.finalGoalId !== goal.id) return "per-goal";
580
588
  const requiredGoals = requiredUltragoalGoals(plan);
581
- const existingFinalAggregateGoal = requiredGoals.find(
582
- item => item.id !== goal.id && item.completionVerification?.receiptKind === "final-aggregate",
583
- );
584
- if (existingFinalAggregateGoal) return "per-goal";
589
+ // Only a still-fresh final-aggregate receipt on another goal defers this
590
+ // checkpoint to per-goal. A stale one (e.g. staled by `steer add_subgoal`
591
+ // appending goals after a terminal run) must not suppress re-minting,
592
+ // otherwise the run can never regain a verifiable final-aggregate receipt:
593
+ // the completion guard demands a fresh final-aggregate receipt while this
594
+ // gate would keep answering per-goal forever.
595
+ const existingFreshFinalAggregateGoal = requiredGoals.find(item => {
596
+ if (item.id === goal.id) return false;
597
+ const receipt = item.completionVerification;
598
+ if (receipt?.receiptKind !== "final-aggregate") return false;
599
+ return validateReceiptFreshBase({ plan, ledger, goal: item, receipt, receiptKind: "final-aggregate" }) === null;
600
+ });
601
+ if (existingFreshFinalAggregateGoal) return "per-goal";
585
602
  const unfinishedRequiredGoals = requiredGoals.filter(
586
603
  item => item.id !== goal.id && !TERMINAL_OR_SKIPPED_STATUSES.has(item.status),
587
604
  );
@@ -3451,7 +3468,12 @@ function canonicalChangeSetRows(value: unknown, fieldName: string): UltragoalCha
3451
3468
  if ("goalId" in record) throw new Error(`${fieldName}[${index}] must not contain goalId attribution`);
3452
3469
  const status = nonEmptyString(record.status);
3453
3470
  if (!status) throw new Error(`${fieldName}[${index}].status is required`);
3454
- return { path: normalizeRepoPath(pathValue), status: status as UltragoalChangeStatus };
3471
+ const oldPath = nonEmptyString(record.oldPath);
3472
+ return {
3473
+ path: normalizeRepoPath(pathValue),
3474
+ status: status as UltragoalChangeStatus,
3475
+ ...(oldPath ? { oldPath: normalizeRepoPath(oldPath) } : {}),
3476
+ };
3455
3477
  });
3456
3478
  }
3457
3479
 
@@ -3711,6 +3733,140 @@ function validateBatchCloseQualityGate(
3711
3733
  throw new Error("validationBatchClose.unionChangeSet.unionHash does not match declared union");
3712
3734
  requireNonEmptyString(close.coverageEvidence, "validationBatchClose.coverageEvidence");
3713
3735
  }
3736
+
3737
+ function hydrateReviewedBatchReplacementClose(input: {
3738
+ gate: JsonObject;
3739
+ plan: UltragoalPlan;
3740
+ goal: UltragoalGoal;
3741
+ metadata: UltragoalValidationBatchMetadata;
3742
+ ledger: readonly UltragoalLedgerEvent[];
3743
+ changeSet?: UltragoalChangeSet;
3744
+ }): JsonObject {
3745
+ const requested = qualityGateObject(input.gate.validationBatchClose);
3746
+ if (requested?.kind !== "review-blocker-replacement-close") return input.gate;
3747
+ const expectedKeys = new Set(["schemaVersion", "kind", "replacementGoalId", "coverageEvidence"]);
3748
+ if (Object.keys(requested).some(key => !expectedKeys.has(key)))
3749
+ throw new Error("review-blocker replacement close contains unsupported fields");
3750
+ const replacementGoalId = nonEmptyString(requested.replacementGoalId);
3751
+ const coverageEvidence = nonEmptyString(requested.coverageEvidence);
3752
+ if (requested.schemaVersion !== 1 || !replacementGoalId || !coverageEvidence)
3753
+ throw new Error("review-blocker replacement close is malformed");
3754
+ if (input.goal.status !== "active" || input.metadata.finalGoalId !== input.goal.id)
3755
+ throw new Error("review-blocker replacement close requires the active durable validation-batch final goal");
3756
+ if (!input.changeSet) throw new Error("review-blocker replacement close requires a current cumulative change set");
3757
+
3758
+ const replacements = input.plan.goals.filter(
3759
+ goal => goal.steering?.kind === "review_blocker" && goal.steering.blockedGoalId === input.goal.id,
3760
+ );
3761
+ if (replacements.length !== 1 || replacements[0]?.id !== replacementGoalId)
3762
+ throw new Error("review-blocker replacement close requires exactly the declared replacement");
3763
+ const replacement = replacements[0]!;
3764
+ const replacementReceipt = replacement.completionVerification;
3765
+ if (replacement.status !== "complete" || replacementReceipt?.receiptKind !== "per-goal")
3766
+ throw new Error("review-blocker replacement close requires a completed per-goal replacement receipt");
3767
+ const replacementDiagnostic = validateReceiptFreshBase({
3768
+ plan: input.plan,
3769
+ ledger: input.ledger,
3770
+ goal: replacement,
3771
+ receipt: replacementReceipt,
3772
+ receiptKind: "per-goal",
3773
+ });
3774
+ if (replacementDiagnostic) throw new Error(`review-blocker replacement close ${replacementDiagnostic.message}`);
3775
+ const replacementCheckpointIndex = input.ledger.findIndex(
3776
+ event => event.eventId === replacementReceipt.checkpointLedgerEventId,
3777
+ );
3778
+ const reviewRecordedIndex = input.ledger.findIndex(
3779
+ event =>
3780
+ event.event === "review_blockers_recorded" &&
3781
+ event.goalId === input.goal.id &&
3782
+ event.blockerGoalId === replacement.id,
3783
+ );
3784
+ const reactivatedIndex = input.ledger.findIndex(
3785
+ (event, index) =>
3786
+ index > replacementCheckpointIndex &&
3787
+ event.event === "goal_checkpointed" &&
3788
+ event.goalId === input.goal.id &&
3789
+ event.status === "active",
3790
+ );
3791
+ if (reviewRecordedIndex < 0 || reviewRecordedIndex >= replacementCheckpointIndex || reactivatedIndex < 0)
3792
+ throw new Error("review-blocker replacement close lacks durable supersession and reopening evidence");
3793
+
3794
+ const historicalRequiredGoalIds = input.plan.goals
3795
+ .filter(goal => goal.id !== input.goal.id && goal.status !== "superseded")
3796
+ .map(goal => goal.id);
3797
+ const aggregateGoals = input.plan.goals.filter(goal => {
3798
+ const receipt = goal.completionVerification;
3799
+ return goal.status === "complete" && receipt?.receiptKind === "final-aggregate";
3800
+ });
3801
+ const aggregateGoal = aggregateGoals.find(goal => {
3802
+ const receipt = goal.completionVerification!;
3803
+ const event = findLedgerReceiptEvent(input.ledger, receipt);
3804
+ return (
3805
+ event !== null &&
3806
+ hashStructuredValue(event.qualityGateJson) === receipt.qualityGateHash &&
3807
+ goal.updatedAt === receipt.verifiedAt &&
3808
+ receipt.basis.relevantGoalIdsBeforeCheckpoint.length === historicalRequiredGoalIds.length &&
3809
+ receipt.basis.relevantGoalIdsBeforeCheckpoint.every(
3810
+ (goalId, index) => goalId === historicalRequiredGoalIds[index],
3811
+ )
3812
+ );
3813
+ });
3814
+ if (!aggregateGoal)
3815
+ throw new Error(
3816
+ "review-blocker replacement close requires a fresh final-aggregate receipt covering required goals",
3817
+ );
3818
+
3819
+ const memberMetadataHashes: Record<string, string> = {};
3820
+ const memberChangeSetHashes: Record<string, string> = {};
3821
+ const memberReceipts: JsonObject[] = [];
3822
+ for (const memberId of input.metadata.memberIds) {
3823
+ const member = input.plan.goals.find(goal => goal.id === memberId);
3824
+ if (!member?.validationBatch)
3825
+ throw new Error(`review-blocker replacement close references missing batch member ${memberId}`);
3826
+ memberMetadataHashes[memberId] = member.validationBatch.metadataHash;
3827
+ if (memberId === input.goal.id) continue;
3828
+ const receipt = requireDeferredMemberReceiptFresh(
3829
+ input.plan,
3830
+ input.ledger,
3831
+ member,
3832
+ "review-blocker replacement close",
3833
+ );
3834
+ memberChangeSetHashes[memberId] = receipt.validationBatch.changeSetHash;
3835
+ memberReceipts.push({
3836
+ goalId: memberId,
3837
+ receiptId: receipt.receiptId,
3838
+ checkpointLedgerEventId: receipt.checkpointLedgerEventId,
3839
+ qualityGateHash: receipt.qualityGateHash,
3840
+ changeSetHash: receipt.validationBatch.changeSetHash,
3841
+ role: "deferred-member",
3842
+ });
3843
+ }
3844
+ const paths = input.changeSet.paths.map(row => ({ ...row }));
3845
+ memberChangeSetHashes[input.goal.id] = changeSetHashForPaths(paths);
3846
+ const unionHash = hashStructuredValue({
3847
+ memberChangeSetHashes,
3848
+ paths: paths.map(row => ({ path: row.path, status: row.status, oldPath: row.oldPath })),
3849
+ });
3850
+ return {
3851
+ ...input.gate,
3852
+ validationBatchClose: {
3853
+ schemaVersion: 1,
3854
+ kind: "validation-batch-close",
3855
+ batchId: input.metadata.batchId,
3856
+ finalGoalId: input.metadata.finalGoalId,
3857
+ memberIds: [...input.metadata.memberIds],
3858
+ memberMetadataHashes,
3859
+ memberReceipts,
3860
+ unionChangeSet: {
3861
+ source: "validation-batch",
3862
+ memberChangeSetHashes,
3863
+ paths,
3864
+ unionHash,
3865
+ },
3866
+ coverageEvidence,
3867
+ },
3868
+ };
3869
+ }
3714
3870
  async function readRequiredCompletionQualityGate(
3715
3871
  cwd: string,
3716
3872
  value: string | undefined,
@@ -3729,13 +3885,25 @@ async function readRequiredCompletionQualityGate(
3729
3885
  const gate = await readStructuredValue(cwd, value);
3730
3886
  const gateObject = qualityGateObject(gate);
3731
3887
  if (!gateObject) throw new Error("qualityGate must be a JSON object");
3732
- await validateCompletionQualityGate(cwd, gateObject, {
3888
+ const validationBatch = options.goal ? requireFreshValidationBatchMetadata(options.goal) : undefined;
3889
+ const hydratedGate =
3890
+ validationBatch && options.plan && options.goal && options.ledger
3891
+ ? hydrateReviewedBatchReplacementClose({
3892
+ gate: gateObject,
3893
+ plan: options.plan,
3894
+ goal: options.goal,
3895
+ metadata: validationBatch,
3896
+ ledger: options.ledger,
3897
+ changeSet: options.changeSet,
3898
+ })
3899
+ : gateObject;
3900
+ await validateCompletionQualityGate(cwd, hydratedGate, {
3733
3901
  changeSet: options.changeSet,
3734
3902
  plan: options.plan,
3735
3903
  goal: options.goal,
3736
3904
  ledger: options.ledger,
3737
3905
  });
3738
- return gate;
3906
+ return hydratedGate;
3739
3907
  }
3740
3908
 
3741
3909
  function validatePipelineCheckpointSafety(
@@ -3812,13 +3980,21 @@ export async function checkpointUltragoalGoal(input: {
3812
3980
  const evidence = input.evidence.trim();
3813
3981
  if (!evidence) throw new Error("checkpoint evidence is required");
3814
3982
  const ledgerBefore = await readUltragoalLedger(input.cwd);
3815
- const matchingIdempotentEvent = ledgerBefore.find(
3983
+ const matchingIdempotentEvents = ledgerBefore.filter(
3816
3984
  event =>
3817
3985
  event.event === "goal_checkpointed" &&
3818
3986
  event.goalId === goal.id &&
3819
3987
  event.status === input.status &&
3820
3988
  event.evidence === evidence,
3821
3989
  );
3990
+ // Re-verification replays legitimately append repeated same-status,
3991
+ // same-evidence checkpoint events for one goal. The recorded receipt must
3992
+ // be compared against ITS OWN checkpoint event — resolved by the receipt's
3993
+ // checkpointLedgerEventId, falling back to the latest match — never the
3994
+ // oldest duplicate, which would wrongly report the current receipt stale.
3995
+ const matchingIdempotentEvent =
3996
+ matchingIdempotentEvents.find(event => event.eventId === goal.completionVerification?.checkpointLedgerEventId) ??
3997
+ matchingIdempotentEvents.at(-1);
3822
3998
  const batchMetadata = input.status === "complete" ? requireFreshValidationBatchMetadata(goal) : undefined;
3823
3999
  if (batchMetadata && goal.completionVerification?.validationBatch) {
3824
4000
  const receiptBatch = goal.completionVerification.validationBatch;
@@ -3835,7 +4011,35 @@ export async function checkpointUltragoalGoal(input: {
3835
4011
  if (input.status === "complete" && goal.completionVerification?.validationBatch && !batchMetadata) {
3836
4012
  throw new Error(`Goal ${goal.id} has stale validation batch completion receipt`);
3837
4013
  }
3838
- if (goal.status === input.status && goal.evidence === evidence && matchingIdempotentEvent) {
4014
+ // An identical-evidence complete replay is only a no-op while the recorded
4015
+ // receipt still validates fresh. When the goal row itself is untouched
4016
+ // (updatedAt still matches the receipt's verifiedAt) but later goal-tagged
4017
+ // ledger events (e.g. blocker classifications) or plan growth staled the
4018
+ // receipt, the replay is a genuine re-verification: it must run the full
4019
+ // quality gate and mint a fresh receipt, otherwise a completed goal with a
4020
+ // context-staled receipt can never be repaired (different evidence is
4021
+ // rejected on complete goals by design). A mutated goal row keeps the
4022
+ // fail-loud tamper handling in the idempotent branch below.
4023
+ const staleCompleteReceiptReplay =
4024
+ input.status === "complete" &&
4025
+ goal.status === "complete" &&
4026
+ goal.evidence === evidence &&
4027
+ Boolean(matchingIdempotentEvent) &&
4028
+ (!goal.completionVerification ||
4029
+ (goal.completionVerification.verifiedAt === goal.updatedAt &&
4030
+ validateReceiptFreshBase({
4031
+ plan,
4032
+ ledger: ledgerBefore,
4033
+ goal,
4034
+ receipt: goal.completionVerification,
4035
+ receiptKind: goal.completionVerification.receiptKind,
4036
+ }) !== null));
4037
+ if (
4038
+ goal.status === input.status &&
4039
+ goal.evidence === evidence &&
4040
+ matchingIdempotentEvent &&
4041
+ !staleCompleteReceiptReplay
4042
+ ) {
3839
4043
  if (batchMetadata) {
3840
4044
  const receipt = goal.completionVerification;
3841
4045
  const receiptBatch = receipt?.validationBatch;
@@ -3857,6 +4061,18 @@ export async function checkpointUltragoalGoal(input: {
3857
4061
  )
3858
4062
  throw new Error(`Goal ${goal.id} has stale validation batch metadata hash in close receipt`);
3859
4063
  }
4064
+ // A complete goal whose row changed after its receipt was verified is
4065
+ // neither a clean no-op nor a repairable context-stale replay: fail loud
4066
+ // instead of silently laundering a tampered/inconsistent durable row.
4067
+ if (
4068
+ input.status === "complete" &&
4069
+ goal.completionVerification &&
4070
+ goal.completionVerification.verifiedAt !== goal.updatedAt
4071
+ ) {
4072
+ throw new Error(
4073
+ `Goal ${goal.id} changed after its completion receipt was verified; refusing idempotent replay. Investigate the durable goals.json row before re-checkpointing.`,
4074
+ );
4075
+ }
3860
4076
  // Idempotent re-checkpoint: this goal is already recorded in the target status with the same
3861
4077
  // evidence, so skip the plan rewrite and ledger append to avoid duplicate goal_checkpointed
3862
4078
  // events. The ledger is the dedup source of truth because it is exactly what a duplicate write
@@ -3868,7 +4084,7 @@ export async function checkpointUltragoalGoal(input: {
3868
4084
  const changeSet = input.status === "complete" ? await computeCheckpointChangeSet(input.cwd) : undefined;
3869
4085
  if (input.status === "complete") {
3870
4086
  validatePipelineCheckpointSafety(plan, goal, changeSet);
3871
- validateCompleteCheckpointTargetGoal(goal);
4087
+ if (!staleCompleteReceiptReplay) validateCompleteCheckpointTargetGoal(goal);
3872
4088
  }
3873
4089
  const qualityGateJson =
3874
4090
  input.status === "complete"
@@ -3895,7 +4111,7 @@ export async function checkpointUltragoalGoal(input: {
3895
4111
  blockedGoal.updatedAt = now;
3896
4112
  }
3897
4113
  }
3898
- const receiptKind = input.status === "complete" ? chooseReceiptKind(plan, goal, input.status) : null;
4114
+ const receiptKind = input.status === "complete" ? chooseReceiptKind(plan, ledgerBefore, goal, input.status) : null;
3899
4115
  const pendingCheckpointEventId = crypto.randomUUID();
3900
4116
  if (input.status === "complete" && receiptKind && qualityGateJson && !Array.isArray(qualityGateJson)) {
3901
4117
  goal.completionVerification = buildCompletionReceipt({
@@ -0,0 +1,58 @@
1
+ import { Buffer } from "node:buffer";
2
+ import * as path from "node:path";
3
+
4
+ export const GJC_TMUX_LAUNCHED_ENV = "GJC_TMUX_LAUNCHED";
5
+
6
+ export interface WindowsPowerShellInnerCommandOptions {
7
+ command: readonly string[];
8
+ args?: readonly string[];
9
+ environment?: Record<string, string>;
10
+ tmuxExitMarkerPath?: string;
11
+ }
12
+
13
+ function powershellQuote(value: string): string {
14
+ return `'${value.replace(/'/g, "''")}'`;
15
+ }
16
+
17
+ function buildPowerShellTmuxExitMarkerFinally(markerPath: string): string {
18
+ const markerDir = path.win32.dirname(markerPath);
19
+ return [
20
+ "} finally {",
21
+ "\ttry {",
22
+ `\t\tNew-Item -ItemType Directory -Force -Path ${powershellQuote(markerDir)} -ErrorAction Stop | Out-Null`,
23
+ "\t\t$__gjcTmuxExitMarker = @{ schema_version = 1; source = 'tmux_inner_shell'; ended_at = (Get-Date).ToUniversalTime().ToString('o'); exit_code = $__gjcTmuxExitCode } | ConvertTo-Json -Compress",
24
+ `\t\tSet-Content -LiteralPath ${powershellQuote(markerPath)} -Value $__gjcTmuxExitMarker -Encoding UTF8 -ErrorAction Stop`,
25
+ "\t} catch {",
26
+ "\t}",
27
+ "}",
28
+ ].join("\n");
29
+ }
30
+
31
+ /** Builds the shared BOM-free UTF-16LE command for native Windows tmux-compatible panes. */
32
+ export function buildWindowsPowerShellInnerCommand({
33
+ command,
34
+ args = [],
35
+ environment,
36
+ tmuxExitMarkerPath,
37
+ }: WindowsPowerShellInnerCommandOptions): string {
38
+ const envLines = Object.entries({ [GJC_TMUX_LAUNCHED_ENV]: "1", ...(environment ?? {}) }).map(
39
+ ([key, value]) => `$env:${key} = ${powershellQuote(value)}`,
40
+ );
41
+ const resolvedCommand = command.map(powershellQuote).join(" ");
42
+ const innerArgs = args.map(powershellQuote).join(" ");
43
+ const invocation = `& ${resolvedCommand} ${innerArgs}`;
44
+ const exitLine = "if ($null -ne $LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 }";
45
+ const script = tmuxExitMarkerPath
46
+ ? [
47
+ ...envLines,
48
+ "$__gjcTmuxExitCode = 1",
49
+ "try {",
50
+ `\t${invocation}`,
51
+ "\tif ($null -ne $LASTEXITCODE) { $__gjcTmuxExitCode = $LASTEXITCODE } else { $__gjcTmuxExitCode = 1 }",
52
+ buildPowerShellTmuxExitMarkerFinally(tmuxExitMarkerPath),
53
+ "exit $__gjcTmuxExitCode",
54
+ ].join("\n")
55
+ : [...envLines, invocation, exitLine].join("\n");
56
+ const encodedCommand = Buffer.from(script, "utf16le").toString("base64");
57
+ return `pwsh -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encodedCommand}`;
58
+ }
@@ -19,7 +19,7 @@ import {
19
19
  type VanishEvidence,
20
20
  validateReceipt,
21
21
  } from "./receipts";
22
- import { type HarnessRpc, singleFlightAccept } from "./rpc-adapter";
22
+ import { type HarnessSessionTransport, singleFlightAccept } from "./session-transport";
23
23
  import { writeReceiptImmutable } from "./storage";
24
24
  import {
25
25
  DEFAULT_RETRY_BUDGET,
@@ -35,10 +35,10 @@ export interface OperateOptions {
35
35
  sessionId: string;
36
36
  workspace: string;
37
37
  branch: string;
38
- rpc: HarnessRpc;
39
- /** Factory used to (re)create the RPC subprocess on restart recovery. Defaults to reusing `rpc`. */
40
- rpcFactory?: () => HarnessRpc;
41
- /** Bounded observation provider (scripted in tests; real = git + rpc state). */
38
+ transport: HarnessSessionTransport;
39
+ /** Factory used to recreate an SDK transport on restart recovery. Defaults to reusing `transport`. */
40
+ transportFactory?: () => HarnessSessionTransport;
41
+ /** Bounded observation provider (scripted in tests; real = git + SDK session state). */
42
42
  observe: () => Promise<Observation>;
43
43
  /** Real dirty-worktree preservation; injectable for tests. Defaults to git stash/diff capture. */
44
44
  preserve?: (workspace: string) => PreserveResult;
@@ -71,7 +71,7 @@ export async function operate(goal: string, opts: OperateOptions): Promise<Opera
71
71
  const vanishReceiptIds: string[] = [];
72
72
  const blockers: string[] = [];
73
73
 
74
- let rpc = opts.rpc;
74
+ let transport = opts.transport;
75
75
 
76
76
  const now = (): string => new Date(opts.clock ? opts.clock() : Date.now()).toISOString();
77
77
  let lifecycle: HarnessLifecycle = "started";
@@ -118,7 +118,7 @@ export async function operate(goal: string, opts: OperateOptions): Promise<Opera
118
118
  };
119
119
 
120
120
  const submit = async (): Promise<boolean> => {
121
- const acc = await singleFlightAccept(rpc, goal, acceptanceTimeoutMs);
121
+ const acc = await singleFlightAccept(transport, goal, acceptanceTimeoutMs);
122
122
  await emit(acc.accepted ? "info" : "warn", acc.accepted ? "prompt_accepted" : "prompt_not_accepted", {
123
123
  reason: acc.reason,
124
124
  });
@@ -160,11 +160,11 @@ export async function operate(goal: string, opts: OperateOptions): Promise<Opera
160
160
  accepted = await submit();
161
161
  } else if (decision.classification === "restart-clean") {
162
162
  budget.zeroDeltaVanish = Math.max(0, budget.zeroDeltaVanish - 1);
163
- rpc = opts.rpcFactory ? opts.rpcFactory() : rpc;
163
+ transport = opts.transportFactory ? opts.transportFactory() : transport;
164
164
  accepted = await submit();
165
165
  } else if (decision.classification === "restart-preserve-delta") {
166
166
  budget.dirtyVanishPreserve = Math.max(0, budget.dirtyVanishPreserve - 1);
167
- rpc = opts.rpcFactory ? opts.rpcFactory() : rpc;
167
+ transport = opts.transportFactory ? opts.transportFactory() : transport;
168
168
  accepted = await submit();
169
169
  } else if (decision.classification === "fallback-codex-exec") {
170
170
  lifecycle = "blocked";