oh-my-codex 0.20.3 → 0.20.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (661) hide show
  1. package/Cargo.lock +35 -18
  2. package/Cargo.toml +1 -1
  3. package/README.md +2 -2
  4. package/crates/omx-runtime/Cargo.toml +3 -0
  5. package/crates/omx-runtime/src/main.rs +390 -0
  6. package/crates/omx-runtime/tests/execution.rs +264 -0
  7. package/dist/adapt/__tests__/herdr-target.test.d.ts +2 -0
  8. package/dist/adapt/__tests__/herdr-target.test.d.ts.map +1 -0
  9. package/dist/adapt/__tests__/herdr-target.test.js +72 -0
  10. package/dist/adapt/__tests__/herdr-target.test.js.map +1 -0
  11. package/dist/adapt/contracts.d.ts +1 -1
  12. package/dist/adapt/contracts.d.ts.map +1 -1
  13. package/dist/adapt/contracts.js +1 -1
  14. package/dist/adapt/contracts.js.map +1 -1
  15. package/dist/adapt/herdr/__tests__/authority.test.d.ts +2 -0
  16. package/dist/adapt/herdr/__tests__/authority.test.d.ts.map +1 -0
  17. package/dist/adapt/herdr/__tests__/authority.test.js +49 -0
  18. package/dist/adapt/herdr/__tests__/authority.test.js.map +1 -0
  19. package/dist/adapt/herdr/__tests__/bridge.test.d.ts +2 -0
  20. package/dist/adapt/herdr/__tests__/bridge.test.d.ts.map +1 -0
  21. package/dist/adapt/herdr/__tests__/bridge.test.js +176 -0
  22. package/dist/adapt/herdr/__tests__/bridge.test.js.map +1 -0
  23. package/dist/adapt/herdr/__tests__/sanitize.test.d.ts +2 -0
  24. package/dist/adapt/herdr/__tests__/sanitize.test.d.ts.map +1 -0
  25. package/dist/adapt/herdr/__tests__/sanitize.test.js +45 -0
  26. package/dist/adapt/herdr/__tests__/sanitize.test.js.map +1 -0
  27. package/dist/adapt/herdr/__tests__/semantic.test.d.ts +2 -0
  28. package/dist/adapt/herdr/__tests__/semantic.test.d.ts.map +1 -0
  29. package/dist/adapt/herdr/__tests__/semantic.test.js +130 -0
  30. package/dist/adapt/herdr/__tests__/semantic.test.js.map +1 -0
  31. package/dist/adapt/herdr/__tests__/seq-store.test.d.ts +2 -0
  32. package/dist/adapt/herdr/__tests__/seq-store.test.d.ts.map +1 -0
  33. package/dist/adapt/herdr/__tests__/seq-store.test.js +54 -0
  34. package/dist/adapt/herdr/__tests__/seq-store.test.js.map +1 -0
  35. package/dist/adapt/herdr/__tests__/socket-live.test.d.ts +2 -0
  36. package/dist/adapt/herdr/__tests__/socket-live.test.d.ts.map +1 -0
  37. package/dist/adapt/herdr/__tests__/socket-live.test.js +104 -0
  38. package/dist/adapt/herdr/__tests__/socket-live.test.js.map +1 -0
  39. package/dist/adapt/herdr/__tests__/team-map.test.d.ts +2 -0
  40. package/dist/adapt/herdr/__tests__/team-map.test.d.ts.map +1 -0
  41. package/dist/adapt/herdr/__tests__/team-map.test.js +46 -0
  42. package/dist/adapt/herdr/__tests__/team-map.test.js.map +1 -0
  43. package/dist/adapt/herdr/__tests__/transport.test.d.ts +2 -0
  44. package/dist/adapt/herdr/__tests__/transport.test.d.ts.map +1 -0
  45. package/dist/adapt/herdr/__tests__/transport.test.js +160 -0
  46. package/dist/adapt/herdr/__tests__/transport.test.js.map +1 -0
  47. package/dist/adapt/herdr/__tests__/wiring.test.d.ts +2 -0
  48. package/dist/adapt/herdr/__tests__/wiring.test.d.ts.map +1 -0
  49. package/dist/adapt/herdr/__tests__/wiring.test.js +118 -0
  50. package/dist/adapt/herdr/__tests__/wiring.test.js.map +1 -0
  51. package/dist/adapt/herdr/authority.d.ts +34 -0
  52. package/dist/adapt/herdr/authority.d.ts.map +1 -0
  53. package/dist/adapt/herdr/authority.js +71 -0
  54. package/dist/adapt/herdr/authority.js.map +1 -0
  55. package/dist/adapt/herdr/bridge.d.ts +84 -0
  56. package/dist/adapt/herdr/bridge.d.ts.map +1 -0
  57. package/dist/adapt/herdr/bridge.js +222 -0
  58. package/dist/adapt/herdr/bridge.js.map +1 -0
  59. package/dist/adapt/herdr/sanitize.d.ts +20 -0
  60. package/dist/adapt/herdr/sanitize.d.ts.map +1 -0
  61. package/dist/adapt/herdr/sanitize.js +70 -0
  62. package/dist/adapt/herdr/sanitize.js.map +1 -0
  63. package/dist/adapt/herdr/semantic.d.ts +67 -0
  64. package/dist/adapt/herdr/semantic.d.ts.map +1 -0
  65. package/dist/adapt/herdr/semantic.js +170 -0
  66. package/dist/adapt/herdr/semantic.js.map +1 -0
  67. package/dist/adapt/herdr/seq-store.d.ts +32 -0
  68. package/dist/adapt/herdr/seq-store.d.ts.map +1 -0
  69. package/dist/adapt/herdr/seq-store.js +126 -0
  70. package/dist/adapt/herdr/seq-store.js.map +1 -0
  71. package/dist/adapt/herdr/team-map.d.ts +30 -0
  72. package/dist/adapt/herdr/team-map.d.ts.map +1 -0
  73. package/dist/adapt/herdr/team-map.js +37 -0
  74. package/dist/adapt/herdr/team-map.js.map +1 -0
  75. package/dist/adapt/herdr/transport.d.ts +115 -0
  76. package/dist/adapt/herdr/transport.d.ts.map +1 -0
  77. package/dist/adapt/herdr/transport.js +260 -0
  78. package/dist/adapt/herdr/transport.js.map +1 -0
  79. package/dist/adapt/herdr/wiring.d.ts +24 -0
  80. package/dist/adapt/herdr/wiring.d.ts.map +1 -0
  81. package/dist/adapt/herdr/wiring.js +62 -0
  82. package/dist/adapt/herdr/wiring.js.map +1 -0
  83. package/dist/adapt/herdr.d.ts +19 -0
  84. package/dist/adapt/herdr.d.ts.map +1 -0
  85. package/dist/adapt/herdr.js +115 -0
  86. package/dist/adapt/herdr.js.map +1 -0
  87. package/dist/adapt/index.d.ts +4 -0
  88. package/dist/adapt/index.d.ts.map +1 -1
  89. package/dist/adapt/index.js +48 -0
  90. package/dist/adapt/index.js.map +1 -1
  91. package/dist/adapt/registry.d.ts.map +1 -1
  92. package/dist/adapt/registry.js +11 -0
  93. package/dist/adapt/registry.js.map +1 -1
  94. package/dist/auth/__tests__/hotswap.test.js +60 -1
  95. package/dist/auth/__tests__/hotswap.test.js.map +1 -1
  96. package/dist/auth/__tests__/storage.test.js +33 -1
  97. package/dist/auth/__tests__/storage.test.js.map +1 -1
  98. package/dist/auth/hotswap.d.ts +16 -2
  99. package/dist/auth/hotswap.d.ts.map +1 -1
  100. package/dist/auth/hotswap.js +22 -7
  101. package/dist/auth/hotswap.js.map +1 -1
  102. package/dist/auth/storage.js +1 -1
  103. package/dist/auth/storage.js.map +1 -1
  104. package/dist/autopilot/__tests__/ralplan-gate.test.js +86 -1333
  105. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  106. package/dist/autopilot/ralplan-gate.d.ts.map +1 -1
  107. package/dist/autopilot/ralplan-gate.js +7 -6
  108. package/dist/autopilot/ralplan-gate.js.map +1 -1
  109. package/dist/cli/__tests__/agents-init.test.js +4 -23
  110. package/dist/cli/__tests__/agents-init.test.js.map +1 -1
  111. package/dist/cli/__tests__/api.test.js +61 -24
  112. package/dist/cli/__tests__/api.test.js.map +1 -1
  113. package/dist/cli/__tests__/auth.test.js +3 -1
  114. package/dist/cli/__tests__/auth.test.js.map +1 -1
  115. package/dist/cli/__tests__/codex-feature-probe.test.js +66 -1
  116. package/dist/cli/__tests__/codex-feature-probe.test.js.map +1 -1
  117. package/dist/cli/__tests__/codex-plugin-layout.test.js +70 -2
  118. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  119. package/dist/cli/__tests__/detached-leader-teardown.test.d.ts +2 -0
  120. package/dist/cli/__tests__/detached-leader-teardown.test.d.ts.map +1 -0
  121. package/dist/cli/__tests__/detached-leader-teardown.test.js +473 -0
  122. package/dist/cli/__tests__/detached-leader-teardown.test.js.map +1 -0
  123. package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts +2 -0
  124. package/dist/cli/__tests__/doctor-process-identity-readiness.test.d.ts.map +1 -0
  125. package/dist/cli/__tests__/doctor-process-identity-readiness.test.js +103 -0
  126. package/dist/cli/__tests__/doctor-process-identity-readiness.test.js.map +1 -0
  127. package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts +2 -0
  128. package/dist/cli/__tests__/doctor-state-root-binding.test.d.ts.map +1 -0
  129. package/dist/cli/__tests__/doctor-state-root-binding.test.js +139 -0
  130. package/dist/cli/__tests__/doctor-state-root-binding.test.js.map +1 -0
  131. package/dist/cli/__tests__/doctor-warning-copy.test.js +35 -3
  132. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  133. package/dist/cli/__tests__/exec.test.js +75 -0
  134. package/dist/cli/__tests__/exec.test.js.map +1 -1
  135. package/dist/cli/__tests__/index.test.js +621 -460
  136. package/dist/cli/__tests__/index.test.js.map +1 -1
  137. package/dist/cli/__tests__/launch-fallback.test.js +1020 -143
  138. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  139. package/dist/cli/__tests__/mcp-parity.test.js +4 -3
  140. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  141. package/dist/cli/__tests__/native-assets.test.js +398 -16
  142. package/dist/cli/__tests__/native-assets.test.js.map +1 -1
  143. package/dist/cli/__tests__/native-hook-claim-journal.test.js +53 -5
  144. package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -1
  145. package/dist/cli/__tests__/ralph.test.js +2 -2
  146. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  147. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +57 -57
  148. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -1
  149. package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts +2 -0
  150. package/dist/cli/__tests__/ralplan-child-binding-3212.test.d.ts.map +1 -0
  151. package/dist/cli/__tests__/ralplan-child-binding-3212.test.js +56 -0
  152. package/dist/cli/__tests__/ralplan-child-binding-3212.test.js.map +1 -0
  153. package/dist/cli/__tests__/ralplan.test.js +84 -12
  154. package/dist/cli/__tests__/ralplan.test.js.map +1 -1
  155. package/dist/cli/__tests__/session-scoped-runtime.test.js +1118 -43
  156. package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
  157. package/dist/cli/__tests__/setup-agents-overwrite.test.js +8 -55
  158. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  159. package/dist/cli/__tests__/setup-install-mode.test.js +183 -4
  160. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  161. package/dist/cli/__tests__/sparkshell-cli.test.js +93 -41
  162. package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
  163. package/dist/cli/__tests__/team.test.js +45 -1
  164. package/dist/cli/__tests__/team.test.js.map +1 -1
  165. package/dist/cli/__tests__/ultragoal.test.js +117 -2
  166. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  167. package/dist/cli/__tests__/uninstall.test.js +50 -5
  168. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  169. package/dist/cli/__tests__/update.test.js +669 -177
  170. package/dist/cli/__tests__/update.test.js.map +1 -1
  171. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +32 -2
  172. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  173. package/dist/cli/api.d.ts.map +1 -1
  174. package/dist/cli/api.js +9 -10
  175. package/dist/cli/api.js.map +1 -1
  176. package/dist/cli/codex-feature-probe.d.ts +16 -0
  177. package/dist/cli/codex-feature-probe.d.ts.map +1 -1
  178. package/dist/cli/codex-feature-probe.js +44 -0
  179. package/dist/cli/codex-feature-probe.js.map +1 -1
  180. package/dist/cli/codex-home.d.ts.map +1 -1
  181. package/dist/cli/codex-home.js +7 -4
  182. package/dist/cli/codex-home.js.map +1 -1
  183. package/dist/cli/doctor.d.ts +17 -0
  184. package/dist/cli/doctor.d.ts.map +1 -1
  185. package/dist/cli/doctor.js +277 -3
  186. package/dist/cli/doctor.js.map +1 -1
  187. package/dist/cli/index.d.ts +231 -12
  188. package/dist/cli/index.d.ts.map +1 -1
  189. package/dist/cli/index.js +2298 -735
  190. package/dist/cli/index.js.map +1 -1
  191. package/dist/cli/native-assets.d.ts +25 -0
  192. package/dist/cli/native-assets.d.ts.map +1 -1
  193. package/dist/cli/native-assets.js +448 -51
  194. package/dist/cli/native-assets.js.map +1 -1
  195. package/dist/cli/native-hook-claim-journal.d.ts +8 -4
  196. package/dist/cli/native-hook-claim-journal.d.ts.map +1 -1
  197. package/dist/cli/native-hook-claim-journal.js +30 -8
  198. package/dist/cli/native-hook-claim-journal.js.map +1 -1
  199. package/dist/cli/package-manager-ownership.d.ts +63 -0
  200. package/dist/cli/package-manager-ownership.d.ts.map +1 -0
  201. package/dist/cli/package-manager-ownership.js +323 -0
  202. package/dist/cli/package-manager-ownership.js.map +1 -0
  203. package/dist/cli/ralph.js +2 -2
  204. package/dist/cli/ralph.js.map +1 -1
  205. package/dist/cli/ralplan.d.ts +4 -2
  206. package/dist/cli/ralplan.d.ts.map +1 -1
  207. package/dist/cli/ralplan.js +76 -34
  208. package/dist/cli/ralplan.js.map +1 -1
  209. package/dist/cli/setup-preferences.d.ts +15 -0
  210. package/dist/cli/setup-preferences.d.ts.map +1 -1
  211. package/dist/cli/setup-preferences.js +27 -1
  212. package/dist/cli/setup-preferences.js.map +1 -1
  213. package/dist/cli/setup.d.ts +3 -0
  214. package/dist/cli/setup.d.ts.map +1 -1
  215. package/dist/cli/setup.js +55 -32
  216. package/dist/cli/setup.js.map +1 -1
  217. package/dist/cli/sparkshell.d.ts.map +1 -1
  218. package/dist/cli/sparkshell.js +52 -9
  219. package/dist/cli/sparkshell.js.map +1 -1
  220. package/dist/cli/ultragoal.d.ts.map +1 -1
  221. package/dist/cli/ultragoal.js +2 -2
  222. package/dist/cli/ultragoal.js.map +1 -1
  223. package/dist/cli/uninstall.d.ts.map +1 -1
  224. package/dist/cli/uninstall.js +27 -28
  225. package/dist/cli/uninstall.js.map +1 -1
  226. package/dist/cli/update-worker.d.ts +2 -0
  227. package/dist/cli/update-worker.d.ts.map +1 -0
  228. package/dist/cli/update-worker.js +142 -0
  229. package/dist/cli/update-worker.js.map +1 -0
  230. package/dist/cli/update.d.ts +14 -22
  231. package/dist/cli/update.d.ts.map +1 -1
  232. package/dist/cli/update.js +192 -241
  233. package/dist/cli/update.js.map +1 -1
  234. package/dist/config/__tests__/generator-idempotent.test.js +173 -29
  235. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  236. package/dist/config/__tests__/generator-notify.test.js +3 -1
  237. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  238. package/dist/config/generator.d.ts +25 -3
  239. package/dist/config/generator.d.ts.map +1 -1
  240. package/dist/config/generator.js +113 -35
  241. package/dist/config/generator.js.map +1 -1
  242. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js +25 -0
  243. package/dist/goal-workflows/__tests__/codex-goal-snapshot.test.js.map +1 -1
  244. package/dist/goal-workflows/codex-goal-snapshot.d.ts +1 -1
  245. package/dist/goal-workflows/codex-goal-snapshot.d.ts.map +1 -1
  246. package/dist/goal-workflows/codex-goal-snapshot.js +2 -0
  247. package/dist/goal-workflows/codex-goal-snapshot.js.map +1 -1
  248. package/dist/hooks/__tests__/agents-overlay.test.js +3 -1
  249. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  250. package/dist/hooks/__tests__/autopilot-skill-contract.test.js +27 -4
  251. package/dist/hooks/__tests__/autopilot-skill-contract.test.js.map +1 -1
  252. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts +2 -0
  253. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.d.ts.map +1 -0
  254. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js +172 -0
  255. package/dist/hooks/__tests__/issue-3293-autopilot-handoff.test.js.map +1 -0
  256. package/dist/hooks/__tests__/keyword-detector.test.js +172 -33
  257. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  258. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +173 -11
  259. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  260. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +1 -0
  261. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  262. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +65 -17
  263. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  264. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +27 -0
  265. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  266. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +10 -118
  267. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  268. package/dist/hooks/__tests__/notify-hook-regression-205.test.js +7 -0
  269. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  270. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +2 -2
  271. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  272. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +4 -1
  273. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  274. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js +2 -1
  275. package/dist/hooks/__tests__/notify-hook-team-worker-fail-closed.test.js.map +1 -1
  276. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +1 -0
  277. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  278. package/dist/hooks/__tests__/prompt-guidance-contract.test.js +9 -0
  279. package/dist/hooks/__tests__/prompt-guidance-contract.test.js.map +1 -1
  280. package/dist/hooks/__tests__/session.test.js +2976 -557
  281. package/dist/hooks/__tests__/session.test.js.map +1 -1
  282. package/dist/hooks/agents-overlay.js +1 -1
  283. package/dist/hooks/agents-overlay.js.map +1 -1
  284. package/dist/hooks/extensibility/__tests__/dispatcher.test.js +108 -2
  285. package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
  286. package/dist/hooks/extensibility/__tests__/sdk.test.js +151 -1
  287. package/dist/hooks/extensibility/__tests__/sdk.test.js.map +1 -1
  288. package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
  289. package/dist/hooks/extensibility/dispatcher.js +20 -3
  290. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  291. package/dist/hooks/extensibility/plugin-runner.js +1 -0
  292. package/dist/hooks/extensibility/plugin-runner.js.map +1 -1
  293. package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
  294. package/dist/hooks/extensibility/runtime.js.map +1 -1
  295. package/dist/hooks/extensibility/sdk/paths.d.ts +1 -1
  296. package/dist/hooks/extensibility/sdk/paths.d.ts.map +1 -1
  297. package/dist/hooks/extensibility/sdk/paths.js +2 -2
  298. package/dist/hooks/extensibility/sdk/paths.js.map +1 -1
  299. package/dist/hooks/extensibility/sdk/runtime-state.d.ts +1 -1
  300. package/dist/hooks/extensibility/sdk/runtime-state.d.ts.map +1 -1
  301. package/dist/hooks/extensibility/sdk/runtime-state.js +55 -15
  302. package/dist/hooks/extensibility/sdk/runtime-state.js.map +1 -1
  303. package/dist/hooks/extensibility/sdk.d.ts +1 -0
  304. package/dist/hooks/extensibility/sdk.d.ts.map +1 -1
  305. package/dist/hooks/extensibility/sdk.js +1 -1
  306. package/dist/hooks/extensibility/sdk.js.map +1 -1
  307. package/dist/hooks/extensibility/types.d.ts +7 -0
  308. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  309. package/dist/hooks/keyword-detector.d.ts +10 -3
  310. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  311. package/dist/hooks/keyword-detector.js +116 -20
  312. package/dist/hooks/keyword-detector.js.map +1 -1
  313. package/dist/hooks/session.d.ts +180 -14
  314. package/dist/hooks/session.d.ts.map +1 -1
  315. package/dist/hooks/session.js +1402 -281
  316. package/dist/hooks/session.js.map +1 -1
  317. package/dist/hud/__tests__/hud-tmux-injection.test.js +6 -6
  318. package/dist/hud/__tests__/hud-tmux-injection.test.js.map +1 -1
  319. package/dist/hud/__tests__/index.test.js +26 -16
  320. package/dist/hud/__tests__/index.test.js.map +1 -1
  321. package/dist/hud/__tests__/reconcile.test.js +83 -78
  322. package/dist/hud/__tests__/reconcile.test.js.map +1 -1
  323. package/dist/hud/__tests__/state.test.js +36 -31
  324. package/dist/hud/__tests__/state.test.js.map +1 -1
  325. package/dist/hud/__tests__/tmux.test.js +155 -198
  326. package/dist/hud/__tests__/tmux.test.js.map +1 -1
  327. package/dist/hud/tmux.d.ts +42 -4
  328. package/dist/hud/tmux.d.ts.map +1 -1
  329. package/dist/hud/tmux.js +1017 -139
  330. package/dist/hud/tmux.js.map +1 -1
  331. package/dist/leader/__tests__/contract.test.js +71 -34
  332. package/dist/leader/__tests__/contract.test.js.map +1 -1
  333. package/dist/leader/contract.d.ts +1 -6
  334. package/dist/leader/contract.d.ts.map +1 -1
  335. package/dist/leader/contract.js +25 -24
  336. package/dist/leader/contract.js.map +1 -1
  337. package/dist/mcp/__tests__/hermes-bridge.test.js +17 -0
  338. package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -1
  339. package/dist/mcp/__tests__/server-lifecycle.test.js +4 -4
  340. package/dist/mcp/__tests__/state-paths.test.js +735 -4
  341. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  342. package/dist/mcp/__tests__/state-server.test.js +1 -1
  343. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  344. package/dist/mcp/__tests__/trace-server.test.js +2 -2
  345. package/dist/mcp/__tests__/trace-server.test.js.map +1 -1
  346. package/dist/mcp/hermes-bridge.d.ts.map +1 -1
  347. package/dist/mcp/hermes-bridge.js +2 -2
  348. package/dist/mcp/hermes-bridge.js.map +1 -1
  349. package/dist/mcp/state-paths.d.ts +78 -4
  350. package/dist/mcp/state-paths.d.ts.map +1 -1
  351. package/dist/mcp/state-paths.js +543 -40
  352. package/dist/mcp/state-paths.js.map +1 -1
  353. package/dist/mcp/state-server.d.ts +4 -4
  354. package/dist/mcp/state-server.d.ts.map +1 -1
  355. package/dist/modes/__tests__/base-autopilot-gates.test.js +36 -7
  356. package/dist/modes/__tests__/base-autopilot-gates.test.js.map +1 -1
  357. package/dist/modes/__tests__/base-multi-state-compat.test.js +1 -1
  358. package/dist/modes/__tests__/base-multi-state-compat.test.js.map +1 -1
  359. package/dist/modes/__tests__/base-session-scope.test.js +17 -8
  360. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  361. package/dist/modes/base.d.ts +5 -5
  362. package/dist/modes/base.d.ts.map +1 -1
  363. package/dist/modes/base.js +76 -21
  364. package/dist/modes/base.js.map +1 -1
  365. package/dist/native-assets/archive.d.ts +17 -0
  366. package/dist/native-assets/archive.d.ts.map +1 -0
  367. package/dist/native-assets/archive.js +238 -0
  368. package/dist/native-assets/archive.js.map +1 -0
  369. package/dist/native-assets/policy.d.ts +42 -0
  370. package/dist/native-assets/policy.d.ts.map +1 -0
  371. package/dist/native-assets/policy.js +155 -0
  372. package/dist/native-assets/policy.js.map +1 -0
  373. package/dist/pipeline/__tests__/orchestrator.test.js +162 -40
  374. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  375. package/dist/pipeline/__tests__/stages.test.js +66 -149
  376. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  377. package/dist/pipeline/orchestrator.d.ts.map +1 -1
  378. package/dist/pipeline/orchestrator.js +124 -18
  379. package/dist/pipeline/orchestrator.js.map +1 -1
  380. package/dist/pipeline/stages/ralplan.d.ts.map +1 -1
  381. package/dist/pipeline/stages/ralplan.js +36 -8
  382. package/dist/pipeline/stages/ralplan.js.map +1 -1
  383. package/dist/ralplan/__tests__/consensus-gate.test.js +70 -1437
  384. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  385. package/dist/ralplan/__tests__/documented-leader-preflight.test.js +328 -39
  386. package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -1
  387. package/dist/ralplan/__tests__/runtime.test.js +82 -102
  388. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  389. package/dist/ralplan/consensus-gate.d.ts +9 -1
  390. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  391. package/dist/ralplan/consensus-gate.js +40 -304
  392. package/dist/ralplan/consensus-gate.js.map +1 -1
  393. package/dist/ralplan/documented-leader-preflight.d.ts +15 -8
  394. package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -1
  395. package/dist/ralplan/documented-leader-preflight.js +356 -54
  396. package/dist/ralplan/documented-leader-preflight.js.map +1 -1
  397. package/dist/ralplan/runtime.d.ts +1 -1
  398. package/dist/ralplan/runtime.d.ts.map +1 -1
  399. package/dist/ralplan/runtime.js +68 -173
  400. package/dist/ralplan/runtime.js.map +1 -1
  401. package/dist/runtime/run-state.d.ts +5 -1
  402. package/dist/runtime/run-state.d.ts.map +1 -1
  403. package/dist/runtime/run-state.js +15 -8
  404. package/dist/runtime/run-state.js.map +1 -1
  405. package/dist/scripts/__tests__/codex-native-hook.test.js +14071 -8859
  406. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  407. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts +2 -0
  408. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.d.ts.map +1 -0
  409. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js +225 -0
  410. package/dist/scripts/__tests__/issue-3293-callsite-parity.test.js.map +1 -0
  411. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts +2 -0
  412. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.d.ts.map +1 -0
  413. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js +188 -0
  414. package/dist/scripts/__tests__/issue-3293-cancel-transaction.test.js.map +1 -0
  415. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts +2 -0
  416. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.d.ts.map +1 -0
  417. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js +259 -0
  418. package/dist/scripts/__tests__/issue-3293-hook-owned-cancel.test.js.map +1 -0
  419. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts +2 -0
  420. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.d.ts.map +1 -0
  421. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js +491 -0
  422. package/dist/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.js.map +1 -0
  423. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts +2 -0
  424. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.d.ts.map +1 -0
  425. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js +708 -0
  426. package/dist/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.js.map +1 -0
  427. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts +2 -0
  428. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.d.ts.map +1 -0
  429. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js +208 -0
  430. package/dist/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.js.map +1 -0
  431. package/dist/scripts/__tests__/notify-state-io.test.js +26 -0
  432. package/dist/scripts/__tests__/notify-state-io.test.js.map +1 -1
  433. package/dist/scripts/__tests__/notify-tmux-injection.test.js +23 -1
  434. package/dist/scripts/__tests__/notify-tmux-injection.test.js.map +1 -1
  435. package/dist/scripts/__tests__/postinstall.test.js +19 -1
  436. package/dist/scripts/__tests__/postinstall.test.js.map +1 -1
  437. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +25 -8
  438. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -1
  439. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +60 -25
  440. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -1
  441. package/dist/scripts/__tests__/smoke-packed-install.test.js +155 -16
  442. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  443. package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts +2 -0
  444. package/dist/scripts/__tests__/verify-native-release-assets.test.d.ts.map +1 -0
  445. package/dist/scripts/__tests__/verify-native-release-assets.test.js +235 -0
  446. package/dist/scripts/__tests__/verify-native-release-assets.test.js.map +1 -0
  447. package/dist/scripts/codex-native-hook.d.ts +50 -1
  448. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  449. package/dist/scripts/codex-native-hook.js +3559 -451
  450. package/dist/scripts/codex-native-hook.js.map +1 -1
  451. package/dist/scripts/codex-native-pre-post.d.ts +9 -0
  452. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  453. package/dist/scripts/codex-native-pre-post.js +35 -12
  454. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  455. package/dist/scripts/generate-native-release-manifest.js +80 -51
  456. package/dist/scripts/generate-native-release-manifest.js.map +1 -1
  457. package/dist/scripts/notify-fallback-watcher.js +28 -39
  458. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  459. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  460. package/dist/scripts/notify-hook/state-io.js +5 -0
  461. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  462. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  463. package/dist/scripts/notify-hook/team-leader-nudge.js +32 -3
  464. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  465. package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
  466. package/dist/scripts/notify-hook/team-worker-stop.js +23 -3
  467. package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
  468. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  469. package/dist/scripts/notify-hook/team-worker.js +45 -5
  470. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  471. package/dist/scripts/notify-hook/tmux-injection.d.ts +1 -0
  472. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  473. package/dist/scripts/notify-hook/tmux-injection.js +4 -1
  474. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  475. package/dist/scripts/notify-hook.js +78 -82
  476. package/dist/scripts/notify-hook.js.map +1 -1
  477. package/dist/scripts/postinstall-advisory.d.ts +14 -0
  478. package/dist/scripts/postinstall-advisory.d.ts.map +1 -0
  479. package/dist/scripts/postinstall-advisory.js +49 -0
  480. package/dist/scripts/postinstall-advisory.js.map +1 -0
  481. package/dist/scripts/postinstall.d.ts +1 -1
  482. package/dist/scripts/postinstall.d.ts.map +1 -1
  483. package/dist/scripts/postinstall.js +1 -1
  484. package/dist/scripts/postinstall.js.map +1 -1
  485. package/dist/scripts/smoke-packed-install.d.ts +32 -1
  486. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  487. package/dist/scripts/smoke-packed-install.js +413 -60
  488. package/dist/scripts/smoke-packed-install.js.map +1 -1
  489. package/dist/scripts/sync-plugin-mirror.d.ts.map +1 -1
  490. package/dist/scripts/sync-plugin-mirror.js +16 -1
  491. package/dist/scripts/sync-plugin-mirror.js.map +1 -1
  492. package/dist/scripts/verify-native-release-assets.js +37 -23
  493. package/dist/scripts/verify-native-release-assets.js.map +1 -1
  494. package/dist/state/__tests__/mode-state-context.test.js +12 -5
  495. package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
  496. package/dist/state/__tests__/operations.test.js +460 -850
  497. package/dist/state/__tests__/operations.test.js.map +1 -1
  498. package/dist/state/__tests__/skill-active.test.js +400 -2
  499. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  500. package/dist/state/mode-state-context.d.ts +3 -0
  501. package/dist/state/mode-state-context.d.ts.map +1 -1
  502. package/dist/state/mode-state-context.js +27 -13
  503. package/dist/state/mode-state-context.js.map +1 -1
  504. package/dist/state/operations.d.ts +3 -0
  505. package/dist/state/operations.d.ts.map +1 -1
  506. package/dist/state/operations.js +144 -40
  507. package/dist/state/operations.js.map +1 -1
  508. package/dist/state/skill-active.d.ts +18 -1
  509. package/dist/state/skill-active.d.ts.map +1 -1
  510. package/dist/state/skill-active.js +420 -23
  511. package/dist/state/skill-active.js.map +1 -1
  512. package/dist/state/workflow-transition-reconcile.d.ts +3 -0
  513. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  514. package/dist/state/workflow-transition-reconcile.js +10 -4
  515. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  516. package/dist/state/workflow-transition.d.ts.map +1 -1
  517. package/dist/state/workflow-transition.js +3 -1
  518. package/dist/state/workflow-transition.js.map +1 -1
  519. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +27 -0
  520. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -1
  521. package/dist/subagents/__tests__/tracker.test.js +837 -1048
  522. package/dist/subagents/__tests__/tracker.test.js.map +1 -1
  523. package/dist/subagents/tracker.d.ts +64 -60
  524. package/dist/subagents/tracker.d.ts.map +1 -1
  525. package/dist/subagents/tracker.js +809 -358
  526. package/dist/subagents/tracker.js.map +1 -1
  527. package/dist/team/__tests__/delivery-e2e-smoke.test.js +6 -7
  528. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  529. package/dist/team/__tests__/mcp-comm.test.js +104 -3
  530. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  531. package/dist/team/__tests__/notice-ledger.test.d.ts +2 -0
  532. package/dist/team/__tests__/notice-ledger.test.d.ts.map +1 -0
  533. package/dist/team/__tests__/notice-ledger.test.js +131 -0
  534. package/dist/team/__tests__/notice-ledger.test.js.map +1 -0
  535. package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts +2 -0
  536. package/dist/team/__tests__/pane-teardown-residue-e2e.test.d.ts.map +1 -0
  537. package/dist/team/__tests__/pane-teardown-residue-e2e.test.js +410 -0
  538. package/dist/team/__tests__/pane-teardown-residue-e2e.test.js.map +1 -0
  539. package/dist/team/__tests__/phase-controller.test.js +20 -0
  540. package/dist/team/__tests__/phase-controller.test.js.map +1 -1
  541. package/dist/team/__tests__/runtime.test.js +725 -59
  542. package/dist/team/__tests__/runtime.test.js.map +1 -1
  543. package/dist/team/__tests__/scaling.test.js +222 -237
  544. package/dist/team/__tests__/scaling.test.js.map +1 -1
  545. package/dist/team/__tests__/state-root.test.js +117 -2
  546. package/dist/team/__tests__/state-root.test.js.map +1 -1
  547. package/dist/team/__tests__/tmux-session.test.js +887 -92
  548. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  549. package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts +2 -0
  550. package/dist/team/__tests__/tmux-source-authority-realtmux.test.d.ts.map +1 -0
  551. package/dist/team/__tests__/tmux-source-authority-realtmux.test.js +149 -0
  552. package/dist/team/__tests__/tmux-source-authority-realtmux.test.js.map +1 -0
  553. package/dist/team/__tests__/tmux-test-fixture.d.ts +69 -0
  554. package/dist/team/__tests__/tmux-test-fixture.d.ts.map +1 -1
  555. package/dist/team/__tests__/tmux-test-fixture.js +242 -15
  556. package/dist/team/__tests__/tmux-test-fixture.js.map +1 -1
  557. package/dist/team/__tests__/tmux-test-fixture.test.js +177 -1
  558. package/dist/team/__tests__/tmux-test-fixture.test.js.map +1 -1
  559. package/dist/team/__tests__/worker-runtime-identity.test.js +45 -72
  560. package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
  561. package/dist/team/notice-ledger.d.ts +54 -0
  562. package/dist/team/notice-ledger.d.ts.map +1 -0
  563. package/dist/team/notice-ledger.js +259 -0
  564. package/dist/team/notice-ledger.js.map +1 -0
  565. package/dist/team/phase-controller.d.ts.map +1 -1
  566. package/dist/team/phase-controller.js +2 -0
  567. package/dist/team/phase-controller.js.map +1 -1
  568. package/dist/team/runtime.d.ts +3 -1
  569. package/dist/team/runtime.d.ts.map +1 -1
  570. package/dist/team/runtime.js +314 -142
  571. package/dist/team/runtime.js.map +1 -1
  572. package/dist/team/scaling.d.ts.map +1 -1
  573. package/dist/team/scaling.js +161 -91
  574. package/dist/team/scaling.js.map +1 -1
  575. package/dist/team/state/monitor.d.ts +10 -0
  576. package/dist/team/state/monitor.d.ts.map +1 -1
  577. package/dist/team/state/monitor.js +13 -0
  578. package/dist/team/state/monitor.js.map +1 -1
  579. package/dist/team/state/types.d.ts +15 -0
  580. package/dist/team/state/types.d.ts.map +1 -1
  581. package/dist/team/state/types.js.map +1 -1
  582. package/dist/team/state-root.d.ts +12 -0
  583. package/dist/team/state-root.d.ts.map +1 -1
  584. package/dist/team/state-root.js +177 -0
  585. package/dist/team/state-root.js.map +1 -1
  586. package/dist/team/state.d.ts +18 -0
  587. package/dist/team/state.d.ts.map +1 -1
  588. package/dist/team/state.js +36 -0
  589. package/dist/team/state.js.map +1 -1
  590. package/dist/team/tmux-session.d.ts +40 -4
  591. package/dist/team/tmux-session.d.ts.map +1 -1
  592. package/dist/team/tmux-session.js +513 -166
  593. package/dist/team/tmux-session.js.map +1 -1
  594. package/dist/ultragoal/__tests__/artifacts.test.js +950 -2
  595. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  596. package/dist/ultragoal/__tests__/docs-contract.test.js +1 -0
  597. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  598. package/dist/ultragoal/artifacts.d.ts +35 -1
  599. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  600. package/dist/ultragoal/artifacts.js +232 -46
  601. package/dist/ultragoal/artifacts.js.map +1 -1
  602. package/dist/utils/__tests__/file-durability.test.js +58 -1
  603. package/dist/utils/__tests__/file-durability.test.js.map +1 -1
  604. package/dist/utils/__tests__/paths.test.js +21 -1
  605. package/dist/utils/__tests__/paths.test.js.map +1 -1
  606. package/dist/utils/file-durability.d.ts +10 -0
  607. package/dist/utils/file-durability.d.ts.map +1 -1
  608. package/dist/utils/file-durability.js +34 -4
  609. package/dist/utils/file-durability.js.map +1 -1
  610. package/dist/utils/paths.d.ts.map +1 -1
  611. package/dist/utils/paths.js +14 -6
  612. package/dist/utils/paths.js.map +1 -1
  613. package/dist/verification/__tests__/ci-rust-gates.test.js +49 -4
  614. package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
  615. package/dist/verification/__tests__/explore-harness-release-workflow.test.js +60 -0
  616. package/dist/verification/__tests__/explore-harness-release-workflow.test.js.map +1 -1
  617. package/dist/verification/__tests__/native-release-manifest.test.js +157 -4
  618. package/dist/verification/__tests__/native-release-manifest.test.js.map +1 -1
  619. package/package.json +13 -5
  620. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  621. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +81 -17
  622. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +13 -5
  623. package/plugins/oh-my-codex/skills/cancel/SKILL.md +30 -85
  624. package/plugins/oh-my-codex/skills/ralph/SKILL.md +5 -5
  625. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +15 -17
  626. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +3 -2
  627. package/skills/autopilot/SKILL.md +13 -5
  628. package/skills/cancel/SKILL.md +30 -85
  629. package/skills/ralph/SKILL.md +5 -5
  630. package/skills/ralplan/SKILL.md +15 -17
  631. package/skills/ultragoal/SKILL.md +3 -2
  632. package/src/scripts/__tests__/codex-native-hook.test.ts +6091 -540
  633. package/src/scripts/__tests__/issue-3293-callsite-parity.test.ts +187 -0
  634. package/src/scripts/__tests__/issue-3293-cancel-transaction.test.ts +189 -0
  635. package/src/scripts/__tests__/issue-3293-hook-owned-cancel.test.ts +187 -0
  636. package/src/scripts/__tests__/issue-3311-ultragoal-native-outside-tmux.test.ts +591 -0
  637. package/src/scripts/__tests__/issue-3358-ultragoal-cancel-lifecycle.test.ts +701 -0
  638. package/src/scripts/__tests__/issue-3369-autopilot-ralplan-state-machine.test.ts +211 -0
  639. package/src/scripts/__tests__/notify-state-io.test.ts +29 -0
  640. package/src/scripts/__tests__/notify-tmux-injection.test.ts +26 -1
  641. package/src/scripts/__tests__/postinstall.test.ts +23 -1
  642. package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +27 -8
  643. package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +61 -27
  644. package/src/scripts/__tests__/smoke-packed-install.test.ts +209 -18
  645. package/src/scripts/__tests__/verify-native-release-assets.test.ts +240 -0
  646. package/src/scripts/codex-native-hook.ts +3638 -475
  647. package/src/scripts/codex-native-pre-post.ts +43 -12
  648. package/src/scripts/generate-native-release-manifest.ts +83 -79
  649. package/src/scripts/notify-fallback-watcher.ts +38 -38
  650. package/src/scripts/notify-hook/state-io.ts +11 -0
  651. package/src/scripts/notify-hook/team-leader-nudge.ts +32 -4
  652. package/src/scripts/notify-hook/team-worker-stop.ts +23 -4
  653. package/src/scripts/notify-hook/team-worker.ts +43 -5
  654. package/src/scripts/notify-hook/tmux-injection.ts +5 -1
  655. package/src/scripts/notify-hook.ts +83 -82
  656. package/src/scripts/postinstall-advisory.ts +67 -0
  657. package/src/scripts/postinstall.ts +1 -1
  658. package/src/scripts/smoke-packed-install.ts +446 -59
  659. package/src/scripts/sync-plugin-mirror.ts +17 -1
  660. package/src/scripts/verify-native-release-assets.ts +39 -31
  661. package/templates/AGENTS.md +1 -0
