oh-my-codex 0.20.2 → 0.20.3

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 (367) hide show
  1. package/Cargo.lock +7 -6
  2. package/Cargo.toml +1 -1
  3. package/README.md +26 -0
  4. package/crates/omx-runtime/Cargo.toml +1 -0
  5. package/crates/omx-runtime/src/main.rs +25 -2
  6. package/crates/omx-runtime/tests/execution.rs +219 -0
  7. package/crates/omx-runtime-core/src/dispatch.rs +96 -10
  8. package/crates/omx-runtime-core/src/engine.rs +839 -29
  9. package/crates/omx-runtime-core/src/lib.rs +8 -0
  10. package/dist/agents/__tests__/definitions.test.js +81 -0
  11. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  12. package/dist/agents/__tests__/native-config.test.js +25 -0
  13. package/dist/agents/__tests__/native-config.test.js.map +1 -1
  14. package/dist/agents/native-config.d.ts +2 -1
  15. package/dist/agents/native-config.d.ts.map +1 -1
  16. package/dist/agents/native-config.js.map +1 -1
  17. package/dist/auth/hotswap.d.ts +6 -0
  18. package/dist/auth/hotswap.d.ts.map +1 -1
  19. package/dist/auth/hotswap.js +85 -15
  20. package/dist/auth/hotswap.js.map +1 -1
  21. package/dist/autopilot/__tests__/ralplan-gate.test.js +1 -1
  22. package/dist/autopilot/__tests__/ralplan-gate.test.js.map +1 -1
  23. package/dist/cli/__tests__/auth.test.js +60 -6
  24. package/dist/cli/__tests__/auth.test.js.map +1 -1
  25. package/dist/cli/__tests__/codex-plugin-layout.test.js +80 -0
  26. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  27. package/dist/cli/__tests__/doctor-warning-copy.test.js +103 -1
  28. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  29. package/dist/cli/__tests__/exec.test.js +136 -0
  30. package/dist/cli/__tests__/exec.test.js.map +1 -1
  31. package/dist/cli/__tests__/index.test.js +258 -4
  32. package/dist/cli/__tests__/index.test.js.map +1 -1
  33. package/dist/cli/__tests__/launch-fallback.test.js +287 -1
  34. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  35. package/dist/cli/__tests__/mcp-parity.test.js +4 -1
  36. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  37. package/dist/cli/__tests__/native-hook-claim-journal.test.js +84 -6
  38. package/dist/cli/__tests__/native-hook-claim-journal.test.js.map +1 -1
  39. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +3 -3
  40. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  41. package/dist/cli/__tests__/ralph.test.js +3 -3
  42. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  43. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js +56 -171
  44. package/dist/cli/__tests__/ralplan-bootstrap-3181.test.js.map +1 -1
  45. package/dist/cli/__tests__/ralplan.test.js +37 -111
  46. package/dist/cli/__tests__/ralplan.test.js.map +1 -1
  47. package/dist/cli/__tests__/resume.test.js +11 -10
  48. package/dist/cli/__tests__/resume.test.js.map +1 -1
  49. package/dist/cli/__tests__/session-search-help.test.js +25 -1
  50. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  51. package/dist/cli/__tests__/setup-install-mode.test.js +42 -4
  52. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  53. package/dist/cli/__tests__/team.test.js +105 -7
  54. package/dist/cli/__tests__/team.test.js.map +1 -1
  55. package/dist/cli/__tests__/uninstall.test.js +46 -0
  56. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  57. package/dist/cli/__tests__/windows-popup-loop-contract.test.js +2 -1
  58. package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -1
  59. package/dist/cli/doctor.d.ts +3 -0
  60. package/dist/cli/doctor.d.ts.map +1 -1
  61. package/dist/cli/doctor.js +15 -2
  62. package/dist/cli/doctor.js.map +1 -1
  63. package/dist/cli/index.d.ts +4 -1
  64. package/dist/cli/index.d.ts.map +1 -1
  65. package/dist/cli/index.js +138 -38
  66. package/dist/cli/index.js.map +1 -1
  67. package/dist/cli/mcp-parity.js +2 -2
  68. package/dist/cli/mcp-parity.js.map +1 -1
  69. package/dist/cli/native-hook-claim-journal.d.ts +16 -5
  70. package/dist/cli/native-hook-claim-journal.d.ts.map +1 -1
  71. package/dist/cli/native-hook-claim-journal.js +42 -29
  72. package/dist/cli/native-hook-claim-journal.js.map +1 -1
  73. package/dist/cli/ralph.js +2 -2
  74. package/dist/cli/ralph.js.map +1 -1
  75. package/dist/cli/ralplan.d.ts +4 -8
  76. package/dist/cli/ralplan.d.ts.map +1 -1
  77. package/dist/cli/ralplan.js +19 -112
  78. package/dist/cli/ralplan.js.map +1 -1
  79. package/dist/cli/session-search.d.ts +5 -0
  80. package/dist/cli/session-search.d.ts.map +1 -1
  81. package/dist/cli/session-search.js +87 -0
  82. package/dist/cli/session-search.js.map +1 -1
  83. package/dist/cli/setup.d.ts +5 -0
  84. package/dist/cli/setup.d.ts.map +1 -1
  85. package/dist/cli/setup.js +80 -31
  86. package/dist/cli/setup.js.map +1 -1
  87. package/dist/cli/uninstall.d.ts +9 -0
  88. package/dist/cli/uninstall.d.ts.map +1 -1
  89. package/dist/cli/uninstall.js +61 -19
  90. package/dist/cli/uninstall.js.map +1 -1
  91. package/dist/compat/__tests__/rust-runtime-compat.test.js +1 -1
  92. package/dist/config/__tests__/generator-idempotent.test.js +330 -1
  93. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  94. package/dist/config/__tests__/generator-notify.test.js +2 -2
  95. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  96. package/dist/config/__tests__/models.test.js +67 -3
  97. package/dist/config/__tests__/models.test.js.map +1 -1
  98. package/dist/config/generator.d.ts +4 -20
  99. package/dist/config/generator.d.ts.map +1 -1
  100. package/dist/config/generator.js +499 -119
  101. package/dist/config/generator.js.map +1 -1
  102. package/dist/config/models.d.ts +12 -2
  103. package/dist/config/models.d.ts.map +1 -1
  104. package/dist/config/models.js +15 -1
  105. package/dist/config/models.js.map +1 -1
  106. package/dist/hooks/__tests__/agents-overlay.test.js +2 -2
  107. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  108. package/dist/hooks/__tests__/keyword-detector.test.js +4 -4
  109. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  110. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +238 -543
  111. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  112. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +38 -4
  113. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  114. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +96 -9
  115. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  116. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +531 -12
  117. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  118. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +155 -23
  119. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  120. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js +482 -32
  121. package/dist/hooks/__tests__/notify-hook-team-tmux-guard.test.js.map +1 -1
  122. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +68 -1
  123. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  124. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +7 -1
  125. package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
  126. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +43 -4
  127. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  128. package/dist/hooks/__tests__/session.test.js +348 -2
  129. package/dist/hooks/__tests__/session.test.js.map +1 -1
  130. package/dist/hooks/agents-overlay.js +1 -1
  131. package/dist/hooks/session.d.ts +26 -2
  132. package/dist/hooks/session.d.ts.map +1 -1
  133. package/dist/hooks/session.js +169 -13
  134. package/dist/hooks/session.js.map +1 -1
  135. package/dist/leader/__tests__/contract.test.js +57 -7
  136. package/dist/leader/__tests__/contract.test.js.map +1 -1
  137. package/dist/leader/contract.d.ts +16 -0
  138. package/dist/leader/contract.d.ts.map +1 -1
  139. package/dist/leader/contract.js +79 -4
  140. package/dist/leader/contract.js.map +1 -1
  141. package/dist/mcp/__tests__/code-intel-server.test.js +31 -3
  142. package/dist/mcp/__tests__/code-intel-server.test.js.map +1 -1
  143. package/dist/mcp/__tests__/wiki-server.test.js +18 -0
  144. package/dist/mcp/__tests__/wiki-server.test.js.map +1 -1
  145. package/dist/mcp/code-intel-server.d.ts.map +1 -1
  146. package/dist/mcp/code-intel-server.js +13 -3
  147. package/dist/mcp/code-intel-server.js.map +1 -1
  148. package/dist/mcp/wiki-server.d.ts +11 -0
  149. package/dist/mcp/wiki-server.d.ts.map +1 -1
  150. package/dist/mcp/wiki-server.js +9 -2
  151. package/dist/mcp/wiki-server.js.map +1 -1
  152. package/dist/modes/__tests__/base-tmux-pane.test.js +4 -4
  153. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  154. package/dist/notifications/temp-contract.d.ts.map +1 -1
  155. package/dist/notifications/temp-contract.js +4 -0
  156. package/dist/notifications/temp-contract.js.map +1 -1
  157. package/dist/pipeline/__tests__/orchestrator.test.js +4 -4
  158. package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -1
  159. package/dist/pipeline/__tests__/stages.test.js +8 -8
  160. package/dist/pipeline/__tests__/stages.test.js.map +1 -1
  161. package/dist/ralplan/__tests__/consensus-gate.test.js +134 -10
  162. package/dist/ralplan/__tests__/consensus-gate.test.js.map +1 -1
  163. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts +2 -0
  164. package/dist/ralplan/__tests__/documented-leader-preflight.test.d.ts.map +1 -0
  165. package/dist/ralplan/__tests__/documented-leader-preflight.test.js +46 -0
  166. package/dist/ralplan/__tests__/documented-leader-preflight.test.js.map +1 -0
  167. package/dist/ralplan/__tests__/runtime.test.js +8 -4
  168. package/dist/ralplan/__tests__/runtime.test.js.map +1 -1
  169. package/dist/ralplan/consensus-gate.d.ts.map +1 -1
  170. package/dist/ralplan/consensus-gate.js +58 -50
  171. package/dist/ralplan/consensus-gate.js.map +1 -1
  172. package/dist/ralplan/documented-leader-preflight.d.ts +34 -0
  173. package/dist/ralplan/documented-leader-preflight.d.ts.map +1 -0
  174. package/dist/ralplan/documented-leader-preflight.js +58 -0
  175. package/dist/ralplan/documented-leader-preflight.js.map +1 -0
  176. package/dist/ralplan/runtime.d.ts +1 -0
  177. package/dist/ralplan/runtime.d.ts.map +1 -1
  178. package/dist/ralplan/runtime.js +11 -7
  179. package/dist/ralplan/runtime.js.map +1 -1
  180. package/dist/runtime/__tests__/bridge.test.js +42 -1
  181. package/dist/runtime/__tests__/bridge.test.js.map +1 -1
  182. package/dist/runtime/bridge.d.ts +12 -0
  183. package/dist/runtime/bridge.d.ts.map +1 -1
  184. package/dist/runtime/bridge.js +52 -1
  185. package/dist/runtime/bridge.js.map +1 -1
  186. package/dist/scripts/__tests__/codex-native-hook.test.js +2620 -487
  187. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  188. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts +2 -0
  189. package/dist/scripts/__tests__/reasoning-artifact-contract.test.d.ts.map +1 -0
  190. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js +108 -0
  191. package/dist/scripts/__tests__/reasoning-artifact-contract.test.js.map +1 -0
  192. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js +46 -173
  193. package/dist/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.js.map +1 -1
  194. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js +39 -159
  195. package/dist/scripts/__tests__/role-intent-durable-recovery-3181.test.js.map +1 -1
  196. package/dist/scripts/__tests__/smoke-packed-install.test.js +254 -2
  197. package/dist/scripts/__tests__/smoke-packed-install.test.js.map +1 -1
  198. package/dist/scripts/codex-native-hook.d.ts +4 -1
  199. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  200. package/dist/scripts/codex-native-hook.js +11013 -1153
  201. package/dist/scripts/codex-native-hook.js.map +1 -1
  202. package/dist/scripts/notify-fallback-watcher.js +82 -108
  203. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  204. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  205. package/dist/scripts/notify-hook/auto-nudge.js +74 -3
  206. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  207. package/dist/scripts/notify-hook/team-dispatch.d.ts +9 -0
  208. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  209. package/dist/scripts/notify-hook/team-dispatch.js +234 -79
  210. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  211. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  212. package/dist/scripts/notify-hook/team-leader-nudge.js +39 -13
  213. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  214. package/dist/scripts/notify-hook/team-tmux-guard.d.ts +12 -4
  215. package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
  216. package/dist/scripts/notify-hook/team-tmux-guard.js +365 -44
  217. package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
  218. package/dist/scripts/notify-hook/team-worker-stop.d.ts.map +1 -1
  219. package/dist/scripts/notify-hook/team-worker-stop.js +19 -18
  220. package/dist/scripts/notify-hook/team-worker-stop.js.map +1 -1
  221. package/dist/scripts/notify-hook/team-worker.d.ts +3 -0
  222. package/dist/scripts/notify-hook/team-worker.d.ts.map +1 -1
  223. package/dist/scripts/notify-hook/team-worker.js +37 -28
  224. package/dist/scripts/notify-hook/team-worker.js.map +1 -1
  225. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  226. package/dist/scripts/notify-hook/tmux-injection.js +28 -2
  227. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  228. package/dist/scripts/notify-hook.js +1 -0
  229. package/dist/scripts/notify-hook.js.map +1 -1
  230. package/dist/scripts/smoke-packed-install.d.ts +48 -3
  231. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  232. package/dist/scripts/smoke-packed-install.js +2796 -13
  233. package/dist/scripts/smoke-packed-install.js.map +1 -1
  234. package/dist/state/__tests__/mode-state-context.test.js +54 -0
  235. package/dist/state/__tests__/mode-state-context.test.js.map +1 -1
  236. package/dist/state/__tests__/operations.test.js +2 -0
  237. package/dist/state/__tests__/operations.test.js.map +1 -1
  238. package/dist/state/mode-state-context.d.ts +5 -0
  239. package/dist/state/mode-state-context.d.ts.map +1 -1
  240. package/dist/state/mode-state-context.js +59 -0
  241. package/dist/state/mode-state-context.js.map +1 -1
  242. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js +24 -245
  243. package/dist/subagents/__tests__/leader-bootstrap-3181.test.js.map +1 -1
  244. package/dist/subagents/tracker.d.ts +1 -82
  245. package/dist/subagents/tracker.d.ts.map +1 -1
  246. package/dist/subagents/tracker.js +3 -275
  247. package/dist/subagents/tracker.js.map +1 -1
  248. package/dist/team/__tests__/api-interop.test.js +91 -1
  249. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  250. package/dist/team/__tests__/delivery-e2e-smoke.test.js +52 -10
  251. package/dist/team/__tests__/delivery-e2e-smoke.test.js.map +1 -1
  252. package/dist/team/__tests__/idle-nudge.test.js +45 -15
  253. package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
  254. package/dist/team/__tests__/mcp-comm.test.js +93 -27
  255. package/dist/team/__tests__/mcp-comm.test.js.map +1 -1
  256. package/dist/team/__tests__/model-contract.test.js +110 -3
  257. package/dist/team/__tests__/model-contract.test.js.map +1 -1
  258. package/dist/team/__tests__/runtime-cli.test.js +9 -0
  259. package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
  260. package/dist/team/__tests__/runtime.test.js +3204 -335
  261. package/dist/team/__tests__/runtime.test.js.map +1 -1
  262. package/dist/team/__tests__/scaling.test.js +2359 -142
  263. package/dist/team/__tests__/scaling.test.js.map +1 -1
  264. package/dist/team/__tests__/state.test.js +804 -36
  265. package/dist/team/__tests__/state.test.js.map +1 -1
  266. package/dist/team/__tests__/team-ops-contract.test.js +6 -0
  267. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  268. package/dist/team/__tests__/tmux-session.test.js +3049 -784
  269. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  270. package/dist/team/__tests__/worker-runtime-identity.test.js +38 -2
  271. package/dist/team/__tests__/worker-runtime-identity.test.js.map +1 -1
  272. package/dist/team/__tests__/worktree.test.js +6 -0
  273. package/dist/team/__tests__/worktree.test.js.map +1 -1
  274. package/dist/team/api-interop.d.ts.map +1 -1
  275. package/dist/team/api-interop.js +15 -9
  276. package/dist/team/api-interop.js.map +1 -1
  277. package/dist/team/exact-pane.d.ts +23 -0
  278. package/dist/team/exact-pane.d.ts.map +1 -0
  279. package/dist/team/exact-pane.js +133 -0
  280. package/dist/team/exact-pane.js.map +1 -0
  281. package/dist/team/idle-nudge.d.ts +12 -1
  282. package/dist/team/idle-nudge.d.ts.map +1 -1
  283. package/dist/team/idle-nudge.js +41 -14
  284. package/dist/team/idle-nudge.js.map +1 -1
  285. package/dist/team/model-contract.d.ts +2 -5
  286. package/dist/team/model-contract.d.ts.map +1 -1
  287. package/dist/team/model-contract.js +59 -17
  288. package/dist/team/model-contract.js.map +1 -1
  289. package/dist/team/runtime.d.ts +1 -0
  290. package/dist/team/runtime.d.ts.map +1 -1
  291. package/dist/team/runtime.js +1244 -180
  292. package/dist/team/runtime.js.map +1 -1
  293. package/dist/team/scaling.d.ts +13 -1
  294. package/dist/team/scaling.d.ts.map +1 -1
  295. package/dist/team/scaling.js +1430 -384
  296. package/dist/team/scaling.js.map +1 -1
  297. package/dist/team/state/dispatch.d.ts.map +1 -1
  298. package/dist/team/state/dispatch.js +26 -8
  299. package/dist/team/state/dispatch.js.map +1 -1
  300. package/dist/team/state/locks.d.ts.map +1 -1
  301. package/dist/team/state/locks.js +61 -13
  302. package/dist/team/state/locks.js.map +1 -1
  303. package/dist/team/state/tasks.d.ts.map +1 -1
  304. package/dist/team/state/tasks.js +4 -3
  305. package/dist/team/state/tasks.js.map +1 -1
  306. package/dist/team/state.d.ts +67 -1
  307. package/dist/team/state.d.ts.map +1 -1
  308. package/dist/team/state.js +636 -129
  309. package/dist/team/state.js.map +1 -1
  310. package/dist/team/team-ops.d.ts +5 -0
  311. package/dist/team/team-ops.d.ts.map +1 -1
  312. package/dist/team/team-ops.js +4 -0
  313. package/dist/team/team-ops.js.map +1 -1
  314. package/dist/team/tmux-session.d.ts +123 -23
  315. package/dist/team/tmux-session.d.ts.map +1 -1
  316. package/dist/team/tmux-session.js +1250 -291
  317. package/dist/team/tmux-session.js.map +1 -1
  318. package/dist/team/worktree.d.ts.map +1 -1
  319. package/dist/team/worktree.js +4 -0
  320. package/dist/team/worktree.js.map +1 -1
  321. package/dist/utils/__tests__/file-durability.test.d.ts +2 -0
  322. package/dist/utils/__tests__/file-durability.test.d.ts.map +1 -0
  323. package/dist/utils/__tests__/file-durability.test.js +57 -0
  324. package/dist/utils/__tests__/file-durability.test.js.map +1 -0
  325. package/dist/utils/file-durability.d.ts +15 -0
  326. package/dist/utils/file-durability.d.ts.map +1 -0
  327. package/dist/utils/file-durability.js +37 -0
  328. package/dist/utils/file-durability.js.map +1 -0
  329. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +3 -0
  330. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
  331. package/dist/wiki/lint.d.ts +4 -1
  332. package/dist/wiki/lint.d.ts.map +1 -1
  333. package/dist/wiki/lint.js +3 -2
  334. package/dist/wiki/lint.js.map +1 -1
  335. package/package.json +1 -1
  336. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  337. package/plugins/oh-my-codex/hooks/codex-native-hook.mjs +24 -0
  338. package/plugins/oh-my-codex/skills/ralph/SKILL.md +6 -4
  339. package/plugins/oh-my-codex/skills/ralplan/SKILL.md +3 -2
  340. package/plugins/oh-my-codex/skills/team/SKILL.md +13 -9
  341. package/skills/ralph/SKILL.md +6 -4
  342. package/skills/ralplan/SKILL.md +3 -2
  343. package/skills/team/SKILL.md +13 -9
  344. package/src/scripts/__tests__/codex-native-hook.test.ts +2826 -497
  345. package/src/scripts/__tests__/reasoning-artifact-contract.test.ts +129 -0
  346. package/src/scripts/__tests__/role-intent-bootstrap-e2e-3181.test.ts +48 -185
  347. package/src/scripts/__tests__/role-intent-durable-recovery-3181.test.ts +44 -177
  348. package/src/scripts/__tests__/smoke-packed-install.test.ts +320 -2
  349. package/src/scripts/codex-native-hook.ts +10715 -1069
  350. package/src/scripts/notify-fallback-watcher.ts +84 -115
  351. package/src/scripts/notify-hook/auto-nudge.ts +71 -3
  352. package/src/scripts/notify-hook/team-dispatch.ts +242 -75
  353. package/src/scripts/notify-hook/team-leader-nudge.ts +40 -18
  354. package/src/scripts/notify-hook/team-tmux-guard.ts +366 -39
  355. package/src/scripts/notify-hook/team-worker-stop.ts +20 -16
  356. package/src/scripts/notify-hook/team-worker.ts +39 -26
  357. package/src/scripts/notify-hook/tmux-injection.ts +28 -2
  358. package/src/scripts/notify-hook.ts +1 -0
  359. package/src/scripts/smoke-packed-install.ts +3196 -14
  360. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts +0 -2
  361. package/dist/subagents/__tests__/adapted-role-binding.test.d.ts.map +0 -1
  362. package/dist/subagents/__tests__/adapted-role-binding.test.js +0 -988
  363. package/dist/subagents/__tests__/adapted-role-binding.test.js.map +0 -1
  364. package/dist/subagents/adapted-role-binding.d.ts +0 -17
  365. package/dist/subagents/adapted-role-binding.d.ts.map +0 -1
  366. package/dist/subagents/adapted-role-binding.js +0 -75
  367. package/dist/subagents/adapted-role-binding.js.map +0 -1
