oh-my-codex 0.11.13 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (369) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/README.md +27 -17
  4. package/crates/omx-runtime/src/main.rs +6 -2
  5. package/dist/agents/native-config.js +1 -1
  6. package/dist/agents/native-config.js.map +1 -1
  7. package/dist/cli/__tests__/autoresearch-guided.test.js +74 -2
  8. package/dist/cli/__tests__/autoresearch-guided.test.js.map +1 -1
  9. package/dist/cli/__tests__/cleanup.test.js +22 -30
  10. package/dist/cli/__tests__/cleanup.test.js.map +1 -1
  11. package/dist/cli/__tests__/error-handling-warnings.test.js +3 -1
  12. package/dist/cli/__tests__/error-handling-warnings.test.js.map +1 -1
  13. package/dist/cli/__tests__/index.test.js +217 -4
  14. package/dist/cli/__tests__/index.test.js.map +1 -1
  15. package/dist/cli/__tests__/setup-refresh.test.js +49 -9
  16. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  17. package/dist/cli/__tests__/setup-scope.test.js +9 -0
  18. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  19. package/dist/cli/__tests__/team.test.js +136 -11
  20. package/dist/cli/__tests__/team.test.js.map +1 -1
  21. package/dist/cli/__tests__/uninstall.test.js +10 -0
  22. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  23. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +1 -0
  24. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  25. package/dist/cli/autoresearch-guided.d.ts.map +1 -1
  26. package/dist/cli/autoresearch-guided.js +2 -1
  27. package/dist/cli/autoresearch-guided.js.map +1 -1
  28. package/dist/cli/autoresearch.d.ts.map +1 -1
  29. package/dist/cli/autoresearch.js +2 -1
  30. package/dist/cli/autoresearch.js.map +1 -1
  31. package/dist/cli/cleanup.d.ts.map +1 -1
  32. package/dist/cli/cleanup.js +4 -2
  33. package/dist/cli/cleanup.js.map +1 -1
  34. package/dist/cli/index.d.ts +12 -0
  35. package/dist/cli/index.d.ts.map +1 -1
  36. package/dist/cli/index.js +238 -30
  37. package/dist/cli/index.js.map +1 -1
  38. package/dist/cli/omx.js +2 -0
  39. package/dist/cli/omx.js.map +1 -1
  40. package/dist/cli/setup.d.ts +1 -0
  41. package/dist/cli/setup.d.ts.map +1 -1
  42. package/dist/cli/setup.js +41 -7
  43. package/dist/cli/setup.js.map +1 -1
  44. package/dist/cli/team.d.ts.map +1 -1
  45. package/dist/cli/team.js +16 -557
  46. package/dist/cli/team.js.map +1 -1
  47. package/dist/cli/uninstall.d.ts.map +1 -1
  48. package/dist/cli/uninstall.js +34 -9
  49. package/dist/cli/uninstall.js.map +1 -1
  50. package/dist/config/__tests__/generator-idempotent.test.js +79 -2
  51. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  52. package/dist/config/__tests__/generator-notify.test.js +2 -0
  53. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  54. package/dist/config/codex-hooks.d.ts +11 -0
  55. package/dist/config/codex-hooks.d.ts.map +1 -0
  56. package/dist/config/codex-hooks.js +50 -0
  57. package/dist/config/codex-hooks.js.map +1 -0
  58. package/dist/config/generator.d.ts +5 -3
  59. package/dist/config/generator.d.ts.map +1 -1
  60. package/dist/config/generator.js +24 -14
  61. package/dist/config/generator.js.map +1 -1
  62. package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts +2 -0
  63. package/dist/hooks/__tests__/debugger-log-recency-contract.test.d.ts.map +1 -0
  64. package/dist/hooks/__tests__/debugger-log-recency-contract.test.js +20 -0
  65. package/dist/hooks/__tests__/debugger-log-recency-contract.test.js.map +1 -0
  66. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +236 -2
  67. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  68. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +86 -0
  69. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  70. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +40 -0
  71. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  72. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts +2 -0
  73. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.d.ts.map +1 -0
  74. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +54 -0
  75. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -0
  76. package/dist/hooks/__tests__/notify-hook-modules.test.js +31 -0
  77. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  78. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +51 -0
  79. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
  80. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts +2 -0
  81. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.d.ts.map +1 -0
  82. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js +136 -0
  83. package/dist/hooks/__tests__/notify-hook-session-idle-dedupe.test.js.map +1 -0
  84. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +120 -0
  85. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  86. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +145 -20
  87. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  88. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +116 -0
  89. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  90. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +86 -0
  91. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  92. package/dist/hooks/__tests__/pre-context-gate-skills.test.js +1 -0
  93. package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -1
  94. package/dist/hooks/extensibility/__tests__/runtime.test.js +49 -0
  95. package/dist/hooks/extensibility/__tests__/runtime.test.js.map +1 -1
  96. package/dist/hooks/extensibility/runtime.d.ts.map +1 -1
  97. package/dist/hooks/extensibility/runtime.js +10 -0
  98. package/dist/hooks/extensibility/runtime.js.map +1 -1
  99. package/dist/hooks/extensibility/types.d.ts +1 -1
  100. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  101. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  102. package/dist/hooks/prompt-guidance-contract.js +12 -8
  103. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  104. package/dist/hooks/session.d.ts +5 -1
  105. package/dist/hooks/session.d.ts.map +1 -1
  106. package/dist/hooks/session.js +10 -6
  107. package/dist/hooks/session.js.map +1 -1
  108. package/dist/hud/index.d.ts.map +1 -1
  109. package/dist/hud/index.js +6 -1
  110. package/dist/hud/index.js.map +1 -1
  111. package/dist/mcp/__tests__/bootstrap.test.js +0 -3
  112. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  113. package/dist/mcp/__tests__/code-intel-server.test.js +27 -1
  114. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  115. package/dist/mcp/__tests__/server-lifecycle.test.js +0 -5
  116. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  117. package/dist/mcp/bootstrap.d.ts +1 -1
  118. package/dist/mcp/bootstrap.d.ts.map +1 -1
  119. package/dist/mcp/bootstrap.js +0 -1
  120. package/dist/mcp/bootstrap.js.map +1 -1
  121. package/dist/mcp/code-intel-server.d.ts +20 -0
  122. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  123. package/dist/mcp/code-intel-server.js +6 -5
  124. package/dist/mcp/code-intel-server.js.map +1 -1
  125. package/dist/notifications/__tests__/idle-cooldown.test.js +24 -1
  126. package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -1
  127. package/dist/notifications/__tests__/reply-listener.test.js +20 -1
  128. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
  129. package/dist/notifications/__tests__/tmux.test.js +41 -0
  130. package/dist/notifications/__tests__/tmux.test.js.map +1 -1
  131. package/dist/notifications/idle-cooldown.d.ts +13 -0
  132. package/dist/notifications/idle-cooldown.d.ts.map +1 -1
  133. package/dist/notifications/idle-cooldown.js +50 -16
  134. package/dist/notifications/idle-cooldown.js.map +1 -1
  135. package/dist/notifications/reply-listener.d.ts.map +1 -1
  136. package/dist/notifications/reply-listener.js +2 -0
  137. package/dist/notifications/reply-listener.js.map +1 -1
  138. package/dist/notifications/tmux.d.ts.map +1 -1
  139. package/dist/notifications/tmux.js +4 -0
  140. package/dist/notifications/tmux.js.map +1 -1
  141. package/dist/scripts/__tests__/codex-native-hook.test.d.ts +2 -0
  142. package/dist/scripts/__tests__/codex-native-hook.test.d.ts.map +1 -0
  143. package/dist/scripts/__tests__/codex-native-hook.test.js +720 -0
  144. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -0
  145. package/dist/scripts/codex-native-hook.d.ts +22 -0
  146. package/dist/scripts/codex-native-hook.d.ts.map +1 -0
  147. package/dist/scripts/codex-native-hook.js +594 -0
  148. package/dist/scripts/codex-native-hook.js.map +1 -0
  149. package/dist/scripts/codex-native-pre-post.d.ts +26 -0
  150. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -0
  151. package/dist/scripts/codex-native-pre-post.js +118 -0
  152. package/dist/scripts/codex-native-pre-post.js.map +1 -0
  153. package/dist/scripts/notify-fallback-watcher.js +262 -18
  154. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  155. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  156. package/dist/scripts/notify-hook/auto-nudge.js +5 -6
  157. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  158. package/dist/scripts/notify-hook/log.d.ts +2 -2
  159. package/dist/scripts/notify-hook/log.d.ts.map +1 -1
  160. package/dist/scripts/notify-hook/log.js +10 -2
  161. package/dist/scripts/notify-hook/log.js.map +1 -1
  162. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  163. package/dist/scripts/notify-hook/managed-tmux.js +2 -0
  164. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  165. package/dist/scripts/notify-hook/orchestration-intent.d.ts +18 -0
  166. package/dist/scripts/notify-hook/orchestration-intent.d.ts.map +1 -0
  167. package/dist/scripts/notify-hook/orchestration-intent.js +72 -0
  168. package/dist/scripts/notify-hook/orchestration-intent.js.map +1 -0
  169. package/dist/scripts/notify-hook/process-runner.js.map +1 -1
  170. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  171. package/dist/scripts/notify-hook/ralph-session-resume.js +7 -0
  172. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  173. package/dist/scripts/notify-hook/team-dispatch.d.ts +15 -6
  174. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  175. package/dist/scripts/notify-hook/team-dispatch.js +125 -6
  176. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  177. package/dist/scripts/notify-hook/team-leader-nudge.d.ts +3 -2
  178. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  179. package/dist/scripts/notify-hook/team-leader-nudge.js +165 -37
  180. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  181. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +4 -1
  182. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  183. package/dist/scripts/notify-hook/team-tmux-guard.js +33 -44
  184. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  185. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  186. package/dist/scripts/notify-hook/team-worker.js +68 -5
  187. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  188. package/dist/scripts/notify-hook/utils.d.ts +1 -1
  189. package/dist/scripts/notify-hook/utils.d.ts.map +1 -1
  190. package/dist/scripts/notify-hook/utils.js.map +1 -1
  191. package/dist/scripts/notify-hook.js +55 -32
  192. package/dist/scripts/notify-hook.js.map +1 -1
  193. package/dist/team/__tests__/api-interop.test.js +344 -18
  194. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  195. package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts +2 -0
  196. package/dist/team/__tests__/delivery-e2e-smoke.test.d.ts.map +1 -0
  197. package/dist/team/__tests__/delivery-e2e-smoke.test.js +671 -0
  198. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -0
  199. package/dist/team/__tests__/mcp-comm.test.js +5 -0
  200. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  201. package/dist/team/__tests__/runtime.test.js +422 -12
  202. package/dist/team/__tests__/runtime.test.js.map +1 -1
  203. package/dist/team/__tests__/state.test.js +126 -8
  204. package/dist/team/__tests__/state.test.js.map +1 -1
  205. package/dist/team/__tests__/team-ops-contract.test.js +4 -0
  206. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  207. package/dist/team/__tests__/tmux-session.test.js +160 -0
  208. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  209. package/dist/team/__tests__/worker-bootstrap.test.js +19 -1
  210. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  211. package/dist/team/api-interop.d.ts.map +1 -1
  212. package/dist/team/api-interop.js +95 -23
  213. package/dist/team/api-interop.js.map +1 -1
  214. package/dist/team/contracts.d.ts +11 -1
  215. package/dist/team/contracts.d.ts.map +1 -1
  216. package/dist/team/contracts.js +29 -0
  217. package/dist/team/contracts.js.map +1 -1
  218. package/dist/team/delivery-log.d.ts +14 -0
  219. package/dist/team/delivery-log.d.ts.map +1 -0
  220. package/dist/team/delivery-log.js +35 -0
  221. package/dist/team/delivery-log.js.map +1 -0
  222. package/dist/team/idle-nudge.d.ts +2 -2
  223. package/dist/team/idle-nudge.js +2 -2
  224. package/dist/team/mcp-comm.d.ts +4 -0
  225. package/dist/team/mcp-comm.d.ts.map +1 -1
  226. package/dist/team/mcp-comm.js +84 -1
  227. package/dist/team/mcp-comm.js.map +1 -1
  228. package/dist/team/pane-status.d.ts +149 -0
  229. package/dist/team/pane-status.d.ts.map +1 -0
  230. package/dist/team/pane-status.js +558 -0
  231. package/dist/team/pane-status.js.map +1 -0
  232. package/dist/team/reminder-intents.d.ts +11 -0
  233. package/dist/team/reminder-intents.d.ts.map +1 -0
  234. package/dist/team/reminder-intents.js +40 -0
  235. package/dist/team/reminder-intents.js.map +1 -0
  236. package/dist/team/runtime-cli.d.ts +1 -1
  237. package/dist/team/runtime-cli.js +2 -2
  238. package/dist/team/runtime-cli.js.map +1 -1
  239. package/dist/team/runtime.d.ts +2 -1
  240. package/dist/team/runtime.d.ts.map +1 -1
  241. package/dist/team/runtime.js +407 -190
  242. package/dist/team/runtime.js.map +1 -1
  243. package/dist/team/scaling.d.ts.map +1 -1
  244. package/dist/team/scaling.js +6 -5
  245. package/dist/team/scaling.js.map +1 -1
  246. package/dist/team/state/dispatch.d.ts +4 -1
  247. package/dist/team/state/dispatch.d.ts.map +1 -1
  248. package/dist/team/state/dispatch.js +59 -18
  249. package/dist/team/state/dispatch.js.map +1 -1
  250. package/dist/team/state/mailbox.d.ts.map +1 -1
  251. package/dist/team/state/mailbox.js +39 -2
  252. package/dist/team/state/mailbox.js.map +1 -1
  253. package/dist/team/state/monitor.d.ts +2 -1
  254. package/dist/team/state/monitor.d.ts.map +1 -1
  255. package/dist/team/state/monitor.js +30 -1
  256. package/dist/team/state/monitor.js.map +1 -1
  257. package/dist/team/state/types.d.ts +5 -2
  258. package/dist/team/state/types.d.ts.map +1 -1
  259. package/dist/team/state/types.js.map +1 -1
  260. package/dist/team/state.d.ts +30 -3
  261. package/dist/team/state.d.ts.map +1 -1
  262. package/dist/team/state.js +170 -2
  263. package/dist/team/state.js.map +1 -1
  264. package/dist/team/team-ops.d.ts +5 -1
  265. package/dist/team/team-ops.d.ts.map +1 -1
  266. package/dist/team/team-ops.js +4 -0
  267. package/dist/team/team-ops.js.map +1 -1
  268. package/dist/team/tmux-session.d.ts +2 -0
  269. package/dist/team/tmux-session.d.ts.map +1 -1
  270. package/dist/team/tmux-session.js +19 -3
  271. package/dist/team/tmux-session.js.map +1 -1
  272. package/dist/team/worker-bootstrap.d.ts +4 -0
  273. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  274. package/dist/team/worker-bootstrap.js +33 -6
  275. package/dist/team/worker-bootstrap.js.map +1 -1
  276. package/dist/utils/__tests__/paths.test.js +63 -1
  277. package/dist/utils/__tests__/paths.test.js.map +1 -1
  278. package/dist/utils/__tests__/platform-command.test.js +50 -4
  279. package/dist/utils/__tests__/platform-command.test.js.map +1 -1
  280. package/dist/utils/paths.d.ts +12 -0
  281. package/dist/utils/paths.d.ts.map +1 -1
  282. package/dist/utils/paths.js +44 -2
  283. package/dist/utils/paths.js.map +1 -1
  284. package/dist/utils/platform-command.d.ts.map +1 -1
  285. package/dist/utils/platform-command.js +13 -5
  286. package/dist/utils/platform-command.js.map +1 -1
  287. package/dist/utils/sleep.d.ts.map +1 -1
  288. package/dist/utils/sleep.js +10 -1
  289. package/dist/utils/sleep.js.map +1 -1
  290. package/package.json +1 -1
  291. package/prompts/analyst.md +2 -2
  292. package/prompts/api-reviewer.md +2 -2
  293. package/prompts/architect.md +2 -2
  294. package/prompts/build-fixer.md +2 -2
  295. package/prompts/code-reviewer.md +2 -2
  296. package/prompts/code-simplifier.md +1 -1
  297. package/prompts/critic.md +2 -2
  298. package/prompts/debugger.md +3 -2
  299. package/prompts/dependency-expert.md +2 -2
  300. package/prompts/designer.md +2 -2
  301. package/prompts/executor.md +3 -2
  302. package/prompts/explore.md +2 -2
  303. package/prompts/git-master.md +2 -2
  304. package/prompts/information-architect.md +2 -2
  305. package/prompts/performance-reviewer.md +2 -2
  306. package/prompts/planner.md +3 -2
  307. package/prompts/product-analyst.md +2 -2
  308. package/prompts/product-manager.md +2 -2
  309. package/prompts/qa-tester.md +2 -2
  310. package/prompts/quality-reviewer.md +2 -2
  311. package/prompts/quality-strategist.md +2 -2
  312. package/prompts/researcher.md +2 -2
  313. package/prompts/security-reviewer.md +2 -2
  314. package/prompts/sisyphus-lite.md +2 -2
  315. package/prompts/style-reviewer.md +2 -2
  316. package/prompts/team-executor.md +2 -2
  317. package/prompts/test-engineer.md +2 -2
  318. package/prompts/ux-researcher.md +2 -2
  319. package/prompts/verifier.md +3 -2
  320. package/prompts/vision.md +2 -2
  321. package/prompts/writer.md +2 -2
  322. package/skills/team/SKILL.md +18 -33
  323. package/src/scripts/__tests__/codex-native-hook.test.ts +931 -0
  324. package/src/scripts/codex-native-hook.ts +721 -0
  325. package/src/scripts/codex-native-pre-post.ts +161 -0
  326. package/src/scripts/notify-fallback-watcher.ts +318 -26
  327. package/src/scripts/notify-hook/auto-nudge.ts +5 -10
  328. package/src/scripts/notify-hook/log.ts +18 -4
  329. package/src/scripts/notify-hook/managed-tmux.ts +1 -0
  330. package/src/scripts/notify-hook/orchestration-intent.ts +82 -0
  331. package/src/scripts/notify-hook/process-runner.ts +4 -4
  332. package/src/scripts/notify-hook/ralph-session-resume.ts +9 -0
  333. package/src/scripts/notify-hook/team-dispatch.ts +134 -6
  334. package/src/scripts/notify-hook/team-leader-nudge.ts +183 -37
  335. package/src/scripts/notify-hook/team-tmux-guard.ts +35 -43
  336. package/src/scripts/notify-hook/team-worker.ts +73 -4
  337. package/src/scripts/notify-hook/utils.ts +1 -1
  338. package/src/scripts/notify-hook.ts +64 -32
  339. package/templates/AGENTS.md +21 -11
  340. package/README.de.md +0 -263
  341. package/README.el.md +0 -223
  342. package/README.es.md +0 -263
  343. package/README.fr.md +0 -263
  344. package/README.it.md +0 -263
  345. package/README.ja.md +0 -264
  346. package/README.ko.md +0 -264
  347. package/README.pl.md +0 -216
  348. package/README.pt.md +0 -263
  349. package/README.ru.md +0 -263
  350. package/README.tr.md +0 -263
  351. package/README.vi.md +0 -223
  352. package/README.zh-TW.md +0 -293
  353. package/README.zh.md +0 -264
  354. package/dist/mcp/__tests__/team-server-cleanup.test.d.ts +0 -2
  355. package/dist/mcp/__tests__/team-server-cleanup.test.d.ts.map +0 -1
  356. package/dist/mcp/__tests__/team-server-cleanup.test.js +0 -219
  357. package/dist/mcp/__tests__/team-server-cleanup.test.js.map +0 -1
  358. package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts +0 -2
  359. package/dist/mcp/__tests__/team-server-runtime-deps.test.d.ts.map +0 -1
  360. package/dist/mcp/__tests__/team-server-runtime-deps.test.js +0 -13
  361. package/dist/mcp/__tests__/team-server-runtime-deps.test.js.map +0 -1
  362. package/dist/mcp/__tests__/team-server-wait.test.d.ts +0 -2
  363. package/dist/mcp/__tests__/team-server-wait.test.d.ts.map +0 -1
  364. package/dist/mcp/__tests__/team-server-wait.test.js +0 -155
  365. package/dist/mcp/__tests__/team-server-wait.test.js.map +0 -1
  366. package/dist/mcp/team-server.d.ts +0 -24
  367. package/dist/mcp/team-server.d.ts.map +0 -1
  368. package/dist/mcp/team-server.js +0 -482
  369. package/dist/mcp/team-server.js.map +0 -1