@@ -2,6 +2,7 @@ import { spawnSync, execFile } from 'child_process';
2
2
  import { promisify } from 'util';
3
3
  import { closeSync, chmodSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from 'fs';
4
4
  import { homedir } from 'os';
5
+ import { randomBytes } from 'crypto';
5
6
  import { dirname, isAbsolute, join, relative, resolve, sep } from 'path';
6
7
  import { CODEX_BYPASS_FLAG, CLAUDE_SKIP_PERMISSIONS_FLAG, MADMAX_FLAG, CONFIG_FLAG, LONG_CONFIG_FLAG, MODEL_FLAG, } from '../cli/constants.js';
7
8
  import { getAgent } from '../agents/definitions.js';
@@ -55,6 +56,16 @@ class ExactPaneProofUnavailableError extends Error {
55
56
  this.name = 'ExactPaneProofUnavailableError';
56
57
  }
57
58
  }
59
+ class AmbiguousSplitWindowOutputError extends Error {
60
+ newlyObservedPaneIds;
61
+ reconciliationError;
62
+ constructor(newlyObservedPaneIds, reconciliationError = null) {
63
+ super('tmux_split_window_output_ambiguous');
64
+ this.newlyObservedPaneIds = newlyObservedPaneIds;
65
+ this.reconciliationError = reconciliationError;
66
+ this.name = 'AmbiguousSplitWindowOutputError';
67
+ }
68
+ }
58
69
  const INJECTION_MARKER = '[OMX_TMUX_INJECT]';