@@ -26,7 +26,6 @@ import {
26
26
  maybeNudgeTeamLeader,
27
27
  resolveLeaderStalenessThresholdMs,
28
28
  } from './notify-hook/team-leader-nudge.js';
29
- import { resolveManagedPaneFromAnchor, resolveManagedSessionPane } from './notify-hook/managed-tmux.js';
30
29
  import { DEFAULT_MARKER } from './tmux-hook-engine.js';
31
30
  import { isTerminalPhase } from './notify-hook/utils.js';
32
31
  import { isSessionStale, isSessionStateAuthoritativeForCwd, readSessionState } from '../hooks/session.js';
@@ -40,6 +39,8 @@ import { validateSessionId } from '../mcp/state-paths.js';
40
39
  import { TEAM_NAME_SAFE_PATTERN } from '../team/contracts.js';
41
40
  import { shouldContinueRun } from '../runtime/run-loop.js';
42
41
  import { deliverNotifyFallback, compactNotifyFallbackDeliveries, NOTIFY_FALLBACK_LEASE_MS } from './notify-fallback-delivery.js';
42
+ import { readExactPaneProofSync } from '../team/exact-pane.js';
43
+ import { OMX_RALPH_PANE_OWNER_OPTION } from '../state/mode-state-context.js';
43
44
 