@@ -0,0 +1,720 @@
1
+ import assert from "node:assert/strict";
2
+ import { execFileSync } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
5
+ import { tmpdir } from "node:os";
6
+ import { dirname, join } from "node:path";
7
+ import { describe, it } from "node:test";
8
+ import { buildManagedCodexHooksConfig } from "../../config/codex-hooks.js";
9
+ import { initTeamState } from "../../team/state.js";
10
+ import { dispatchCodexNativeHook, mapCodexHookEventToOmxEvent, resolveSessionOwnerPidFromAncestry, } from "../codex-native-hook.js";
11
+ async function writeJson(path, value) {
12
+ await mkdir(dirname(path), { recursive: true }).catch(() => { });
13
+ await writeFile(path, JSON.stringify(value, null, 2));
14
+ }
15
+ describe("codex native hook config", () => {
16
+ it("builds the expected managed hooks.json shape", () => {
17
+ const config = buildManagedCodexHooksConfig("/tmp/omx");
18
+ assert.deepEqual(Object.keys(config.hooks), [
19
+ "SessionStart",
20
+ "PreToolUse",
21
+ "PostToolUse",
22
+ "UserPromptSubmit",
23
+ "Stop",
24
+ ]);
25
+ const preToolUse = config.hooks.PreToolUse[0];
26
+ assert.equal(preToolUse.matcher, "Bash");
27
+ assert.match(String(preToolUse.hooks?.[0]?.command || ""), /codex-native-hook\.js"?$/);
28
+ const stop = config.hooks.Stop[0];
29
+ assert.equal(stop.hooks?.[0]?.timeout, 30);
30
+ });
31
+ });
32
+ describe("codex native hook dispatch", () => {
33
+ it("maps Codex events onto OMX logical surfaces", () => {
34
+ assert.equal(mapCodexHookEventToOmxEvent("SessionStart"), "session-start");
35
+ assert.equal(mapCodexHookEventToOmxEvent("UserPromptSubmit"), "keyword-detector");
36
+ assert.equal(mapCodexHookEventToOmxEvent("PreToolUse"), "pre-tool-use");
37
+ assert.equal(mapCodexHookEventToOmxEvent("PostToolUse"), "post-tool-use");
38
+ assert.equal(mapCodexHookEventToOmxEvent("Stop"), "stop");
39
+ });
40
+ it("writes SessionStart state against the long-lived session owner pid", async () => {
41
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-session-start-"));
42
+ try {
43
+ const result = await dispatchCodexNativeHook({
44
+ hook_event_name: "SessionStart",
45
+ cwd,
46
+ session_id: "sess-start-1",
47
+ }, {
48
+ cwd,
49
+ sessionOwnerPid: 43210,
50
+ });
51
+ assert.equal(result.omxEventName, "session-start");
52
+ assert.deepEqual(result.outputJson, {
53
+ hookSpecificOutput: {
54
+ hookEventName: "SessionStart",
55
+ additionalContext: "OMX native SessionStart detected. Load workspace conventions from AGENTS.md, restore relevant .omx runtime/project memory context, and continue from existing mode state before making changes.",
56
+ },
57
+ });
58
+ const sessionState = JSON.parse(await readFile(join(cwd, ".omx", "state", "session.json"), "utf-8"));
59
+ assert.equal(sessionState.session_id, "sess-start-1");
60
+ assert.equal(sessionState.pid, 43210);
61
+ }
62
+ finally {
63
+ await rm(cwd, { recursive: true, force: true });
64
+ }
65
+ });
66
+ it("appends .omx/ to repo-root .gitignore during SessionStart when missing", async () => {
67
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-session-gitignore-"));
68
+ try {
69
+ await writeFile(join(cwd, ".gitignore"), "node_modules/\n");
70
+ execFileSync("git", ["init"], { cwd, stdio: "pipe" });
71
+ const result = await dispatchCodexNativeHook({
72
+ hook_event_name: "SessionStart",
73
+ cwd,
74
+ session_id: "sess-gitignore-1",
75
+ }, { cwd, sessionOwnerPid: 43210 });
76
+ assert.equal(result.omxEventName, "session-start");
77
+ const gitignore = await readFile(join(cwd, ".gitignore"), "utf-8");
78
+ assert.match(gitignore, /^node_modules\/\n\.omx\/\n$/);
79
+ assert.match(JSON.stringify(result.outputJson), /Added \.omx\/ to .*\.gitignore/);
80
+ }
81
+ finally {
82
+ await rm(cwd, { recursive: true, force: true });
83
+ }
84
+ });
85
+ it("includes persisted project-memory summary in SessionStart context", async () => {
86
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-session-memory-"));
87
+ try {
88
+ await writeJson(join(cwd, ".omx", "project-memory.json"), {
89
+ techStack: "TypeScript + Node.js",
90
+ build: "npm test",
91
+ conventions: "small diffs, verify before claim",
92
+ directives: [
93
+ { directive: "Keep native Stop bounded to real continuation decisions.", priority: "high" },
94
+ ],
95
+ notes: [
96
+ { category: "env", content: "Requires LOCAL_API_BASE for smoke tests", timestamp: new Date().toISOString() },
97
+ ],
98
+ });
99
+ const result = await dispatchCodexNativeHook({
100
+ hook_event_name: "SessionStart",
101
+ cwd,
102
+ session_id: "sess-memory-1",
103
+ }, { cwd, sessionOwnerPid: 43210 });
104
+ const serialized = JSON.stringify(result.outputJson);
105
+ assert.match(serialized, /\[Project memory\]/);
106
+ assert.match(serialized, /TypeScript \+ Node\.js/);
107
+ assert.match(serialized, /small diffs, verify before claim/);
108
+ assert.match(serialized, /Keep native Stop bounded to real continuation decisions\./);
109
+ assert.match(serialized, /Requires LOCAL_API_BASE for smoke tests/);
110
+ }
111
+ finally {
112
+ await rm(cwd, { recursive: true, force: true });
113
+ }
114
+ });
115
+ it("resolves the Codex owner from ancestry without mistaking codex-native-hook wrappers for Codex", () => {
116
+ const commands = new Map([
117
+ [2100, 'sh -c node "/repo/dist/scripts/codex-native-hook.js"'],
118
+ [1100, 'node /usr/local/bin/codex.js'],
119
+ [900, 'bash'],
120
+ ]);
121
+ const parents = new Map([
122
+ [2100, 1100],
123
+ [1100, 900],
124
+ [900, 1],
125
+ ]);
126
+ const resolved = resolveSessionOwnerPidFromAncestry(2100, {
127
+ readParentPid: (pid) => parents.get(pid) ?? null,
128
+ readProcessCommand: (pid) => commands.get(pid) ?? "",
129
+ });
130
+ assert.equal(resolved, 1100);
131
+ });
132
+ it("records keyword activation from UserPromptSubmit payloads", async () => {
133
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-"));
134
+ try {
135
+ await mkdir(join(cwd, ".omx", "state"), { recursive: true });
136
+ const result = await dispatchCodexNativeHook({
137
+ hook_event_name: "UserPromptSubmit",
138
+ cwd,
139
+ session_id: "sess-1",
140
+ thread_id: "thread-1",
141
+ turn_id: "turn-1",
142
+ prompt: "$ralplan implement issue #1307",
143
+ }, { cwd });
144
+ assert.equal(result.omxEventName, "keyword-detector");
145
+ assert.equal(result.skillState?.skill, "ralplan");
146
+ assert.ok(result.outputJson, "UserPromptSubmit should emit developer context");
147
+ const statePath = join(cwd, ".omx", "state", "skill-active-state.json");
148
+ assert.equal(existsSync(statePath), true);
149
+ const state = JSON.parse(await readFile(statePath, "utf-8"));
150
+ assert.equal(state.skill, "ralplan");
151
+ assert.equal(state.active, true);
152
+ }
153
+ finally {
154
+ await rm(cwd, { recursive: true, force: true });
155
+ }
156
+ });
157
+ it("returns a destructive-command caution on PreToolUse for rm -rf dist", async () => {
158
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-pretool-danger-"));
159
+ try {
160
+ const result = await dispatchCodexNativeHook({
161
+ hook_event_name: "PreToolUse",
162
+ cwd,
163
+ tool_name: "Bash",
164
+ tool_use_id: "tool-danger",
165
+ tool_input: { command: "rm -rf dist" },
166
+ }, { cwd });
167
+ assert.equal(result.omxEventName, "pre-tool-use");
168
+ assert.deepEqual(result.outputJson, {
169
+ hookSpecificOutput: {
170
+ hookEventName: "PreToolUse",
171
+ },
172
+ systemMessage: "Destructive Bash command detected (`rm -rf dist`). Confirm the target and expected side effects before running it.",
173
+ });
174
+ }
175
+ finally {
176
+ await rm(cwd, { recursive: true, force: true });
177
+ }
178
+ });
179
+ it("stays silent on PreToolUse for neutral pwd", async () => {
180
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-pretool-neutral-"));
181
+ try {
182
+ const result = await dispatchCodexNativeHook({
183
+ hook_event_name: "PreToolUse",
184
+ cwd,
185
+ tool_name: "Bash",
186
+ tool_use_id: "tool-neutral",
187
+ tool_input: { command: "pwd" },
188
+ }, { cwd });
189
+ assert.equal(result.omxEventName, "pre-tool-use");
190
+ assert.equal(result.outputJson, null);
191
+ }
192
+ finally {
193
+ await rm(cwd, { recursive: true, force: true });
194
+ }
195
+ });
196
+ it("returns PostToolUse remediation guidance for command-not-found output", async () => {
197
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-failure-"));
198
+ try {
199
+ const result = await dispatchCodexNativeHook({
200
+ hook_event_name: "PostToolUse",
201
+ cwd,
202
+ tool_name: "Bash",
203
+ tool_use_id: "tool-fail",
204
+ tool_input: { command: "foo --version" },
205
+ tool_response: "{\"exit_code\":127,\"stdout\":\"\",\"stderr\":\"bash: foo: command not found\"}",
206
+ }, { cwd });
207
+ assert.equal(result.omxEventName, "post-tool-use");
208
+ assert.deepEqual(result.outputJson, {
209
+ decision: "block",
210
+ reason: "The Bash output indicates a command/setup failure that should be fixed before retrying.",
211
+ hookSpecificOutput: {
212
+ hookEventName: "PostToolUse",
213
+ additionalContext: "Bash reported `command not found`, `permission denied`, or a missing file/path. Verify the command, dependency installation, PATH, file permissions, and referenced paths before retrying.",
214
+ },
215
+ });
216
+ }
217
+ finally {
218
+ await rm(cwd, { recursive: true, force: true });
219
+ }
220
+ });
221
+ it("treats stderr-only informative non-zero output as reviewable instead of a generic failure", async () => {
222
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-informative-stderr-"));
223
+ try {
224
+ const result = await dispatchCodexNativeHook({
225
+ hook_event_name: "PostToolUse",
226
+ cwd,
227
+ tool_name: "Bash",
228
+ tool_use_id: "tool-useful-stderr",
229
+ tool_input: { command: "gh pr checks" },
230
+ tool_response: "{\"exit_code\":8,\"stdout\":\"\",\"stderr\":\"build pending\\nlint pass\"}",
231
+ }, { cwd });
232
+ assert.equal(result.omxEventName, "post-tool-use");
233
+ assert.deepEqual(result.outputJson, {
234
+ decision: "block",
235
+ reason: "The Bash command returned a non-zero exit code but produced useful output that should be reviewed before retrying.",
236
+ hookSpecificOutput: {
237
+ hookEventName: "PostToolUse",
238
+ additionalContext: "The Bash output appears informative despite the non-zero exit code. Review and report the output before retrying instead of assuming the command simply failed.",
239
+ },
240
+ });
241
+ }
242
+ finally {
243
+ await rm(cwd, { recursive: true, force: true });
244
+ }
245
+ });
246
+ it("treats non-zero gh pr checks style output as informative instead of a generic failure", async () => {
247
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-informative-"));
248
+ try {
249
+ const result = await dispatchCodexNativeHook({
250
+ hook_event_name: "PostToolUse",
251
+ cwd,
252
+ tool_name: "Bash",
253
+ tool_use_id: "tool-useful",
254
+ tool_input: { command: "gh pr checks" },
255
+ tool_response: "{\"exit_code\":8,\"stdout\":\"build\\tpending\\t2m\\nlint\\tpass\\t18s\",\"stderr\":\"\"}",
256
+ }, { cwd });
257
+ assert.equal(result.omxEventName, "post-tool-use");
258
+ assert.deepEqual(result.outputJson, {
259
+ decision: "block",
260
+ reason: "The Bash command returned a non-zero exit code but produced useful output that should be reviewed before retrying.",
261
+ hookSpecificOutput: {
262
+ hookEventName: "PostToolUse",
263
+ additionalContext: "The Bash output appears informative despite the non-zero exit code. Review and report the output before retrying instead of assuming the command simply failed.",
264
+ },
265
+ });
266
+ }
267
+ finally {
268
+ await rm(cwd, { recursive: true, force: true });
269
+ }
270
+ });
271
+ it("stays silent on neutral successful PostToolUse output", async () => {
272
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-posttool-neutral-"));
273
+ try {
274
+ const result = await dispatchCodexNativeHook({
275
+ hook_event_name: "PostToolUse",
276
+ cwd,
277
+ tool_name: "Bash",
278
+ tool_use_id: "tool-ok",
279
+ tool_input: { command: "pwd" },
280
+ tool_response: "{\"exit_code\":0,\"stdout\":\"/repo\",\"stderr\":\"\"}",
281
+ }, { cwd });
282
+ assert.equal(result.omxEventName, "post-tool-use");
283
+ assert.equal(result.outputJson, null);
284
+ }
285
+ finally {
286
+ await rm(cwd, { recursive: true, force: true });
287
+ }
288
+ });
289
+ it("returns Stop continuation output while Autopilot is active", async () => {
290
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-autopilot-"));
291
+ try {
292
+ const stateDir = join(cwd, ".omx", "state");
293
+ await mkdir(stateDir, { recursive: true });
294
+ await writeJson(join(stateDir, "autopilot-state.json"), {
295
+ active: true,
296
+ current_phase: "execution",
297
+ });
298
+ const result = await dispatchCodexNativeHook({
299
+ hook_event_name: "Stop",
300
+ cwd,
301
+ session_id: "sess-stop-autopilot",
302
+ }, { cwd });
303
+ assert.equal(result.omxEventName, "stop");
304
+ assert.deepEqual(result.outputJson, {
305
+ decision: "block",
306
+ reason: "OMX autopilot is still active (phase: execution); continue the task and gather fresh verification evidence before stopping.",
307
+ stopReason: "autopilot_execution",
308
+ systemMessage: "OMX autopilot is still active (phase: execution).",
309
+ });
310
+ }
311
+ finally {
312
+ await rm(cwd, { recursive: true, force: true });
313
+ }
314
+ });
315
+ it("returns Stop continuation output while Ultrawork is active", async () => {
316
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-ultrawork-"));
317
+ try {
318
+ const stateDir = join(cwd, ".omx", "state");
319
+ await mkdir(stateDir, { recursive: true });
320
+ await writeJson(join(stateDir, "ultrawork-state.json"), {
321
+ active: true,
322
+ current_phase: "executing",
323
+ });
324
+ const result = await dispatchCodexNativeHook({ hook_event_name: "Stop", cwd, session_id: "sess-stop-ultrawork" }, { cwd });
325
+ assert.deepEqual(result.outputJson, {
326
+ decision: "block",
327
+ reason: "OMX ultrawork is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
328
+ stopReason: "ultrawork_executing",
329
+ systemMessage: "OMX ultrawork is still active (phase: executing).",
330
+ });
331
+ }
332
+ finally {
333
+ await rm(cwd, { recursive: true, force: true });
334
+ }
335
+ });
336
+ it("returns Stop continuation output while UltraQA is active", async () => {
337
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-ultraqa-"));
338
+ try {
339
+ const stateDir = join(cwd, ".omx", "state");
340
+ await mkdir(stateDir, { recursive: true });
341
+ await writeJson(join(stateDir, "ultraqa-state.json"), {
342
+ active: true,
343
+ current_phase: "diagnose",
344
+ });
345
+ const result = await dispatchCodexNativeHook({ hook_event_name: "Stop", cwd, session_id: "sess-stop-ultraqa" }, { cwd });
346
+ assert.deepEqual(result.outputJson, {
347
+ decision: "block",
348
+ reason: "OMX ultraqa is still active (phase: diagnose); continue the task and gather fresh verification evidence before stopping.",
349
+ stopReason: "ultraqa_diagnose",
350
+ systemMessage: "OMX ultraqa is still active (phase: diagnose).",
351
+ });
352
+ }
353
+ finally {
354
+ await rm(cwd, { recursive: true, force: true });
355
+ }
356
+ });
357
+ it("returns Stop continuation output while team phase is non-terminal", async () => {
358
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-"));
359
+ try {
360
+ const stateDir = join(cwd, ".omx", "state");
361
+ await mkdir(stateDir, { recursive: true });
362
+ await writeJson(join(stateDir, "team-state.json"), {
363
+ active: true,
364
+ current_phase: "team-exec",
365
+ team_name: "review-team",
366
+ });
367
+ await writeJson(join(stateDir, "team", "review-team", "phase.json"), {
368
+ current_phase: "team-verify",
369
+ max_fix_attempts: 3,
370
+ current_fix_attempt: 0,
371
+ transitions: [],
372
+ updated_at: new Date().toISOString(),
373
+ });
374
+ const result = await dispatchCodexNativeHook({
375
+ hook_event_name: "Stop",
376
+ cwd,
377
+ session_id: "sess-stop-team",
378
+ }, { cwd });
379
+ assert.equal(result.omxEventName, "stop");
380
+ assert.deepEqual(result.outputJson, {
381
+ decision: "block",
382
+ reason: "OMX team pipeline is still active (review-team) at phase team-verify; continue coordinating until the team reaches a terminal phase.",
383
+ stopReason: "team_team-verify",
384
+ systemMessage: "OMX team pipeline is still active at phase team-verify.",
385
+ });
386
+ }
387
+ finally {
388
+ await rm(cwd, { recursive: true, force: true });
389
+ }
390
+ });
391
+ it("returns Stop continuation output from canonical team state when coarse mode state is missing", async () => {
392
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-canonical-"));
393
+ try {
394
+ await initTeamState("canonical-team", "canonical stop fallback", "executor", 1, cwd, undefined, { ...process.env, OMX_SESSION_ID: "sess-stop-team-canonical" });
395
+ const result = await dispatchCodexNativeHook({
396
+ hook_event_name: "Stop",
397
+ cwd,
398
+ session_id: "sess-stop-team-canonical",
399
+ }, { cwd });
400
+ assert.equal(result.omxEventName, "stop");
401
+ assert.deepEqual(result.outputJson, {
402
+ decision: "block",
403
+ reason: "OMX team pipeline is still active (canonical-team) at phase team-exec; continue coordinating until the team reaches a terminal phase.",
404
+ stopReason: "team_team-exec",
405
+ systemMessage: "OMX team pipeline is still active at phase team-exec.",
406
+ });
407
+ }
408
+ finally {
409
+ await rm(cwd, { recursive: true, force: true });
410
+ }
411
+ });
412
+ it("does not block Stop from canonical team state alone when the canonical phase is terminal", async () => {
413
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-terminal-"));
414
+ try {
415
+ await initTeamState("terminal-team", "terminal stop fallback", "executor", 1, cwd, undefined, { ...process.env, OMX_SESSION_ID: "sess-stop-team-terminal" });
416
+ await writeJson(join(cwd, ".omx", "state", "team", "terminal-team", "phase.json"), {
417
+ current_phase: "complete",
418
+ max_fix_attempts: 3,
419
+ current_fix_attempt: 0,
420
+ transitions: [],
421
+ updated_at: new Date().toISOString(),
422
+ });
423
+ const result = await dispatchCodexNativeHook({
424
+ hook_event_name: "Stop",
425
+ cwd,
426
+ session_id: "sess-stop-team-terminal",
427
+ }, { cwd });
428
+ assert.equal(result.omxEventName, "stop");
429
+ assert.equal(result.outputJson, null);
430
+ }
431
+ finally {
432
+ await rm(cwd, { recursive: true, force: true });
433
+ }
434
+ });
435
+ it("returns Stop continuation output from canonical team state when manifest session ownership is missing", async () => {
436
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-legacy-"));
437
+ try {
438
+ await initTeamState("legacy-team", "legacy stop fallback", "executor", 1, cwd, undefined, { ...process.env, OMX_SESSION_ID: "sess-stop-team-legacy" });
439
+ const manifestPath = join(cwd, ".omx", "state", "team", "legacy-team", "manifest.v2.json");
440
+ const manifest = JSON.parse(await readFile(manifestPath, "utf-8"));
441
+ await writeJson(manifestPath, {
442
+ ...manifest,
443
+ leader: {
444
+ ...manifest.leader,
445
+ session_id: "",
446
+ },
447
+ });
448
+ const result = await dispatchCodexNativeHook({
449
+ hook_event_name: "Stop",
450
+ cwd,
451
+ session_id: "sess-stop-team-legacy",
452
+ }, { cwd });
453
+ assert.equal(result.omxEventName, "stop");
454
+ assert.deepEqual(result.outputJson, {
455
+ decision: "block",
456
+ reason: "OMX team pipeline is still active (legacy-team) at phase team-exec; continue coordinating until the team reaches a terminal phase.",
457
+ stopReason: "team_team-exec",
458
+ systemMessage: "OMX team pipeline is still active at phase team-exec.",
459
+ });
460
+ }
461
+ finally {
462
+ await rm(cwd, { recursive: true, force: true });
463
+ }
464
+ });
465
+ it("reads canonical Stop fallback team state from OMX_TEAM_STATE_ROOT when configured", async () => {
466
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-root-"));
467
+ const sharedRoot = join(cwd, "shared-root");
468
+ const priorTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
469
+ try {
470
+ process.env.OMX_TEAM_STATE_ROOT = "shared-root";
471
+ await initTeamState("canonical-root-team", "canonical stop root fallback", "executor", 1, cwd, undefined, { ...process.env, OMX_SESSION_ID: "sess-stop-team-root", OMX_TEAM_STATE_ROOT: "shared-root" });
472
+ const result = await dispatchCodexNativeHook({
473
+ hook_event_name: "Stop",
474
+ cwd,
475
+ session_id: "sess-stop-team-root",
476
+ }, { cwd });
477
+ assert.equal(result.omxEventName, "stop");
478
+ assert.deepEqual(result.outputJson, {
479
+ decision: "block",
480
+ reason: "OMX team pipeline is still active (canonical-root-team) at phase team-exec; continue coordinating until the team reaches a terminal phase.",
481
+ stopReason: "team_team-exec",
482
+ systemMessage: "OMX team pipeline is still active at phase team-exec.",
483
+ });
484
+ assert.equal(existsSync(join(sharedRoot, "team", "canonical-root-team", "phase.json")), true);
485
+ }
486
+ finally {
487
+ if (typeof priorTeamStateRoot === "string")
488
+ process.env.OMX_TEAM_STATE_ROOT = priorTeamStateRoot;
489
+ else
490
+ delete process.env.OMX_TEAM_STATE_ROOT;
491
+ await rm(cwd, { recursive: true, force: true });
492
+ }
493
+ });
494
+ it("returns Stop continuation output from canonical team state rooted via OMX_TEAM_STATE_ROOT", async () => {
495
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-team-env-root-"));
496
+ const previousTeamStateRoot = process.env.OMX_TEAM_STATE_ROOT;
497
+ try {
498
+ process.env.OMX_TEAM_STATE_ROOT = "shared-team-state";
499
+ await initTeamState("env-root-team", "env root stop fallback", "executor", 1, cwd, undefined, {
500
+ ...process.env,
501
+ OMX_SESSION_ID: "sess-stop-team-env-root",
502
+ OMX_TEAM_STATE_ROOT: "shared-team-state",
503
+ });
504
+ const result = await dispatchCodexNativeHook({
505
+ hook_event_name: "Stop",
506
+ cwd,
507
+ session_id: "sess-stop-team-env-root",
508
+ }, { cwd });
509
+ assert.equal(result.omxEventName, "stop");
510
+ assert.deepEqual(result.outputJson, {
511
+ decision: "block",
512
+ reason: "OMX team pipeline is still active (env-root-team) at phase team-exec; continue coordinating until the team reaches a terminal phase.",
513
+ stopReason: "team_team-exec",
514
+ systemMessage: "OMX team pipeline is still active at phase team-exec.",
515
+ });
516
+ }
517
+ finally {
518
+ if (typeof previousTeamStateRoot === "string")
519
+ process.env.OMX_TEAM_STATE_ROOT = previousTeamStateRoot;
520
+ else
521
+ delete process.env.OMX_TEAM_STATE_ROOT;
522
+ await rm(cwd, { recursive: true, force: true });
523
+ }
524
+ });
525
+ it("returns Stop continuation output for active ralplan skill without active subagents", async () => {
526
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-skill-"));
527
+ try {
528
+ const stateDir = join(cwd, ".omx", "state");
529
+ await mkdir(join(stateDir, "sessions", "sess-stop-skill"), { recursive: true });
530
+ await writeJson(join(stateDir, "session.json"), { session_id: "sess-stop-skill" });
531
+ await writeJson(join(stateDir, "sessions", "sess-stop-skill", "skill-active-state.json"), {
532
+ active: true,
533
+ skill: "ralplan",
534
+ phase: "planning",
535
+ });
536
+ const result = await dispatchCodexNativeHook({
537
+ hook_event_name: "Stop",
538
+ cwd,
539
+ session_id: "sess-stop-skill",
540
+ }, { cwd });
541
+ assert.equal(result.omxEventName, "stop");
542
+ assert.deepEqual(result.outputJson, {
543
+ decision: "block",
544
+ reason: "OMX skill ralplan is still active (phase: planning); continue until the current ralplan workflow reaches a terminal state.",
545
+ stopReason: "skill_ralplan_planning",
546
+ systemMessage: "OMX skill ralplan is still active (phase: planning).",
547
+ });
548
+ }
549
+ finally {
550
+ await rm(cwd, { recursive: true, force: true });
551
+ }
552
+ });
553
+ it("does not block on active ralplan skill when subagents are still active", async () => {
554
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-skill-subagent-"));
555
+ try {
556
+ const stateDir = join(cwd, ".omx", "state");
557
+ await mkdir(join(stateDir, "sessions", "sess-stop-skill-subagent"), { recursive: true });
558
+ await writeJson(join(stateDir, "session.json"), { session_id: "sess-stop-skill-subagent" });
559
+ await writeJson(join(stateDir, "sessions", "sess-stop-skill-subagent", "skill-active-state.json"), {
560
+ active: true,
561
+ skill: "ralplan",
562
+ phase: "planning",
563
+ });
564
+ await writeJson(join(stateDir, "subagent-tracking.json"), {
565
+ schemaVersion: 1,
566
+ sessions: {
567
+ "sess-stop-skill-subagent": {
568
+ session_id: "sess-stop-skill-subagent",
569
+ leader_thread_id: "leader-1",
570
+ updated_at: new Date().toISOString(),
571
+ threads: {
572
+ "leader-1": {
573
+ thread_id: "leader-1",
574
+ kind: "leader",
575
+ first_seen_at: new Date().toISOString(),
576
+ last_seen_at: new Date().toISOString(),
577
+ turn_count: 1,
578
+ },
579
+ "sub-1": {
580
+ thread_id: "sub-1",
581
+ kind: "subagent",
582
+ first_seen_at: new Date().toISOString(),
583
+ last_seen_at: new Date().toISOString(),
584
+ turn_count: 1,
585
+ },
586
+ },
587
+ },
588
+ },
589
+ });
590
+ const result = await dispatchCodexNativeHook({
591
+ hook_event_name: "Stop",
592
+ cwd,
593
+ session_id: "sess-stop-skill-subagent",
594
+ }, { cwd });
595
+ assert.equal(result.omxEventName, "stop");
596
+ assert.equal(result.outputJson, null);
597
+ }
598
+ finally {
599
+ await rm(cwd, { recursive: true, force: true });
600
+ }
601
+ });
602
+ it("returns Stop continuation output for active deep-interview skill without active subagents", async () => {
603
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-deep-interview-"));
604
+ try {
605
+ const stateDir = join(cwd, ".omx", "state");
606
+ await mkdir(join(stateDir, "sessions", "sess-stop-deep-interview"), { recursive: true });
607
+ await writeJson(join(stateDir, "session.json"), { session_id: "sess-stop-deep-interview" });
608
+ await writeJson(join(stateDir, "sessions", "sess-stop-deep-interview", "skill-active-state.json"), {
609
+ active: true,
610
+ skill: "deep-interview",
611
+ phase: "planning",
612
+ });
613
+ const result = await dispatchCodexNativeHook({
614
+ hook_event_name: "Stop",
615
+ cwd,
616
+ session_id: "sess-stop-deep-interview",
617
+ }, { cwd });
618
+ assert.deepEqual(result.outputJson, {
619
+ decision: "block",
620
+ reason: "OMX skill deep-interview is still active (phase: planning); continue until the current deep-interview workflow reaches a terminal state.",
621
+ stopReason: "skill_deep-interview_planning",
622
+ systemMessage: "OMX skill deep-interview is still active (phase: planning).",
623
+ });
624
+ }
625
+ finally {
626
+ await rm(cwd, { recursive: true, force: true });
627
+ }
628
+ });
629
+ it("returns Stop continuation output while Ralph is active", async () => {
630
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-"));
631
+ try {
632
+ const stateDir = join(cwd, ".omx", "state");
633
+ await mkdir(stateDir, { recursive: true });
634
+ await writeFile(join(stateDir, "ralph-state.json"), JSON.stringify({
635
+ active: true,
636
+ current_phase: "executing",
637
+ }));
638
+ const result = await dispatchCodexNativeHook({
639
+ hook_event_name: "Stop",
640
+ cwd,
641
+ session_id: "sess-stop",
642
+ }, { cwd });
643
+ assert.equal(result.omxEventName, "stop");
644
+ assert.deepEqual(result.outputJson, {
645
+ decision: "block",
646
+ reason: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
647
+ stopReason: "ralph_executing",
648
+ systemMessage: "OMX Ralph is still active (phase: executing); continue the task and gather fresh verification evidence before stopping.",
649
+ });
650
+ }
651
+ finally {
652
+ await rm(cwd, { recursive: true, force: true });
653
+ }
654
+ });
655
+ it("does not re-block Ralph when Stop already continued once", async () => {
656
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-stop-ralph-once-"));
657
+ try {
658
+ const stateDir = join(cwd, ".omx", "state");
659
+ await mkdir(stateDir, { recursive: true });
660
+ await writeFile(join(stateDir, "ralph-state.json"), JSON.stringify({
661
+ active: true,
662
+ current_phase: "executing",
663
+ }));
664
+ const result = await dispatchCodexNativeHook({
665
+ hook_event_name: "Stop",
666
+ cwd,
667
+ session_id: "sess-stop-ralph-once",
668
+ stop_hook_active: true,
669
+ }, { cwd });
670
+ assert.equal(result.omxEventName, "stop");
671
+ assert.equal(result.outputJson, null);
672
+ }
673
+ finally {
674
+ await rm(cwd, { recursive: true, force: true });
675
+ }
676
+ });
677
+ it("returns Stop continuation output for native auto-nudge stall prompts", async () => {
678
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-auto-nudge-"));
679
+ try {
680
+ const stateDir = join(cwd, ".omx", "state");
681
+ await mkdir(stateDir, { recursive: true });
682
+ const result = await dispatchCodexNativeHook({
683
+ hook_event_name: "Stop",
684
+ cwd,
685
+ session_id: "sess-stop-auto",
686
+ last_assistant_message: "Would you like me to keep going and finish the cleanup?",
687
+ }, { cwd });
688
+ assert.equal(result.omxEventName, "stop");
689
+ assert.deepEqual(result.outputJson, {
690
+ decision: "block",
691
+ reason: "yes, proceed",
692
+ stopReason: "auto_nudge",
693
+ systemMessage: "OMX native Stop detected a stall/permission-style handoff and continued the turn automatically.",
694
+ });
695
+ }
696
+ finally {
697
+ await rm(cwd, { recursive: true, force: true });
698
+ }
699
+ });
700
+ it("does not auto-nudge again when Stop already continued once", async () => {
701
+ const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-auto-nudge-once-"));
702
+ try {
703
+ const stateDir = join(cwd, ".omx", "state");
704
+ await mkdir(stateDir, { recursive: true });
705
+ const result = await dispatchCodexNativeHook({
706
+ hook_event_name: "Stop",
707
+ cwd,
708
+ session_id: "sess-stop-auto-once",
709
+ stop_hook_active: true,
710
+ last_assistant_message: "Would you like me to continue?",
711
+ }, { cwd });
712
+ assert.equal(result.omxEventName, "stop");
713
+ assert.equal(result.outputJson, null);
714
+ }
715
+ finally {
716
+ await rm(cwd, { recursive: true, force: true });
717
+ }
718
+ });
719
+ });
720
+ //# sourceMappingURL=codex-native-hook.test.js.map