59
70
  const MODEL_INSTRUCTIONS_FILE_KEY = 'model_instructions_file';
60
71
  const OMX_BYPASS_DEFAULT_SYSTEM_PROMPT_ENV = 'OMX_BYPASS_DEFAULT_SYSTEM_PROMPT';
@@ -101,7 +112,7 @@ const TMUX_PANE_STABILITY_POLL_MS = 60;
101
112
  const TMUX_PANE_STABILITY_POLLS_REQUIRED = 2;
102
113
  const TMUX_PANE_STABILITY_TIMEOUT_MS = 750;
103
114
  const OMX_TEAM_STATE_ROOT_ENV = 'OMX_TEAM_STATE_ROOT';
104
- function runTmux(args) {
115
+ function runTmux(args, preserveStdout = false) {
105
116
  const { result } = spawnPlatformCommandSync('tmux', args, { encoding: 'utf-8' });
106
117
  if (result.error) {
107
118
  return { ok: false, stderr: result.error.message };
@@ -109,7 +120,16 @@ function runTmux(args) {
109
120
  if (result.status !== 0) {
110
121
  return { ok: false, stderr: (result.stderr || '').trim() || `tmux exited ${result.status}` };
111
122
  }
112
- return { ok: true, stdout: (result.stdout || '').trim() };
123
+ const stdout = result.stdout || '';
124
+ return { ok: true, stdout: preserveStdout ? stdout : stdout.trim() };
125
+ }
126
+ export function parseSplitWindowPaneId(stdout, expectedReceipt) {
127
+ const match = expectedReceipt === undefined
128
+ ? /^(%\d+)(?:\r?\n)?$/.exec(stdout)
129
+ : /^(%\d+)\t([^\r\n\t]+)(?:\r?\n)?$/.exec(stdout);
130
+ if (!match || (expectedReceipt !== undefined && match[2] !== expectedReceipt))
131
+ return null;
132
+ return match[1];
113
133
  }
114
134
  /** Preserve structured tmux fields, including an empty final field. */
115
135
  /** Preserve structured tmux fields, including an empty final field. */
@@ -122,6 +142,115 @@ function runTmuxStructured(args) {
122
142
  }
123
143
  return { ok: true, stdout: (result.stdout || '').replace(/\r?\n$/, '') };
124
144
  }
145
+ function captureSourcePaneAuthority(paneId, expectedTeamPaneOwnerId) {
146
+ const target = paneId.trim();
147
+ if (!/^%[0-9]+$/.test(target))
148
+ throw new Error(`invalid tmux source pane: ${paneId}`);
149
+ const result = runTmuxStructured([
150
+ 'display-message', '-p', '-t', target,
151
+ '#{session_name}\t#{session_id}\t#{session_created}\t#{window_index}\t#{window_id}\t#{pane_id}\t#{pane_pid}',
152
+ ]);
153
+ if (!result.ok)
154
+ throw new Error(`failed to capture tmux source authority: ${result.stderr}`);
155
+ const fields = result.stdout.split('\t');
156
+ if (fields.length !== 7)
157
+ throw new Error('malformed tmux source authority');
158
+ const [sessionName, sessionId, sessionCreated, windowIndex, windowId, capturedPaneId, panePid] = fields;
159
+ if (!sessionName || !/^\$[0-9]+$/.test(sessionId) || !/^[0-9]+$/.test(sessionCreated)
160
+ || !/^[0-9]+$/.test(windowIndex) || !/^@[0-9]+$/.test(windowId)
161
+ || capturedPaneId !== target || !/^[1-9][0-9]*$/.test(panePid)) {
162
+ throw new Error('malformed tmux source authority');
163
+ }
164
+ const parsedPid = Number(panePid);
165
+ if (!Number.isSafeInteger(parsedPid) || parsedPid <= 0)
166
+ throw new Error('malformed tmux source authority');
167
+ const proof = readExactPaneProofSync(target);
168
+ if (proof.status === 'unavailable')
169
+ throw new ExactPaneProofUnavailableError(proof);
170
+ if (proof.status !== 'live' || proof.pid !== parsedPid)
171
+ throw new Error(`tmux pane identity changed: ${target}`);
172
+ const ownerResult = runTmuxStructured(['show-option', '-qv', '-p', '-t', target, OMX_TEAM_PANE_OWNER_OPTION]);
173
+ if (!ownerResult.ok)
174
+ throw new Error(`failed to capture tmux pane owner: ${ownerResult.stderr}`);
175
+ const teamPaneOwnerId = ownerResult.stdout.trim() || null;
176
+ if (teamPaneOwnerId && !/^[A-Za-z0-9._:-]+$/.test(teamPaneOwnerId)) {
177
+ throw new Error('malformed tmux pane owner');
178
+ }
179
+ if (expectedTeamPaneOwnerId !== undefined && teamPaneOwnerId !== expectedTeamPaneOwnerId) {
180
+ throw new Error(`tmux pane team owner changed: ${target}`);
181
+ }
182
+ return {
183
+ paneId: target,
184
+ panePid: parsedPid,
185
+ sessionName,
186
+ sessionId,
187
+ sessionCreated,
188
+ windowId,
189
+ windowIndex,
190
+ teamPaneOwnerId,
191
+ };
192
+ }
193
+ function sourceAuthorityPredicate(source) {
194
+ return [
195
+ '#{==:#{pane_dead},0}',
196
+ `#{==:#{pane_id},${source.paneId}}`,
197
+ `#{==:#{pane_pid},${source.panePid}}`,
198
+ `#{==:#{session_id},${source.sessionId}}`,
199
+ `#{==:#{session_created},${source.sessionCreated}}`,
200
+ `#{==:#{window_id},${source.windowId}}`,
201
+ ...(source.teamPaneOwnerId ? [`#{==:#{${OMX_TEAM_PANE_OWNER_OPTION}},${source.teamPaneOwnerId}}`] : []),
202
+ ].reduce((combined, condition) => `#{&&:${combined},${condition}}`);
203
+ }
204
+ function sourceTransactionReceipt() {
205
+ return `omx_source_${process.pid}_${Date.now()}_${randomBytes(16).toString('hex')}`;
206
+ }
207
+ function bindSplitReceiptToPaneCommand(command, receipt) {
208
+ return `${command} # ${receipt}`;
209
+ }
210
+ /** Queue an effect in the source pane's tmux server only when its exact pane/session/window incarnation still matches. */
211
+ export function runSourceAuthorizedTmux(source, effect, receipt = sourceTransactionReceipt()) {
212
+ const result = runTmux([
213
+ 'if-shell', '-F', '-t', source.paneId, sourceAuthorityPredicate(source),
214
+ `${effect} ; display-message -p ${shellQuoteSingle(receipt)}`,
215
+ "display-message -p ''",
216
+ ]);
217
+ if (!result.ok)
218
+ throw new Error(`tmux source authority transaction failed: ${result.stderr}`);
219
+ if (result.stdout !== receipt)
220
+ throw new Error('tmux source authority changed before effect');
221
+ return receipt;
222
+ }
223
+ function runSourceAuthorizedSplit(source, buildEffect) {
224
+ // Reconcile against the immutable window ID, not the mutable session:index
225
+ // target: a concurrent renumber between the guarded split and the after-read
226
+ // must never turn an unrelated window's pane into kill authority.
227
+ const windowTarget = source.windowId;
228
+ const beforeTopology = listPanesResult(windowTarget);
229
+ if (beforeTopology.error) {
230
+ throw new Error(`failed to read tmux pane topology before split: ${beforeTopology.error}`);
231
+ }
232
+ const beforePaneIds = new Set(beforeTopology.panes.map((pane) => pane.paneId));
233
+ const receipt = sourceTransactionReceipt();
234
+ const effect = buildEffect(receipt);
235
+ const result = runTmux([
236
+ 'if-shell', '-F', '-t', source.paneId, sourceAuthorityPredicate(source),
237
+ effect.replace("-F '#{pane_id}'", `-F '#{pane_id}\\t${receipt}'`),
238
+ "display-message -p ''",
239
+ ], true);
240
+ if (!result.ok)
241
+ throw new Error(`tmux source authority transaction failed: ${result.stderr}`);
242
+ const paneId = parseSplitWindowPaneId(result.stdout, receipt);
243
+ if (!paneId) {
244
+ const afterTopology = listPanesResult(windowTarget);
245
+ const newlyObservedPaneIds = afterTopology.error
246
+ ? []
247
+ : afterTopology.panes
248
+ .filter((pane) => !beforePaneIds.has(pane.paneId) && pane.startCommand.includes(receipt))
249
+ .map((pane) => pane.paneId);
250
+ throw new AmbiguousSplitWindowOutputError(newlyObservedPaneIds, afterTopology.error);
251
+ }
252
+ return paneId;
253
+ }
125
254
  function restoredHudCleanupDebtPath(cwd, stateRoot) {
126
255
  const canonicalStateRoot = resolveCanonicalTeamStateRoot(resolve(cwd));
127
256
  if (typeof stateRoot !== 'string' || !stateRoot.trim()) {
@@ -338,17 +467,6 @@ function sanitizeTmuxStyleOption(sessionTarget, optionName, beforeEffect) {
338
467
  const result = runTmux(['set-option', '-t', sessionTarget, optionName, sanitized]);
339
468
  return result.ok;
340
469
  }
341
- function tagPaneInstance(paneTarget, instanceId, expectedPanePid) {
342
- const target = paneTarget.trim();
343
- const sanitized = instanceId.trim();
344
- if (!target || !sanitized)
345
- return;
346
- const provenTarget = requireLiveExactPaneSync(target, expectedPanePid);
347
- const result = runTmux(['set-option', '-p', '-t', provenTarget, OMX_PANE_INSTANCE_OPTION, sanitized]);
348
- if (!result.ok) {
349
- throw new Error(`failed to tag tmux pane ${provenTarget}: ${result.stderr}`);
350
- }
351
- }
352
470
  export function tagPaneTeamOwner(paneTarget, teamOwnerId, expectedPanePid) {
353
471
  const target = paneTarget.trim();
354
472
  const sanitized = teamOwnerId.trim();
@@ -471,6 +589,13 @@ function requireLiveTeamOwnedPaneSync(paneId, expectedPanePid, expectedTeamOwner
471
589
  }
472
590
  return requireLiveExactPaneSync(target, expectedPanePid);
473
591
  }
592
+ function frozenWindowTopologyError(teamTarget, expectedPaneIds, actualPaneIds) {
593
+ const expected = [...expectedPaneIds].sort();
594
+ const actual = [...actualPaneIds].sort();
595
+ const unexpected = actual.filter((paneId) => !expectedPaneIds.has(paneId));
596
+ const missing = expected.filter((paneId) => !actualPaneIds.has(paneId));
597
+ return new Error(`tmux window topology changed before layout mutation: target=${teamTarget}; expected=[${expected.join(',')}]; actual=[${actual.join(',')}]; unexpected=[${unexpected.join(',')}]; missing=[${missing.join(',')}]. Team requires an isolated tmux window with no host-owned foreign panes`);
598
+ }
474
599
  function requireFrozenWindowTopologySync(teamTarget, expectedPanePids, expectedPaneOwners) {
475
600
  const topology = listPanesResult(teamTarget);
476
601
  if (topology.error)
@@ -478,7 +603,7 @@ function requireFrozenWindowTopologySync(teamTarget, expectedPanePids, expectedP
478
603
  const actualPaneIds = new Set(topology.panes.map((pane) => pane.paneId));
479
604
  if (actualPaneIds.size !== expectedPanePids.size
480
605
  || [...expectedPanePids.keys()].some((paneId) => !actualPaneIds.has(paneId))) {
481
- throw new Error('tmux window topology changed before layout mutation');
606
+ throw frozenWindowTopologyError(teamTarget, new Set(expectedPanePids.keys()), actualPaneIds);
482
607
  }
483
608
  for (const [paneId, expectedPanePid] of expectedPanePids) {
484
609
  const expectedOwner = expectedPaneOwners?.get(paneId);
@@ -511,7 +636,7 @@ function requireFrozenWindowTopologySync(teamTarget, expectedPanePids, expectedP
511
636
  const finalPaneIds = new Set(finalTopology.panes.map((pane) => pane.paneId));
512
637
  if (finalPaneIds.size !== expectedPanePids.size
513
638
  || [...expectedPanePids.keys()].some((paneId) => !finalPaneIds.has(paneId))) {
514
- throw new Error('tmux window topology changed before layout mutation');
639
+ throw frozenWindowTopologyError(teamTarget, new Set(expectedPanePids.keys()), finalPaneIds);
515
640
  }
516
641
  }
517
642
  export function listPaneIds(target) {
@@ -636,6 +761,59 @@ async function runTmuxAsync(args) {
636
761
  function hasExplicitWorkerPaneId(workerPaneId) {
637
762
  return typeof workerPaneId === 'string' && workerPaneId.trim().length > 0;
638
763
  }
764
+ function readExactWorkerPaneLivenessProofSync(paneId) {
765
+ if (!/^%[0-9]+$/.test(paneId))
766
+ return { status: 'unavailable', paneId, reason: 'invalid_pane_id' };
767
+ const result = runTmuxStructured([
768
+ 'display-message', '-p', '-t', paneId,
769
+ `#{pane_id}\t#{pane_dead}\t#{pane_pid}\t#{${OMX_TEAM_PANE_OWNER_OPTION}}`,
770
+ ]);
771
+ if (!result.ok) {
772
+ if (/can't find pane|no such pane|unknown pane/i.test(result.stderr)) {
773
+ return { status: 'gone', paneId, reason: 'absent' };
774
+ }
775
+ return { status: 'unavailable', paneId, reason: `query_failed:${result.stderr || 'unknown'}` };
776
+ }
777
+ const lines = result.stdout.replace(/\r\n/g, '\n').split('\n').filter((line) => line.length > 0);
778
+ if (lines.length !== 1)
779
+ return { status: 'unavailable', paneId, reason: 'malformed_exact_pane_result' };
780
+ const fields = lines[0].split('\t');
781
+ if (fields.length !== 4)
782
+ return { status: 'unavailable', paneId, reason: 'malformed_exact_pane_result' };
783
+ const [actualPaneId, paneDead, rawPid, ownerId] = fields;
784
+ if (actualPaneId !== paneId) {
785
+ return { status: 'unavailable', paneId, reason: `pane_id_changed:expected=${paneId}:actual=${actualPaneId}` };
786
+ }
787
+ if (paneDead !== '0' && paneDead !== '1')
788
+ return { status: 'unavailable', paneId, reason: 'malformed_exact_pane_result' };
789
+ if (!/^[0-9]+$/.test(rawPid))
790
+ return { status: 'unavailable', paneId, reason: 'malformed_exact_pane_result' };
791
+ const pid = Number(rawPid);
792
+ if (!Number.isSafeInteger(pid) || pid <= 0)
793
+ return { status: 'unavailable', paneId, reason: 'malformed_exact_pane_result' };
794
+ if (paneDead === '1')
795
+ return { status: 'gone', paneId, reason: 'dead' };
796
+ return { status: 'live', paneId, pid, ownerId };
797
+ }
798
+ function requireExactWorkerPaneLivenessIdentity(paneId, expectedPanePid, expectedTeamOwnerId, hudPaneId) {
799
+ if (hudPaneId?.trim() && paneId === hudPaneId.trim()) {
800
+ throw new Error(`tmux worker pane is HUD target: ${paneId}`);
801
+ }
802
+ const proof = readExactWorkerPaneLivenessProofSync(paneId);
803
+ if (proof.status === 'unavailable' && proof.reason.startsWith('pane_id_changed:')) {
804
+ throw new Error(`tmux worker pane identity changed: ${paneId}: ${proof.reason}`);
805
+ }
806
+ if (proof.status !== 'live')
807
+ return proof;
808
+ if (typeof expectedPanePid === 'number' && proof.pid !== expectedPanePid) {
809
+ throw new Error(`tmux worker pane PID changed: ${paneId}: expected ${expectedPanePid}, got ${proof.pid}`);
810
+ }
811
+ const expectedOwner = typeof expectedTeamOwnerId === 'string' ? expectedTeamOwnerId.trim() : '';
812
+ if (expectedOwner && proof.ownerId !== expectedOwner) {
813
+ throw new Error(`tmux worker pane incarnation changed: ${paneId}: expected ${expectedOwner}, got ${proof.ownerId || 'missing'}`);
814
+ }
815
+ return proof;
816
+ }
639
817
  function resolveWorkerPaneTargetSync(sessionName, workerIndex, workerPaneId) {
640
818
  if (!hasExplicitWorkerPaneId(workerPaneId))
641
819
  return paneTarget(sessionName, workerIndex);
@@ -883,7 +1061,7 @@ function buildBestEffortShellCommand(command) {
883
1061
  }
884
1062
  function buildAuthoritativeHudResizeShellCommand(hudPaneId, heightLines = HUD_TMUX_TEAM_HEIGHT_LINES, expectedPanePid, expectedPaneOwnerId, effectCommand = buildNestedTmuxShellCommand(buildHudResizeCommand(buildHudPaneTarget(hudPaneId), heightLines))) {
885
1063
  const target = buildHudPaneTarget(hudPaneId);
886
- const snapshot = buildNestedTmuxShellCommand("list-panes -a -F '#{pane_id}\\t#{pane_dead}\\t#{pane_pid}'");
1064
+ const snapshot = buildNestedTmuxShellCommand("list-panes -a -F '#{pane_id}\t#{pane_dead}\t#{pane_pid}'");
887
1065
  const expectedPid = typeof expectedPanePid === 'number' && Number.isSafeInteger(expectedPanePid) && expectedPanePid > 0
888
1066
  ? ` && $3 == "${expectedPanePid}"`
889
1067
  : '';
@@ -949,12 +1127,11 @@ export function buildScheduleDelayedHudResizeArgs(hudPaneId, delaySeconds = HUD_
949
1127
  export function buildReconcileHudResizeArgs(hudPaneId, heightLines = HUD_TMUX_TEAM_HEIGHT_LINES, expectedPanePid, expectedPaneOwnerId) {
950
1128
  return ['run-shell', buildBestEffortShellCommand(buildAuthoritativeHudResizeShellCommand(hudPaneId, heightLines, expectedPanePid, expectedPaneOwnerId))];
951
1129
  }
952
- function redrawLeaderPaneAfterTeamLayout(leaderPaneId, expectedPanePid, expectedTeamOwnerId) {
953
- const target = leaderPaneId.trim();
954
- if (!target.startsWith('%'))
955
- return;
956
- const provenTarget = requireLiveTeamOwnedPaneSync(target, expectedPanePid, expectedTeamOwnerId);
957
- runTmux(['send-keys', '-t', provenTarget, 'C-l']);
1130
+ function redrawLeaderPaneAfterTeamLayout(source, expectedTeamOwnerId) {
1131
+ const provenTarget = requireLiveTeamOwnedPaneSync(source.paneId, source.panePid, expectedTeamOwnerId);
1132
+ if (provenTarget !== source.paneId)
1133
+ throw new Error(`tmux pane identity changed: ${source.paneId}`);
1134
+ runSourceAuthorizedTmux(source, `send-keys -t ${source.paneId} C-l`);
958
1135
  }
959
1136
  const ZSH_CANDIDATE_PATHS = ['/bin/zsh', '/usr/bin/zsh', '/usr/local/bin/zsh', '/opt/local/bin/zsh', '/opt/homebrew/bin/zsh'];
960
1137
  const BASH_CANDIDATE_PATHS = ['/bin/bash', '/usr/bin/bash'];
@@ -1311,6 +1488,23 @@ function appendTeamWorkerMcpDisableOverrides(args, env) {
1311
1488
  args.splice(endOfOptionsIndex < 0 ? args.length : endOfOptionsIndex, 0, CONFIG_FLAG, `${key}=false`);
1312
1489
  }
1313
1490
  }
1491
+ const CODEX_BYPASS_MDM_INCOMPATIBLE_REASON = 'codex_bypass_mdm_incompatible';
1492
+ const CODEX_BYPASS_MDM_REJECTED_MARKER = 'MDM_POLICY_REJECTED: approval_policy=never forbids --dangerously-bypass-approvals-and-sandbox';
1493
+ export function classifyCodexBypassMdmIncompatibility(captured, workerCli, finalArgs) {
1494
+ if (workerCli !== 'codex' || !finalArgs || !parseTeamWorkerLaunchArgs([...finalArgs], 'final tmux worker arguments', { directPolicyMode: 'ignore' }).wantsBypass)
1495
+ return null;
1496
+ const normalizedLines = captured.replace(/\r\n?/g, '\n').split('\n');
1497
+ return normalizedLines.includes(CODEX_BYPASS_MDM_REJECTED_MARKER)
1498
+ ? CODEX_BYPASS_MDM_INCOMPATIBLE_REASON
1499
+ : null;
1500
+ }
1501
+ function buildAttachedTmuxWorkerStartupPlan(teamName, workerIndex, launchArgs, cwd, extraEnv, workerCliOverride, initialPrompt, workerRole) {
1502
+ const processSpec = buildWorkerStartupProcessLaunchSpec(teamName, workerIndex, launchArgs, cwd, extraEnv, workerCliOverride, initialPrompt, workerRole);
1503
+ const startupArgs = [...processSpec.args];
1504
+ if (processSpec.workerCli === 'codex')
1505
+ appendTeamWorkerMcpDisableOverrides(startupArgs, { ...process.env, ...extraEnv });
1506
+ return Object.freeze({ processSpec, startupArgs: Object.freeze(startupArgs) });
1507
+ }
1314
1508
  function insertArgsBeforeEndOfOptions(args, insertedArgs) {
1315
1509
  const endOfOptionsIndex = args.indexOf('--');
1316
1510
  if (endOfOptionsIndex < 0)
@@ -1434,24 +1628,17 @@ function buildWorkerStartupScriptContent(processSpec, startupEnv, startupArgs, c
1434
1628
  '',
1435
1629
  ].filter((line) => line !== '').join('\n');
1436
1630
  }
1437
- export function writeWorkerStartupScriptCommand(teamName, workerIndex, launchArgs = [], cwd = process.cwd(), extraEnv = {}, workerCliOverride, initialPrompt, workerRole) {
1631
+ export function writeWorkerStartupScriptCommand(teamName, workerIndex, launchArgs = [], cwd = process.cwd(), extraEnv = {}, workerCliOverride, initialPrompt, workerRole, attachedPlan) {
1438
1632
  if (process.platform === 'win32' && !isMsysOrGitBash())
1439
1633
  return null;
1440
1634
  const stateRoot = extraEnv[OMX_TEAM_STATE_ROOT_ENV]?.trim();
1441
1635
  if (!stateRoot)
1442
1636
  return null;
1443
- const processSpec = buildWorkerStartupProcessLaunchSpec(teamName, workerIndex, launchArgs, cwd, extraEnv, workerCliOverride, initialPrompt, workerRole);
1444
- const startupEnv = {
1445
- ...readTmuxWorkerAmbientEnv(process.env),
1446
- ...processSpec.env,
1447
- };
1448
- const startupArgs = [...processSpec.args];
1449
- if (processSpec.workerCli === 'codex') {
1450
- appendTeamWorkerMcpDisableOverrides(startupArgs, { ...process.env, ...extraEnv });
1451
- }
1637
+ const startupPlan = attachedPlan ?? buildAttachedTmuxWorkerStartupPlan(teamName, workerIndex, launchArgs, cwd, extraEnv, workerCliOverride, initialPrompt, workerRole);
1638
+ const startupEnv = { ...readTmuxWorkerAmbientEnv(process.env), ...startupPlan.processSpec.env };
1452
1639
  const scriptPath = join(stateRoot, 'team', teamName, 'runtime', `worker-${workerIndex}-startup.sh`);
1453
1640
  mkdirSync(dirname(scriptPath), { recursive: true });
1454
- writeFileSync(scriptPath, buildWorkerStartupScriptContent(processSpec, startupEnv, startupArgs, cwd, extraEnv), 'utf-8');
1641
+ writeFileSync(scriptPath, buildWorkerStartupScriptContent(startupPlan.processSpec, startupEnv, [...startupPlan.startupArgs], cwd, extraEnv), 'utf-8');
1455
1642
  chmodSync(scriptPath, 0o700);
1456
1643
  return `exec /bin/sh ${shellQuoteSingle(translatePathForMsys(scriptPath))}`;
1457
1644
  }
@@ -1616,6 +1803,7 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1616
1803
  const partialWorkerPaneIds = [];
1617
1804
  const partialWorkerPaneIdsByIndex = Array.from({ length: workerCount }, () => null);
1618
1805
  const partialWorkerPanePidsByIndex = Array.from({ length: workerCount }, () => null);
1806
+ const partialStartupCleanupPanePids = new Map();
1619
1807
  let partialHudPaneId = null;
1620
1808
  let partialHudPanePid = null;
1621
1809
  try {
@@ -1647,7 +1835,11 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1647
1835
  throw new ExactPaneProofUnavailableError(leaderProof);
1648
1836
  if (leaderProof.status === 'gone')
1649
1837
  throw new Error(`tmux pane is not proven live: ${leaderPaneId}`);
1650
- const leaderPanePid = leaderProof.pid;
1838
+ let leaderSource = captureSourcePaneAuthority(leaderPaneId);
1839
+ if (leaderSource.sessionName !== sessionName || leaderSource.windowIndex !== windowIndex || leaderSource.panePid !== leaderProof.pid) {
1840
+ throw new Error('tmux source authority changed during team startup');
1841
+ }
1842
+ const leaderPanePid = leaderSource.panePid;
1651
1843
  partialLeaderPaneId = leaderPaneId;
1652
1844
  partialLeaderPanePid = leaderPanePid;
1653
1845
  const initialHudPaneIds = findHudWatchPaneIds(paneListResult.panes, leaderPaneId, { leaderPaneId });
@@ -1669,13 +1861,36 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1669
1861
  // instead of making it disappear on team startup failures or broken installs.
1670
1862
  requireFrozenWindowTopologySync(teamTarget, initialWindowPanePids);
1671
1863
  if (ownerSessionId) {
1672
- const tagResult = runTmux(['set-option', '-t', sessionName, OMX_INSTANCE_OPTION, ownerSessionId]);
1673
- if (!tagResult.ok) {
1674
- throw new Error(`failed to tag tmux session ${sessionName}: ${tagResult.stderr}`);
1675
- }
1864
+ runSourceAuthorizedTmux(leaderSource, `set-option -t ${leaderSource.sessionId} ${OMX_INSTANCE_OPTION} ${shellQuoteSingle(ownerSessionId)}`);
1676
1865
  }
1677
- tagPaneInstance(leaderPaneId, ownerSessionId, leaderPanePid);
1678
- tagPaneTeamOwner(leaderPaneId, teamPaneOwnerId, leaderPanePid);
1866
+ if (ownerSessionId) {
1867
+ runSourceAuthorizedTmux(leaderSource, `set-option -p -t ${leaderPaneId} ${OMX_PANE_INSTANCE_OPTION} ${shellQuoteSingle(ownerSessionId)}`);
1868
+ }
1869
+ runSourceAuthorizedTmux(leaderSource, `set-option -p -t ${leaderPaneId} ${OMX_TEAM_PANE_OWNER_OPTION} ${shellQuoteSingle(teamPaneOwnerId)}`);
1870
+ // All subsequent Team mutations must bind the frozen leader owner in the
1871
+ // same tmux-server transaction as their effect. The initial tag itself is
1872
+ // deliberately the sole bootstrap mutation before an owner exists.
1873
+ leaderSource = captureSourcePaneAuthority(leaderPaneId, teamPaneOwnerId);
1874
+ const exactProveAndTagReconciledPane = (paneId) => {
1875
+ const proof = readExactPaneProofSync(paneId);
1876
+ if (proof.status === 'unavailable')
1877
+ throw new ExactPaneProofUnavailableError(proof);
1878
+ if (proof.status === 'gone')
1879
+ return null;
1880
+ const paneSource = captureSourcePaneAuthority(paneId);
1881
+ if (paneSource.panePid !== proof.pid)
1882
+ throw new Error(`tmux pane identity changed: ${paneId}`);
1883
+ if (paneSource.teamPaneOwnerId && paneSource.teamPaneOwnerId !== teamPaneOwnerId) {
1884
+ throw new Error(`tmux pane team owner changed: ${paneId}`);
1885
+ }
1886
+ if (ownerSessionId) {
1887
+ runSourceAuthorizedTmux(paneSource, `set-option -p -t ${paneId} ${OMX_PANE_INSTANCE_OPTION} ${shellQuoteSingle(ownerSessionId)}`);
1888
+ }
1889
+ rollbackTaggedPaneOwnerIds.set(paneId, teamPaneOwnerId);
1890
+ runSourceAuthorizedTmux(paneSource, `set-option -p -t ${paneId} ${OMX_TEAM_PANE_OWNER_OPTION} ${shellQuoteSingle(teamPaneOwnerId)}`);
1891
+ rollbackPanes.set(paneId, proof.pid);
1892
+ return proof.pid;
1893
+ };
1679
1894
  if (canRecreateTeamHud) {
1680
1895
  for (const [hudPaneId, hudPanePid] of initialWindowPanePids) {
1681
1896
  if (hudPaneId !== leaderPaneId)
@@ -1683,6 +1898,7 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1683
1898
  }
1684
1899
  }
1685
1900
  const workerPaneIds = [];
1901
+ const workerStartupArgs = Array.from({ length: workerCount }, () => Object.freeze([]));
1686
1902
  const workerPanePidsByIndex = Array.from({ length: workerCount }, () => null);
1687
1903
  let rightStackRootPaneId = null;
1688
1904
  let rightStackRootPanePid = null;
@@ -1694,30 +1910,49 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1694
1910
  const tmuxWorkerCwd = translatePathForMsys(workerCwd);
1695
1911
  const workerEnv = startup.env || {};
1696
1912
  const launchArgsForWorker = [...(workerLaunchPolicyPlan[i - 1] ?? workerLaunchArgs)];
1913
+ const attachedStartupPlan = buildAttachedTmuxWorkerStartupPlan(safeTeamName, i, launchArgsForWorker, workerCwd, workerEnv, workerCliPlan[i - 1], startup.initialPrompt, startup.workerRole);
1914
+ workerStartupArgs[i - 1] = attachedStartupPlan.startupArgs;
1697
1915
  trustWorkerMiseConfigIfAvailable(workerCwd);
1698
- const cmd = writeWorkerStartupScriptCommand(safeTeamName, i, launchArgsForWorker, workerCwd, workerEnv, workerCliPlan[i - 1], startup.initialPrompt, startup.workerRole) ?? buildWorkerStartupCommand(safeTeamName, i, launchArgsForWorker, workerCwd, workerEnv, workerCliPlan[i - 1], startup.initialPrompt, startup.workerRole);
1916
+ const cmd = writeWorkerStartupScriptCommand(safeTeamName, i, launchArgsForWorker, workerCwd, workerEnv, workerCliPlan[i - 1], startup.initialPrompt, startup.workerRole, attachedStartupPlan) ?? buildWorkerStartupCommand(safeTeamName, i, launchArgsForWorker, workerCwd, workerEnv, workerCliPlan[i - 1], startup.initialPrompt, startup.workerRole);
1699
1917
  // First split creates the right side from leader. Remaining splits stack on the right.
1700
1918
  const splitDirection = i === 1 ? '-h' : '-v';
1701
1919
  const splitTarget = requireLiveTeamOwnedPaneSync(i === 1 ? leaderPaneId : (rightStackRootPaneId ?? leaderPaneId), i === 1 ? leaderPanePid : (rightStackRootPanePid ?? leaderPanePid), teamPaneOwnerId);
1702
- const split = runTmux([
1703
- 'split-window',
1704
- splitDirection,
1705
- '-t',
1706
- splitTarget,
1707
- '-d',
1708
- '-P',
1709
- '-F',
1710
- '#{pane_id}',
1711
- '-c',
1712
- tmuxWorkerCwd,
1713
- cmd,
1714
- ]);
1715
- if (!split.ok) {
1716
- throw new Error(`failed to create worker pane ${i}: ${split.stderr}`);
1920
+ const splitSource = captureSourcePaneAuthority(splitTarget, teamPaneOwnerId);
1921
+ let paneId;
1922
+ try {
1923
+ paneId = runSourceAuthorizedSplit(splitSource, (receipt) => `split-window ${splitDirection} -t ${splitTarget} -d -P -F '#{pane_id}' -c ${shellQuoteSingle(tmuxWorkerCwd)} ${shellQuoteSingle(bindSplitReceiptToPaneCommand(cmd, receipt))}`);
1717
1924
  }
1718
- const paneId = split.stdout.split('\n')[0]?.trim();
1719
- if (!paneId || !paneId.startsWith('%')) {
1720
- throw new Error(`failed to capture worker pane id for worker ${i}`);
1925
+ catch (error) {
1926
+ if (error instanceof AmbiguousSplitWindowOutputError) {
1927
+ const isUnassignedAmbiguity = error.newlyObservedPaneIds.length > 1;
1928
+ for (const candidatePaneId of error.newlyObservedPaneIds) {
1929
+ rollbackPanes.set(candidatePaneId, null);
1930
+ partialWorkerPaneIds.push(candidatePaneId);
1931
+ if (isUnassignedAmbiguity)
1932
+ partialStartupCleanupPanePids.set(candidatePaneId, null);
1933
+ }
1934
+ if (error.newlyObservedPaneIds.length === 1) {
1935
+ partialWorkerPaneIdsByIndex[i - 1] = error.newlyObservedPaneIds[0];
1936
+ }
1937
+ for (const candidatePaneId of error.newlyObservedPaneIds) {
1938
+ const reconciledPid = exactProveAndTagReconciledPane(candidatePaneId);
1939
+ if (reconciledPid === null) {
1940
+ rollbackPanes.delete(candidatePaneId);
1941
+ partialWorkerPaneIds.splice(partialWorkerPaneIds.lastIndexOf(candidatePaneId), 1);
1942
+ partialStartupCleanupPanePids.delete(candidatePaneId);
1943
+ if (partialWorkerPaneIdsByIndex[i - 1] === candidatePaneId) {
1944
+ partialWorkerPaneIdsByIndex[i - 1] = null;
1945
+ }
1946
+ }
1947
+ else if (isUnassignedAmbiguity) {
1948
+ partialStartupCleanupPanePids.set(candidatePaneId, reconciledPid);
1949
+ }
1950
+ else {
1951
+ partialWorkerPanePidsByIndex[i - 1] = reconciledPid;
1952
+ }
1953
+ }
1954
+ }
1955
+ throw error;
1721
1956
  }
1722
1957
  // The pane exists once split-window returns its concrete ID. Persist it in
1723
1958
  // rollback/partial state before its first proof: a malformed or unavailable
@@ -1738,9 +1973,14 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1738
1973
  if (isNativeWindows() && !waitForPaneToRemainPresent(teamTarget, paneId)) {
1739
1974
  throw new Error(`worker pane ${i} did not remain present after tmux split-window returned ${paneId}`);
1740
1975
  }
1741
- tagPaneInstance(paneId, ownerSessionId, panePid);
1976
+ const paneSource = captureSourcePaneAuthority(paneId);
1977
+ if (paneSource.panePid !== panePid)
1978
+ throw new Error(`tmux pane identity changed: ${paneId}`);
1979
+ if (ownerSessionId) {
1980
+ runSourceAuthorizedTmux(paneSource, `set-option -p -t ${paneId} ${OMX_PANE_INSTANCE_OPTION} ${shellQuoteSingle(ownerSessionId)}`);
1981
+ }
1742
1982
  rollbackTaggedPaneOwnerIds.set(paneId, teamPaneOwnerId);
1743
- tagPaneTeamOwner(paneId, teamPaneOwnerId, panePid);
1983
+ runSourceAuthorizedTmux(paneSource, `set-option -p -t ${paneId} ${OMX_TEAM_PANE_OWNER_OPTION} ${shellQuoteSingle(teamPaneOwnerId)}`);
1744
1984
  frozenWindowPaneOwners.set(paneId, teamPaneOwnerId);
1745
1985
  workerPaneIds.push(paneId);
1746
1986
  if (i === 1) {
@@ -1750,7 +1990,7 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1750
1990
  }
1751
1991
  // Keep leader as full left/main pane; workers stay stacked on the right.
1752
1992
  requireFrozenWindowTopologySync(teamTarget, frozenWindowPanePids, frozenWindowPaneOwners);
1753
- runTmux(['select-layout', '-t', teamTarget, 'main-vertical']);
1993
+ runSourceAuthorizedTmux(leaderSource, `select-layout -t ${leaderSource.windowId} main-vertical`);
1754
1994
  // Force leader pane to use half the window width.
1755
1995
  const windowWidthResult = runTmux(['display-message', '-p', '-t', teamTarget, '#{window_width}']);
1756
1996
  if (windowWidthResult.ok) {
@@ -1758,9 +1998,9 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1758
1998
  if (Number.isFinite(width) && width >= 40) {
1759
1999
  const half = String(Math.floor(width / 2));
1760
2000
  requireFrozenWindowTopologySync(teamTarget, frozenWindowPanePids, frozenWindowPaneOwners);
1761
- runTmux(['set-window-option', '-t', teamTarget, 'main-pane-width', half]);
2001
+ runSourceAuthorizedTmux(leaderSource, `set-window-option -t ${leaderSource.windowId} main-pane-width ${half}`);
1762
2002
  requireFrozenWindowTopologySync(teamTarget, frozenWindowPanePids, frozenWindowPaneOwners);
1763
- runTmux(['select-layout', '-t', teamTarget, 'main-vertical']);
2003
+ runSourceAuthorizedTmux(leaderSource, `select-layout -t ${leaderSource.windowId} main-vertical`);
1764
2004
  }
1765
2005
  }
1766
2006
  // Re-create a single team HUD as a full-width bottom strip spanning both
@@ -1775,97 +2015,134 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1775
2015
  const hudCwd = translatePathForMsys(cwd);
1776
2016
  requireFrozenWindowTopologySync(teamTarget, frozenWindowPanePids, frozenWindowPaneOwners);
1777
2017
  const hudSplitTarget = leaderPaneId;
1778
- const hudResult = runTmux([
1779
- 'split-window', '-v', '-f', '-l', String(HUD_TMUX_TEAM_HEIGHT_LINES), '-t', hudSplitTarget, '-d', '-P', '-F', '#{pane_id}', '-c', hudCwd, hudCmd,
1780
- ]);
1781
- if (hudResult.ok) {
1782
- const id = hudResult.stdout.split('\n')[0]?.trim() ?? '';
1783
- if (id.startsWith('%')) {
1784
- // split-window has created a concrete pane even though no proof has
1785
- // authorized an effect yet. Retain PID-less cleanup debt first.
1786
- rollbackPanes.set(id, null);
1787
- partialHudPaneId = id;
1788
- partialHudPanePid = null;
1789
- const hudProof = readExactPaneProofSync(id);
1790
- if (hudProof.status === 'unavailable')
1791
- throw new ExactPaneProofUnavailableError(hudProof);
1792
- if (hudProof.status === 'gone')
1793
- throw new Error(`tmux pane is not proven live: ${id}`);
1794
- const hudPanePid = hudProof.pid;
1795
- frozenWindowPanePids.set(id, hudPanePid);
1796
- rollbackPanes.set(id, hudPanePid);
1797
- partialHudPanePid = hudPanePid;
1798
- if (isNativeWindows() && !waitForPaneToRemainPresent(teamTarget, id)) {
1799
- throw new Error(`HUD pane did not remain present after tmux split-window returned ${id}`);
2018
+ const hudSource = captureSourcePaneAuthority(hudSplitTarget, teamPaneOwnerId);
2019
+ let id;
2020
+ try {
2021
+ id = runSourceAuthorizedSplit(hudSource, (receipt) => `split-window -v -f -l ${HUD_TMUX_TEAM_HEIGHT_LINES} -t ${hudSplitTarget} -d -P -F '#{pane_id}' -c ${shellQuoteSingle(hudCwd)} ${shellQuoteSingle(bindSplitReceiptToPaneCommand(hudCmd, receipt))}`);
2022
+ }
2023
+ catch (error) {
2024
+ if (error instanceof AmbiguousSplitWindowOutputError) {
2025
+ const isUnassignedAmbiguity = error.newlyObservedPaneIds.length > 1;
2026
+ for (const candidatePaneId of error.newlyObservedPaneIds) {
2027
+ rollbackPanes.set(candidatePaneId, null);
2028
+ if (isUnassignedAmbiguity)
2029
+ partialStartupCleanupPanePids.set(candidatePaneId, null);
1800
2030
  }
1801
- tagPaneInstance(id, ownerSessionId, hudPanePid);
1802
- rollbackTaggedPaneOwnerIds.set(id, teamPaneOwnerId);
1803
- tagPaneTeamOwner(id, teamPaneOwnerId, hudPanePid);
1804
- frozenWindowPaneOwners.set(id, teamPaneOwnerId);
1805
- hudPaneId = id;
1806
- if (isNativeWindows()) {
1807
- const provenHudPaneId = requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
1808
- const reconcile = runTmux(buildHudResizeArgs(provenHudPaneId));
1809
- if (!reconcile.ok) {
1810
- throw new Error(`failed to reconcile HUD resize: ${reconcile.stderr}`);
1811
- }
2031
+ if (error.newlyObservedPaneIds.length === 1) {
2032
+ partialHudPaneId = error.newlyObservedPaneIds[0];
2033
+ partialHudPanePid = null;
1812
2034
  }
1813
- else {
1814
- const hookTarget = buildResizeHookTarget(sessionName, windowIndex);
1815
- const hookName = buildResizeHookName(safeTeamName, sessionName, windowIndex, hudPaneId);
1816
- requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
1817
- const registerHook = runTmux(buildRegisterResizeHookArgs(hookTarget, hookName, hudPaneId, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
1818
- const clientAttachedHookName = buildClientAttachedReconcileHookName(safeTeamName, sessionName, windowIndex, hudPaneId);
1819
- if (registerHook.ok) {
1820
- resizeHookTarget = hookTarget;
1821
- resizeHookName = hookName;
1822
- registeredResizeHook = {
1823
- name: resizeHookName,
1824
- target: resizeHookTarget,
1825
- leaderPaneId,
1826
- leaderPanePid,
1827
- hudPaneId,
1828
- hudPanePid,
1829
- teamPaneOwnerId,
1830
- };
2035
+ for (const candidatePaneId of error.newlyObservedPaneIds) {
2036
+ const reconciledPid = exactProveAndTagReconciledPane(candidatePaneId);
2037
+ if (reconciledPid === null) {
2038
+ rollbackPanes.delete(candidatePaneId);
2039
+ partialStartupCleanupPanePids.delete(candidatePaneId);
2040
+ if (partialHudPaneId === candidatePaneId)
2041
+ partialHudPaneId = null;
1831
2042
  }
1832
- else {
1833
- console.warn(`[omx] tmux resize hook unavailable for ${hookTarget} (${hookName}): ${registerHook.stderr}; `
1834
- + 'continuing with best-effort HUD resize fallback.');
1835
- }
1836
- requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
1837
- const registerClientAttachedHook = runTmux(buildRegisterClientAttachedReconcileArgs(hookTarget, clientAttachedHookName, hudPaneId, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
1838
- if (registerClientAttachedHook.ok) {
1839
- registeredClientAttachedHook = {
1840
- name: clientAttachedHookName,
1841
- target: hookTarget,
1842
- leaderPaneId,
1843
- leaderPanePid,
1844
- hudPaneId,
1845
- hudPanePid,
1846
- teamPaneOwnerId,
1847
- };
2043
+ else if (isUnassignedAmbiguity) {
2044
+ partialStartupCleanupPanePids.set(candidatePaneId, reconciledPid);
1848
2045
  }
1849
2046
  else {
1850
- console.warn(`[omx] tmux client-attached resize fallback unavailable for ${hookTarget} `
1851
- + `(${clientAttachedHookName}): ${registerClientAttachedHook.stderr}; continuing with delayed HUD resize fallback.`);
1852
- }
1853
- requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
1854
- const delayed = runTmux(buildScheduleDelayedHudResizeArgs(hudPaneId, HUD_RESIZE_RECONCILE_DELAY_SECONDS, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
1855
- if (!delayed.ok) {
1856
- console.warn(`[omx] tmux delayed HUD resize unavailable for ${hudPaneId}: ${delayed.stderr}; continuing.`);
1857
- }
1858
- requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
1859
- const reconcile = runTmux(buildReconcileHudResizeArgs(hudPaneId, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
1860
- if (!reconcile.ok) {
1861
- console.warn(`[omx] tmux HUD resize reconcile unavailable for ${hudPaneId}: ${reconcile.stderr}; continuing.`);
2047
+ partialHudPanePid = reconciledPid;
1862
2048
  }
1863
2049
  }
1864
2050
  }
2051
+ throw error;
2052
+ }
2053
+ {
2054
+ // split-window has created a concrete pane even though no proof has
2055
+ // authorized an effect yet. Retain PID-less cleanup debt first.
2056
+ rollbackPanes.set(id, null);
2057
+ partialHudPaneId = id;
2058
+ partialHudPanePid = null;
2059
+ const hudProof = readExactPaneProofSync(id);
2060
+ if (hudProof.status === 'unavailable')
2061
+ throw new ExactPaneProofUnavailableError(hudProof);
2062
+ if (hudProof.status === 'gone')
2063
+ throw new Error(`tmux pane is not proven live: ${id}`);
2064
+ const hudPanePid = hudProof.pid;
2065
+ frozenWindowPanePids.set(id, hudPanePid);
2066
+ rollbackPanes.set(id, hudPanePid);
2067
+ partialHudPanePid = hudPanePid;
2068
+ if (isNativeWindows() && !waitForPaneToRemainPresent(teamTarget, id)) {
2069
+ throw new Error(`HUD pane did not remain present after tmux split-window returned ${id}`);
2070
+ }
2071
+ const hudSource = captureSourcePaneAuthority(id);
2072
+ if (hudSource.panePid !== hudPanePid)
2073
+ throw new Error(`tmux pane identity changed: ${id}`);
2074
+ if (ownerSessionId) {
2075
+ runSourceAuthorizedTmux(hudSource, `set-option -p -t ${id} ${OMX_PANE_INSTANCE_OPTION} ${shellQuoteSingle(ownerSessionId)}`);
2076
+ }
2077
+ rollbackTaggedPaneOwnerIds.set(id, teamPaneOwnerId);
2078
+ runSourceAuthorizedTmux(hudSource, `set-option -p -t ${id} ${OMX_TEAM_PANE_OWNER_OPTION} ${shellQuoteSingle(teamPaneOwnerId)}`);
2079
+ frozenWindowPaneOwners.set(id, teamPaneOwnerId);
2080
+ hudPaneId = id;
2081
+ if (isNativeWindows()) {
2082
+ const provenHudPaneId = requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
2083
+ const reconcile = runTmux(buildHudResizeArgs(provenHudPaneId));
2084
+ if (!reconcile.ok) {
2085
+ throw new Error(`failed to reconcile HUD resize: ${reconcile.stderr}`);
2086
+ }
2087
+ }
2088
+ else {
2089
+ const hookTarget = buildResizeHookTarget(sessionName, windowIndex);
2090
+ const hookName = buildResizeHookName(safeTeamName, sessionName, windowIndex, hudPaneId);
2091
+ requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
2092
+ const registerHook = runTmux(buildRegisterResizeHookArgs(hookTarget, hookName, hudPaneId, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
2093
+ const clientAttachedHookName = buildClientAttachedReconcileHookName(safeTeamName, sessionName, windowIndex, hudPaneId);
2094
+ if (registerHook.ok) {
2095
+ resizeHookTarget = hookTarget;
2096
+ resizeHookName = hookName;
2097
+ registeredResizeHook = {
2098
+ name: resizeHookName,
2099
+ target: resizeHookTarget,
2100
+ leaderPaneId,
2101
+ leaderPanePid,
2102
+ hudPaneId,
2103
+ hudPanePid,
2104
+ teamPaneOwnerId,
2105
+ };
2106
+ }
2107
+ else {
2108
+ console.warn(`[omx] tmux resize hook unavailable for ${hookTarget} (${hookName}): ${registerHook.stderr}; `
2109
+ + 'continuing with best-effort HUD resize fallback.');
2110
+ }
2111
+ requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
2112
+ const registerClientAttachedHook = runTmux(buildRegisterClientAttachedReconcileArgs(hookTarget, clientAttachedHookName, hudPaneId, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
2113
+ if (registerClientAttachedHook.ok) {
2114
+ registeredClientAttachedHook = {
2115
+ name: clientAttachedHookName,
2116
+ target: hookTarget,
2117
+ leaderPaneId,
2118
+ leaderPanePid,
2119
+ hudPaneId,
2120
+ hudPanePid,
2121
+ teamPaneOwnerId,
2122
+ };
2123
+ }
2124
+ else {
2125
+ console.warn(`[omx] tmux client-attached resize fallback unavailable for ${hookTarget} `
2126
+ + `(${clientAttachedHookName}): ${registerClientAttachedHook.stderr}; continuing with delayed HUD resize fallback.`);
2127
+ }
2128
+ requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
2129
+ const delayed = runTmux(buildScheduleDelayedHudResizeArgs(hudPaneId, HUD_RESIZE_RECONCILE_DELAY_SECONDS, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
2130
+ if (!delayed.ok) {
2131
+ console.warn(`[omx] tmux delayed HUD resize unavailable for ${hudPaneId}: ${delayed.stderr}; continuing.`);
2132
+ }
2133
+ requireLiveTeamOwnedPaneSync(hudPaneId, hudPanePid, teamPaneOwnerId);
2134
+ const reconcile = runTmux(buildReconcileHudResizeArgs(hudPaneId, HUD_TMUX_TEAM_HEIGHT_LINES, hudPanePid, teamPaneOwnerId));
2135
+ if (!reconcile.ok) {
2136
+ console.warn(`[omx] tmux HUD resize reconcile unavailable for ${hudPaneId}: ${reconcile.stderr}; continuing.`);
2137
+ }
2138
+ }
1865
2139
  }
1866
2140
  }
1867
- runTmux(['select-pane', '-t', requireLiveTeamOwnedPaneSync(leaderPaneId, leaderPanePid, teamPaneOwnerId)]);
1868
- redrawLeaderPaneAfterTeamLayout(leaderPaneId, leaderPanePid, teamPaneOwnerId);
2141
+ const focusedLeader = requireLiveTeamOwnedPaneSync(leaderPaneId, leaderPanePid, teamPaneOwnerId);
2142
+ if (focusedLeader !== leaderSource.paneId)
2143
+ throw new Error(`tmux pane identity changed: ${leaderPaneId}`);
2144
+ runSourceAuthorizedTmux(leaderSource, `select-pane -t ${leaderPaneId}`);
2145
+ redrawLeaderPaneAfterTeamLayout(leaderSource, teamPaneOwnerId);
1869
2146
  sleepSeconds(0.5);
1870
2147
  // Enable mouse scrolling so agent output panes can be scrolled with the
1871
2148
  // mouse wheel without conflicting with keyboard up/down arrow-key input
@@ -1874,20 +2151,20 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1874
2151
  if (process.env.OMX_TEAM_MOUSE !== '0') {
1875
2152
  enableMouseScrolling(sessionName, () => { requireLiveTeamOwnedPaneSync(leaderPaneId, leaderPanePid, teamPaneOwnerId); });
1876
2153
  }
1877
- const sessionIncarnation = teamTarget.includes(':') ? null : queryDetachedTeamSession(sessionName);
1878
- if (sessionIncarnation && sessionIncarnation.status !== 'exact') {
1879
- throw new Error(`tmux_session_incarnation_unavailable:${sessionName}`);
1880
- }
1881
2154
  return {
1882
2155
  name: teamTarget,
1883
- tmuxSessionId: sessionIncarnation?.incarnation.sessionId,
1884
- tmuxSessionCreated: sessionIncarnation?.incarnation.sessionCreated,
2156
+ tmuxSessionId: leaderSource.sessionId,
2157
+ tmuxSessionCreated: leaderSource.sessionCreated,
1885
2158
  workerCount,
1886
2159
  cwd,
1887
2160
  workerPaneIds,
1888
2161
  workerPaneIdsByIndex: [...workerPaneIds],
1889
2162
  workerPanePidsByIndex,
1890
2163
  leaderPanePid,
2164
+ workerStartupArgs: Object.freeze(workerStartupArgs),
2165
+ leaderSessionId: leaderSource.sessionId,
2166
+ leaderSessionCreated: leaderSource.sessionCreated,
2167
+ leaderWindowId: leaderSource.windowId,
1891
2168
  hudPanePid: partialHudPanePid,
1892
2169
  leaderPaneId,
1893
2170
  hudPaneId,
@@ -1898,6 +2175,9 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1898
2175
  }
1899
2176
  catch (error) {
1900
2177
  const cleanupErrors = [];
2178
+ if (error instanceof AmbiguousSplitWindowOutputError && error.reconciliationError) {
2179
+ cleanupErrors.push('failed to reconcile tmux pane topology after ambiguous split output');
2180
+ }
1901
2181
  const unregisterAuthorizedHook = (hook, unregister, label) => {
1902
2182
  try {
1903
2183
  requireLiveTeamOwnedPaneSync(hook.leaderPaneId, hook.leaderPanePid, hook.teamPaneOwnerId);
@@ -1949,6 +2229,9 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1949
2229
  .map((paneId) => paneId && unresolvedPaneIds.has(paneId) ? paneId : null);
1950
2230
  const unresolvedWorkerPanePidsByIndex = partialWorkerPanePidsByIndex
1951
2231
  .map((panePid, index) => partialWorkerPaneIdsByIndex[index] && unresolvedPaneIds.has(partialWorkerPaneIdsByIndex[index]) ? panePid : null);
2232
+ const unresolvedStartupCleanupPanes = [...partialStartupCleanupPanePids.entries()]
2233
+ .filter(([paneId]) => unresolvedPaneIds.has(paneId))
2234
+ .map(([paneId, panePid]) => ({ paneId, panePid }));
1952
2235
  const unresolvedHudPaneId = partialHudPaneId && (unresolvedPaneIds.has(partialHudPaneId)
1953
2236
  || registeredResizeHook !== null
1954
2237
  || registeredClientAttachedHook !== null)
@@ -1956,7 +2239,8 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1956
2239
  : null;
1957
2240
  const hasRecoverablePartialArtifact = unresolvedPaneIds.size > 0
1958
2241
  || registeredResizeHook !== null
1959
- || registeredClientAttachedHook !== null;
2242
+ || registeredClientAttachedHook !== null
2243
+ || (error instanceof AmbiguousSplitWindowOutputError && error.reconciliationError !== null);
1960
2244
  if (hasRecoverablePartialArtifact && partialTeamTarget && partialLeaderPaneId) {
1961
2245
  throw new CreateTeamSessionPartialError({
1962
2246
  name: partialTeamTarget,
@@ -1965,6 +2249,7 @@ export function createTeamSession(teamName, workerCount, cwd, workerLaunchArgs =
1965
2249
  workerPaneIds: unresolvedWorkerPaneIds,
1966
2250
  workerPaneIdsByIndex: unresolvedWorkerPaneIdsByIndex,
1967
2251
  workerPanePidsByIndex: unresolvedWorkerPanePidsByIndex,
2252
+ startupCleanupPanes: unresolvedStartupCleanupPanes,
1968
2253
  leaderPanePid: partialLeaderPanePid,
1969
2254
  hudPanePid: unresolvedHudPaneId ? partialHudPanePid : null,
1970
2255
  leaderPaneId: partialLeaderPaneId,
@@ -2038,7 +2323,9 @@ export function restoreStandaloneHudPane(leaderPaneId, cwd, options = {}) {
2038
2323
  runTmux(['select-pane', '-t', requireAuthorizedLeaderPane()]);
2039
2324
  return existingHudPaneId;
2040
2325
  }
2041
- const hudCmd = `exec env ${formatHudEnvAssignments(process.env, { sessionId: options.sessionId, leaderPaneId: normalizedLeaderPaneId })} ${shellQuoteSingle(translatePathForMsys(resolveLeaderNodePath()))} ${shellQuoteSingle(translatePathForMsys(omxEntry))} hud --watch`;
2326
+ const beforeSplitPaneIds = new Set(paneListResult.panes.map((pane) => pane.paneId));
2327
+ const splitReceipt = sourceTransactionReceipt();
2328
+ const hudCmd = bindSplitReceiptToPaneCommand(`exec env ${formatHudEnvAssignments(process.env, { sessionId: options.sessionId, leaderPaneId: normalizedLeaderPaneId })} ${shellQuoteSingle(translatePathForMsys(resolveLeaderNodePath()))} ${shellQuoteSingle(translatePathForMsys(omxEntry))} hud --watch`, splitReceipt);
2042
2329
  let hudResult = null;
2043
2330
  for (const restoreCwd of resolveStandaloneHudRestoreCwdCandidates(normalizedLeaderPaneId, cwd, options.cwd, requireAuthorizedLeaderPane)) {
2044
2331
  const candidateResult = runTmux([
@@ -2055,7 +2342,7 @@ export function restoreStandaloneHudPane(leaderPaneId, cwd, options = {}) {
2055
2342
  '-c',
2056
2343
  translatePathForMsys(restoreCwd.rawPath),
2057
2344
  hudCmd,
2058
- ]);
2345
+ ], true);
2059
2346
  if (candidateResult.ok) {
2060
2347
  hudResult = candidateResult;
2061
2348
  break;
@@ -2063,9 +2350,45 @@ export function restoreStandaloneHudPane(leaderPaneId, cwd, options = {}) {
2063
2350
  }
2064
2351
  if (!hudResult?.ok)
2065
2352
  return null;
2066
- const paneId = hudResult.stdout.split('\n')[0]?.trim() ?? '';
2067
- if (!paneId.startsWith('%'))
2068
- return null;
2353
+ const paneId = parseSplitWindowPaneId(hudResult.stdout);
2354
+ if (!paneId) {
2355
+ const afterTopology = listPanesResult(normalizedLeaderPaneId);
2356
+ if (afterTopology.error) {
2357
+ throw new Error('restored_hud_split_topology_reconciliation_failed');
2358
+ }
2359
+ const newlyObservedPaneIds = afterTopology.panes
2360
+ .filter((pane) => !beforeSplitPaneIds.has(pane.paneId) && pane.startCommand.includes(splitReceipt))
2361
+ .map((pane) => pane.paneId);
2362
+ if (newlyObservedPaneIds.length === 1) {
2363
+ const reconciledPaneId = newlyObservedPaneIds[0];
2364
+ persistRestoredHudCleanupDebtSync(cwd, {
2365
+ schema_version: 1,
2366
+ operation: 'restored_hud_cleanup',
2367
+ pane_id: reconciledPaneId,
2368
+ pane_pid: null,
2369
+ leader_pane_id: normalizedLeaderPaneId,
2370
+ leader_pane_pid: options.expectedLeaderPanePid ?? leaderPanePid,
2371
+ leader_pane_owner_id: options.expectedLeaderPaneOwnerId?.trim() || null,
2372
+ hud_owner_leader_pane_id: normalizedLeaderPaneId,
2373
+ }, options.stateRoot);
2374
+ const reconciledProof = readExactPaneProofSync(reconciledPaneId);
2375
+ if (reconciledProof.status === 'unavailable')
2376
+ throw new ExactPaneProofUnavailableError(reconciledProof);
2377
+ if (reconciledProof.status === 'gone')
2378
+ throw new Error(`tmux pane is not proven live: ${reconciledPaneId}`);
2379
+ persistRestoredHudCleanupDebtSync(cwd, {
2380
+ schema_version: 1,
2381
+ operation: 'restored_hud_cleanup',
2382
+ pane_id: reconciledPaneId,
2383
+ pane_pid: reconciledProof.pid,
2384
+ leader_pane_id: normalizedLeaderPaneId,
2385
+ leader_pane_pid: options.expectedLeaderPanePid ?? leaderPanePid,
2386
+ leader_pane_owner_id: options.expectedLeaderPaneOwnerId?.trim() || null,
2387
+ hud_owner_leader_pane_id: normalizedLeaderPaneId,
2388
+ }, options.stateRoot);
2389
+ }
2390
+ throw new Error('restored_hud_split_output_ambiguous');
2391
+ }
2069
2392
  persistRestoredHudCleanupDebtSync(cwd, {
2070
2393
  schema_version: 1,
2071
2394
  operation: 'restored_hud_cleanup',
@@ -2163,7 +2486,10 @@ function paneHasClaudeBypassPermissionsPrompt(captured) {
2163
2486
  && tail.some((line) => /Enter\s*to\s*confirm/i.test(line));
2164
2487
  return hasWarning && hasChoices;
2165
2488
  }
2166
- export function evaluateStartupDirectTriggerSafetyCapture(captured, workerCli) {
2489
+ export function evaluateStartupDirectTriggerSafetyCapture(captured, workerCli, finalArgs) {
2490
+ const incompatibleReason = classifyCodexBypassMdmIncompatibility(captured, workerCli, finalArgs);
2491
+ if (incompatibleReason)
2492
+ return { safe: false, reason: incompatibleReason };
2167
2493
  if (paneHasTrustPrompt(captured))
2168
2494
  return { safe: false, reason: 'trust_prompt' };
2169
2495
  if (paneHasClaudeBypassPermissionsPrompt(captured))
@@ -2176,7 +2502,7 @@ export function evaluateStartupDirectTriggerSafetyCapture(captured, workerCli) {
2176
2502
  return { safe: true, reason: 'codex_viewport' };
2177
2503
  return { safe: false, reason: 'not_agent_viewport' };
2178
2504
  }
2179
- export async function evaluateStartupDirectTriggerSafety(sessionName, workerIndex, workerPaneId, workerCli) {
2505
+ export async function evaluateStartupDirectTriggerSafety(sessionName, workerIndex, workerPaneId, workerCli, finalArgs) {
2180
2506
  if (!isTmuxAvailable())
2181
2507
  return { safe: false, reason: 'tmux_unavailable' };
2182
2508
  const target = await resolveWorkerPaneTargetAsync(sessionName, workerIndex, workerPaneId);
@@ -2185,7 +2511,7 @@ export async function evaluateStartupDirectTriggerSafety(sessionName, workerInde
2185
2511
  const result = await runTmuxAsync(sharedBuildVisibleCapturePaneArgv(target));
2186
2512
  if (!result.ok)
2187
2513
  return { safe: false, reason: 'capture_failed' };
2188
- return evaluateStartupDirectTriggerSafetyCapture(result.stdout, workerCli);
2514
+ return evaluateStartupDirectTriggerSafetyCapture(result.stdout, workerCli, finalArgs);
2189
2515
  }
2190
2516
  function acceptClaudeBypassPermissionsPrompt(resolveTarget) {
2191
2517
  const literalTarget = resolveTarget();
@@ -2455,12 +2781,13 @@ export function waitForWorkerReady(sessionName, workerIndex, timeoutMs = 30_000,
2455
2781
  // Async twin of waitForWorkerReady for team startup fan-out. Keep the readiness
2456
2782
  // semantics mirrored with the synchronous helper above, but yield between polls
2457
2783
  // so one slow worker pane cannot block later workers' startup attempts.
2458
- export async function waitForWorkerReadyAsync(sessionName, workerIndex, timeoutMs = 30_000, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId) {
2784
+ export async function waitForWorkerReadyDetailedAsync(sessionName, workerIndex, timeoutMs = 30_000, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId, incompatibility) {
2459
2785
  const initialBackoffMs = 150;
2460
2786
  const maxBackoffMs = 8000;
2461
2787
  const startedAt = Date.now();
2462
2788
  let blockedByTrustPrompt = false;
2463
2789
  let promptDismissed = false;
2790
+ let startupIncompatible = false;
2464
2791
  const resolveTarget = createPinnedWorkerPaneTargetResolver(sessionName, workerIndex, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId);
2465
2792
  const sendRobustEnter = async () => {
2466
2793
  // Trust + follow-up splash can require two submits in Codex TUI.
@@ -2482,6 +2809,12 @@ export async function waitForWorkerReadyAsync(sessionName, workerIndex, timeoutM
2482
2809
  const result = await runTmuxAsync(sharedBuildVisibleCapturePaneArgv(target));
2483
2810
  if (!result.ok)
2484
2811
  return false;
2812
+ const incompatibleReason = classifyCodexBypassMdmIncompatibility(result.stdout, incompatibility?.workerCli, incompatibility?.finalArgs);
2813
+ if (incompatibleReason) {
2814
+ startupIncompatible = true;
2815
+ incompatibility?.onIncompatible(incompatibleReason);
2816
+ return false;
2817
+ }
2485
2818
  if (await dismissClaudeBypassPermissionsPromptIfPresentAsync(resolveTarget, result.stdout)) {
2486
2819
  promptDismissed = true;
2487
2820
  return false;
@@ -2519,6 +2852,8 @@ export async function waitForWorkerReadyAsync(sessionName, workerIndex, timeoutM
2519
2852
  while (Date.now() - startedAt < timeoutMs) {
2520
2853
  if (await check())
2521
2854
  return true;
2855
+ if (startupIncompatible)
2856
+ return false;
2522
2857
  if (blockedByTrustPrompt)
2523
2858
  return false;
2524
2859
  // After dismissing a trust prompt, reset backoff so we re-check quickly
@@ -2535,6 +2870,9 @@ export async function waitForWorkerReadyAsync(sessionName, workerIndex, timeoutM
2535
2870
  }
2536
2871
  return false;
2537
2872
  }
2873
+ export async function waitForWorkerReadyAsync(sessionName, workerIndex, timeoutMs = 30_000, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId) {
2874
+ return waitForWorkerReadyDetailedAsync(sessionName, workerIndex, timeoutMs, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId);
2875
+ }
2538
2876
  /**
2539
2877
  * Detect and auto-dismiss a Codex "Trust this directory?" prompt in a worker pane.
2540
2878
  * Returns true if a trust prompt was found and dismissed, false otherwise.
@@ -2692,8 +3030,8 @@ export function notifyLeaderStatus(sessionName, message) {
2692
3030
  // Get PID of the shell process in a worker's tmux pane
2693
3031
  export function getWorkerPanePid(sessionName, workerIndex, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId) {
2694
3032
  if (hasExplicitWorkerPaneId(workerPaneId)) {
2695
- const target = createPinnedWorkerPaneTargetResolverSync(sessionName, workerIndex, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId)();
2696
- return target ? expectedPanePid ?? null : null;
3033
+ const proof = requireExactWorkerPaneLivenessIdentity(workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId);
3034
+ return proof.status === 'live' ? proof.pid : null;
2697
3035
  }
2698
3036
  const result = runTmux(['list-panes', '-t', paneTarget(sessionName, workerIndex), '-F', '#{pane_pid}']);
2699
3037
  if (!result.ok)
@@ -2709,10 +3047,19 @@ export function getWorkerPanePid(sessionName, workerIndex, workerPaneId, expecte
2709
3047
  // Check if worker's tmux pane has a running process
2710
3048
  export function isWorkerAlive(sessionName, workerIndex, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId) {
2711
3049
  if (hasExplicitWorkerPaneId(workerPaneId)) {
2712
- const target = createPinnedWorkerPaneTargetResolverSync(sessionName, workerIndex, workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId)();
2713
- if (!target || typeof expectedPanePid !== 'number')
3050
+ if (hudPaneId?.trim() && workerPaneId === hudPaneId.trim()) {
3051
+ throw new Error(`tmux worker pane is HUD target: ${workerPaneId}`);
3052
+ }
3053
+ const proof = requireExactWorkerPaneLivenessIdentity(workerPaneId, expectedPanePid, expectedTeamOwnerId, hudPaneId);
3054
+ if (proof.status === 'unavailable')
3055
+ return true;
3056
+ if (proof.status === 'gone')
2714
3057
  return false;
2715
- return probeProcessLiveness(expectedPanePid) !== 'gone';
3058
+ if (typeof expectedPanePid !== 'number' || !Number.isSafeInteger(expectedPanePid) || expectedPanePid <= 0)
3059
+ return true;
3060
+ if (typeof expectedTeamOwnerId !== 'string' || expectedTeamOwnerId.trim() === '')
3061
+ return true;
3062
+ return probeProcessLiveness(proof.pid) !== 'gone';
2716
3063
  }
2717
3064
  const result = runTmux([
2718
3065
  'list-panes',