44
45
  function argValue(name: string, fallback = ''): string {
45
46
  const idx = process.argv.indexOf(name);
@@ -72,8 +73,12 @@ function normalizeValidTeamName(value: unknown): string {
72
73
  }
73
74
 
74
75
  function parsePositivePid(value: unknown): number | null {
75
- const pid = Math.trunc(asNumber(value as string | number | undefined, 0));
76
- return pid > 0 ? pid : null;
76
+ if (typeof value === 'number') return Number.isSafeInteger(value) && value > 0 ? value : null;
77
+ if (typeof value !== 'string') return null;
78
+ const trimmed = value.trim();
79
+ if (!/^[1-9][0-9]*$/.test(trimmed)) return null;
80
+ const pid = Number(trimmed);
81
+ return Number.isSafeInteger(pid) && pid > 0 ? pid : null;
77
82
  }
78
83
 
79
84
  function parseIsoMillis(value: string | null | undefined): number | null {
@@ -771,27 +776,57 @@ async function resolveActiveTeamState(): Promise<ActiveTeamResult> {
771
776
  };
772
777
  }
773
778
 
774
- async function emitRalphContinueSteer(paneId: string, message: string): Promise<void> {
775
- const markedText = `${message} ${DEFAULT_MARKER}`;
776
- await new Promise<void>((resolve) => {
777
- const { result: typed } = spawnPlatformCommandSync('tmux', ['send-keys', '-t', paneId, '-l', markedText], { encoding: 'utf-8' });
778
- if (typed.error) throw new Error(typed.error.message);
779
- if (typed.status !== 0) throw new Error((typed.stderr || typed.stdout || '').trim() || 'tmux send-keys failed');
780
- setTimeout(resolve, 100);
781
- });
782
- await new Promise<void>((resolve) => {
783
- const { result: submitA } = spawnPlatformCommandSync('tmux', ['send-keys', '-t', paneId, 'C-m'], { encoding: 'utf-8' });
784
- if (submitA.error) throw new Error(submitA.error.message);
785
- if (submitA.status !== 0) throw new Error((submitA.stderr || submitA.stdout || '').trim() || 'tmux send-keys C-m failed');
786
- setTimeout(resolve, 100);
787
- });
788
- const { result: submitB } = spawnPlatformCommandSync('tmux', ['send-keys', '-t', paneId, 'C-m'], { encoding: 'utf-8' });
789
- if (submitB.error) throw new Error(submitB.error.message);
790
- if (submitB.status !== 0) {
791
- throw new Error((submitB.stderr || submitB.stdout || '').trim() || 'tmux send-keys C-m failed');
779
+ interface RalphContinuePaneBinding {
780
+ paneId: string;
781
+ panePid: number;
782
+ sessionName: string;
783
+ paneOwnerId: string;
784
+ }
785
+
786
+ function parseRalphContinuePaneBinding(state: Record<string, unknown> | null): RalphContinuePaneBinding | null {
787
+ const paneId = safeString(state?.tmux_pane_id).trim();
788
+ const panePid = parsePositivePid(state?.tmux_pane_pid);
789
+ const sessionName = safeString(state?.tmux_session_name).trim();
790
+ const paneOwnerId = safeString(state?.tmux_pane_owner_id).trim();
791
+ if (!/^%[0-9]+$/.test(paneId) || panePid === null || !sessionName || !paneOwnerId) return null;
792
+ if (paneOwnerId.startsWith('team:')) return null;
793
+ return { paneId, panePid, sessionName, paneOwnerId };
794
+ }
795
+
796
+ function requireFrozenRalphPaneBinding(binding: RalphContinuePaneBinding): void {
797
+ const initialProof = readExactPaneProofSync(binding.paneId);
798
+ if (initialProof.status !== 'live' || initialProof.pid !== binding.panePid) {
799
+ throw new Error(`persisted Ralph pane identity unavailable: ${binding.paneId}`);
800
+ }
801
+ const session = spawnPlatformCommandSync('tmux', ['display-message', '-p', '-t', binding.paneId, '#S'], { encoding: 'utf-8' }).result;
802
+ if (session.error || session.status !== 0 || safeString(session.stdout).trim() !== binding.sessionName) {
803
+ throw new Error(`persisted Ralph pane session changed: ${binding.paneId}`);
804
+ }
805
+ const owner = spawnPlatformCommandSync('tmux', ['show-option', '-qv', '-p', '-t', binding.paneId, OMX_RALPH_PANE_OWNER_OPTION], { encoding: 'utf-8' }).result;
806
+ if (owner.error || owner.status !== 0 || safeString(owner.stdout).trim() !== binding.paneOwnerId) {
807
+ throw new Error(`persisted Ralph pane owner changed: ${binding.paneId}`);
808
+ }
809
+ const finalProof = readExactPaneProofSync(binding.paneId);
810
+ if (finalProof.status !== 'live' || finalProof.pid !== binding.panePid) {
811
+ throw new Error(`persisted Ralph pane identity changed: ${binding.paneId}`);
792
812
  }
793
813
  }
794
814
 
815
+ async function emitRalphContinueSteer(binding: RalphContinuePaneBinding, message: string): Promise<void> {
816
+ const markedText = `${message} ${DEFAULT_MARKER}`;
817
+ const sendKeys = (args: string[], failure: string): void => {
818
+ requireFrozenRalphPaneBinding(binding);
819
+ const { result } = spawnPlatformCommandSync('tmux', args, { encoding: 'utf-8' });
820
+ if (result.error) throw new Error(result.error.message);
821
+ if (result.status !== 0) throw new Error((result.stderr || result.stdout || '').trim() || failure);
822
+ };
823
+ sendKeys(['send-keys', '-t', binding.paneId, '-l', markedText], 'tmux send-keys failed');
824
+ await sleep(100);
825
+ sendKeys(['send-keys', '-t', binding.paneId, 'C-m'], 'tmux send-keys C-m failed');
826
+ await sleep(100);
827
+ sendKeys(['send-keys', '-t', binding.paneId, 'C-m'], 'tmux send-keys C-m failed');
828
+ }
829
+
795
830
  async function readRalphSteerTimestamp(): Promise<string> {
796
831
  return readFile(ralphSteerTimestampPath, 'utf-8')
797
832
  .then((content) => safeString(content).trim())
@@ -1074,89 +1109,7 @@ async function writePidFileRecord(): Promise<void> {
1074
1109
  await writeFile(pidFilePath, JSON.stringify(nextRecord, null, 2)).catch(() => {});
1075
1110
  }
1076
1111
 
1077
- async function buildWatcherManagedPayload(): Promise<Record<string, string> | null> {
1078
- const session = await readSessionState(cwd).catch(() => null);
1079
- const sessionId = safeString(session?.session_id).trim();
1080
- if (!sessionId || !session || isSessionStale(session)) return null;
1081
- return { session_id: sessionId };
1082
- }
1083
-
1084
- async function persistReboundRalphPaneState(
1085
- statePath: string,
1086
- state: Record<string, unknown> | null,
1087
- paneId: string,
1088
- nowIso: string,
1089
- ): Promise<Record<string, unknown>> {
1090
- const latestState = await readFile(statePath, 'utf-8')
1091
- .then((content) => JSON.parse(content) as Record<string, unknown>)
1092
- .catch(() => null);
1093
- const nextState = {
1094
- ...((latestState && typeof latestState === 'object') ? latestState : (state || {})),
1095
- tmux_pane_id: paneId,
1096
- tmux_pane_set_at: nowIso,
1097
- };
1098
- const tmpPath = `${statePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
1099
- await writeFile(tmpPath, JSON.stringify(nextState, null, 2));
1100
- try {
1101
- await rename(tmpPath, statePath);
1102
- } catch (error) {
1103
- await unlink(tmpPath).catch(() => {});
1104
- throw error;
1105
- }
1106
- return nextState;
1107
- }
1108
-
1109
- async function resolveRalphContinuePaneTarget(
1110
- activeRalph: ActiveModeResult,
1111
- nowIso: string,
1112
- ): Promise<{ paneId: string; state: Record<string, unknown> | null; reboundFrom: string }> {
1113
- const currentState = activeRalph.state && typeof activeRalph.state === 'object'
1114
- ? activeRalph.state as Record<string, unknown>
1115
- : null;
1116
- const anchorPaneId = safeString(currentState?.tmux_pane_id).trim();
1117
- if (!anchorPaneId) {
1118
- return {
1119
- paneId: '',
1120
- state: currentState,
1121
- reboundFrom: '',
1122
- };
1123
- }
1124
-
1125
- const managedPayload = await buildWatcherManagedPayload();
1126
- if (!managedPayload) {
1127
- return {
1128
- paneId: anchorPaneId,
1129
- state: currentState,
1130
- reboundFrom: '',
1131
- };
1132
- }
1133
-
1134
- let resolvedPaneId = await resolveManagedPaneFromAnchor(anchorPaneId, cwd, managedPayload, { allowTeamWorker: false });
1135
- if (!resolvedPaneId) {
1136
- resolvedPaneId = await resolveManagedSessionPane(cwd, managedPayload);
1137
- }
1138
- if (!resolvedPaneId) {
1139
- return {
1140
- paneId: '',
1141
- state: currentState,
1142
- reboundFrom: '',
1143
- };
1144
- }
1145
- if (resolvedPaneId === anchorPaneId) {
1146
- return {
1147
- paneId: resolvedPaneId,
1148
- state: currentState,
1149
- reboundFrom: '',
1150
- };
1151
- }
1152
1112
 
1153
- const updatedState = await persistReboundRalphPaneState(activeRalph.path, currentState, resolvedPaneId, nowIso);
1154
- return {
1155
- paneId: resolvedPaneId,
1156
- state: updatedState,
1157
- reboundFrom: anchorPaneId,
1158
- };
1159
- }
1160
1113
 
1161
1114
  async function runRalphContinueSteerTick(): Promise<void> {
1162
1115
  const now = Date.now();
@@ -1217,24 +1170,27 @@ async function runRalphContinueSteerTick(): Promise<void> {
1217
1170
  return { sent: false, skipped: true };
1218
1171
  }
1219
1172
 
1220
- const resolvedPane = await resolveRalphContinuePaneTarget(activeRalph, nowIso);
1221
- activeRalph.state = resolvedPane.state;
1222
- const paneId = resolvedPane.paneId;
1223
- if (!paneId) {
1224
- lastRalphContinueSteer.last_reason = 'pane_missing';
1173
+ const binding = parseRalphContinuePaneBinding(activeRalph.state);
1174
+ if (!binding) {
1175
+ lastRalphContinueSteer.last_reason = 'pane_binding_missing';
1225
1176
  lastRalphContinueSteer.pane_id = '';
1226
1177
  return { sent: false, skipped: true };
1227
1178
  }
1228
-
1229
- const paneGuard = await checkPaneReadyForTeamSendKeys(paneId);
1230
- lastRalphContinueSteer.pane_id = paneId;
1179
+ lastRalphContinueSteer.pane_id = binding.paneId;
1180
+ try {
1181
+ requireFrozenRalphPaneBinding(binding);
1182
+ } catch (error) {
1183
+ lastRalphContinueSteer.last_reason = 'pane_binding_changed';
1184
+ lastRalphContinueSteer.last_error = error instanceof Error ? error.message : safeString(error);
1185
+ return { sent: false, skipped: true };
1186
+ }
1187
+ const paneGuard = await checkPaneReadyForTeamSendKeys(binding.paneId, binding.paneId);
1231
1188
  lastRalphContinueSteer.pane_current_command = paneGuard.paneCurrentCommand || '';
1232
1189
  if (!paneGuard.ok) {
1233
1190
  lastRalphContinueSteer.last_reason = paneGuard.reason || 'pane_guard_blocked';
1234
1191
  return { sent: false, skipped: true };
1235
1192
  }
1236
-
1237
- await emitRalphContinueSteer(paneId, RALPH_CONTINUE_TEXT);
1193
+ await emitRalphContinueSteer(binding, RALPH_CONTINUE_TEXT);
1238
1194
  await writeRalphSteerTimestamp(nowIso);
1239
1195
  lastRalphContinueSteer.last_sent_at = nowIso;
1240
1196
  lastRalphContinueSteer.shared_last_sent_at = nowIso;
@@ -1243,8 +1199,7 @@ async function runRalphContinueSteerTick(): Promise<void> {
1243
1199
  await eventLog({
1244
1200
  type: 'ralph_continue_steer',
1245
1201
  reason: 'sent',
1246
- pane_id: paneId,
1247
- rebound_from: resolvedPane.reboundFrom || null,
1202
+ pane_id: binding.paneId,
1248
1203
  state_path: activeRalph.path,
1249
1204
  current_phase: safeString(activeRalph.state?.current_phase) || null,
1250
1205
  cadence_ms: RALPH_CONTINUE_CADENCE_MS,
@@ -1887,6 +1842,20 @@ async function runLeaderNudgeTick(): Promise<boolean> {
1887
1842
  return false;
1888
1843
  }
1889
1844
 
1845
+ const activeTeam = await resolveActiveTeamState();
1846
+ if (!activeTeam.active) {
1847
+ leaderNudgeRuns += 1;
1848
+ lastLeaderNudge = {
1849
+ enabled: true,
1850
+ leader_only: true,
1851
+ stale_threshold_ms: staleThresholdMs,
1852
+ precomputed_leader_stale: false,
1853
+ last_tick_at: startedIso,
1854
+ last_error: `inactive_team:${activeTeam.reason}`,
1855
+ };
1856
+ return false;
1857
+ }
1858
+
1890
1859
  try {
1891
1860
  const preComputedLeaderStale = await isLeaderStale(stateDir, staleThresholdMs, Date.now());
1892
1861
  await maybeNudgeTeamLeader({
@@ -559,6 +559,40 @@ export async function capturePane(paneId, lines = 10) {
559
559
  }
560
560
  }
561
561
 
562
+ async function resolveTeamWorkerNudgeBinding(stateDir: string): Promise<{
563
+ paneId: string;
564
+ panePid: number;
565
+ paneOwnerId: string;
566
+ hudPaneId: string;
567
+ } | null> {
568
+ const workerContext = safeString(process.env.OMX_TEAM_WORKER || '').trim();
569
+ if (!workerContext) return null;
570
+ const match = /^([A-Za-z0-9][A-Za-z0-9_-]*)\/(worker-[1-9]\d*)$/.exec(workerContext);
571
+ if (!match) return null;
572
+ const [, teamName, workerName] = match;
573
+ const teamDir = join(stateDir, 'team', teamName);
574
+ try {
575
+ const manifestPath = join(teamDir, 'manifest.v2.json');
576
+ const configPath = join(teamDir, 'config.json');
577
+ let raw: any;
578
+ try {
579
+ raw = JSON.parse(await readFile(manifestPath, 'utf-8'));
580
+ } catch {
581
+ raw = JSON.parse(await readFile(configPath, 'utf-8'));
582
+ }
583
+ if (safeString(raw?.name).trim() !== teamName || !Array.isArray(raw?.workers)) return null;
584
+ const worker = raw.workers.find((entry: any) => safeString(entry?.name).trim() === workerName);
585
+ const paneId = safeString(worker?.pane_id).trim();
586
+ const panePid = asNumber(worker?.pid);
587
+ const hudPaneId = safeString(raw?.hud_pane_id).trim();
588
+ const paneOwnerId = typeof raw?.tmux_pane_owner_id === 'string' ? raw.tmux_pane_owner_id.trim() : '';
589
+ if (!/^%\d+$/.test(paneId) || !Number.isInteger(panePid) || panePid <= 0 || !paneOwnerId || paneId === hudPaneId) return null;
590
+ return { paneId, panePid, paneOwnerId, hudPaneId };
591
+ } catch {
592
+ return null;
593
+ }
594
+ }
595
+
562
596
  export async function resolveNudgePaneTarget(stateDir: any, cwd = '', payload: any = undefined, context: ResolvedPromptTurnContext | null = null) {
563
597
  const allowTeamWorker = safeString(process.env.OMX_TEAM_WORKER || '').trim() !== '';
564
598
  const managedCurrentPane = context
@@ -638,14 +672,34 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload, context
638
672
  if (!nudgeState || typeof nudgeState !== 'object') {
639
673
  nudgeState = { nudgeCount: 0, lastNudgeAt: '', lastSignature: '', lastSemanticSignature: '' };
640
674
  }
641
- const paneId = await resolveNudgePaneTarget(stateDir, cwd, payload, context);
675
+ const teamWorkerBinding = await resolveTeamWorkerNudgeBinding(stateDir);
676
+ if (safeString(process.env.OMX_TEAM_WORKER || '').trim() && !teamWorkerBinding) return;
677
+ const paneId = teamWorkerBinding?.paneId
678
+ ?? await resolveNudgePaneTarget(stateDir, cwd, payload, context);
679
+ const teamPaneOptions = teamWorkerBinding
680
+ ? {
681
+ exactPaneId: teamWorkerBinding.paneId,
682
+ expectedPanePid: teamWorkerBinding.panePid,
683
+ expectedPaneOwnerId: teamWorkerBinding.paneOwnerId,
684
+ expectedHudPaneId: teamWorkerBinding.hudPaneId,
685
+ }
686
+ : { exactPaneId: paneId };
642
687
 
643
688
  let detected = detectStallPattern(lastMessage, config.patterns, skillState?.phase);
644
689
  let source = 'payload';
645
690
  let captured = '';
646
691
 
647
692
  if (!detected && paneId) {
648
- captured = await capturePane(paneId);
693
+ if (teamWorkerBinding) {
694
+ const captureGuard = await evaluatePaneInjectionReadiness(paneId, {
695
+ skipIfScrolling: true,
696
+ ...teamPaneOptions,
697
+ });
698
+ if (!captureGuard.ok) return;
699
+ captured = captureGuard.paneCapture;
700
+ } else {
701
+ captured = await capturePane(paneId);
702
+ }
649
703
  detected = detectStallPattern(filterCapturedTestLines(captured), config.patterns, skillState?.phase);
650
704
  source = 'capture-pane';
651
705
  }
@@ -706,7 +760,7 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload, context
706
760
  return;
707
761
  }
708
762
 
709
- const paneGuard = await evaluatePaneInjectionReadiness(paneId, { skipIfScrolling: true });
763
+ const paneGuard = await evaluatePaneInjectionReadiness(paneId, { skipIfScrolling: true, ...teamPaneOptions });
710
764
  if (!paneGuard.ok) {
711
765
  await logTmuxHookEvent(logsDir, {
712
766
  timestamp: new Date().toISOString(),
@@ -719,6 +773,18 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload, context
719
773
  }).catch(() => {});
720
774
  return;
721
775
  }
776
+ const readinessPanePid = asNumber(paneGuard.exactPaneProof?.pid);
777
+ if (!Number.isInteger(readinessPanePid) || readinessPanePid <= 0) {
778
+ await logTmuxHookEvent(logsDir, {
779
+ timestamp: new Date().toISOString(),
780
+ type: 'auto_nudge_skipped',
781
+ pane_id: paneId,
782
+ reason: 'pane_readiness_unverified',
783
+ source,
784
+ }).catch(() => {});
785
+ return;
786
+ }
787
+ const pinnedPaneOptions = { ...teamPaneOptions, expectedPanePid: readinessPanePid };
722
788
 
723
789
  const blockedAutoApproval = isDeepInterviewAutoApprovalLocked(skillState)
724
790
  && !releaseReason
@@ -747,6 +813,8 @@ export async function maybeAutoNudge({ cwd, stateDir, logsDir, payload, context
747
813
  try {
748
814
  const sendResult = await sendPaneInput({
749
815
  paneTarget: paneId,
816
+ exactPaneId: paneId,
817
+ ...pinnedPaneOptions,
750
818
  prompt: `${effectiveResponse} ${DEFAULT_MARKER}`,
751
819
  submitKeyPresses: 2,
752
820
  submitDelayMs: 100,