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
@@ -1,12 +1,20 @@
1
1
  // @ts-nocheck
2
2
  import assert from 'node:assert/strict';
3
- import { access, chmod, mkdtemp, mkdir, rm, symlink, writeFile } from 'node:fs/promises';
3
+ import { access, chmod, mkdtemp, mkdir, readFile, rm, symlink, writeFile } from 'node:fs/promises';
4
4
  import { EventEmitter } from 'node:events';
5
5
  import { tmpdir } from 'node:os';
6
6
  import { delimiter, join } from 'node:path';
7
7
  import { PassThrough } from 'node:stream';
8
8
  import { test } from 'node:test';
9
9
  import {
10
+ assertInstalledPluginSurface,
11
+ assertInstalledReasoningDeclarationContract,
12
+ assertInstalledReasoningRuntimeContract,
13
+ assertInstalledRootReasoningHelp,
14
+ assertInstalledRootReasoningRejection,
15
+ assertInstalledTeamSkillContract,
16
+ assertPackedInstallFileMetadata,
17
+ buildNativeHookSmokePayload,
10
18
  ensureRepoDependencies,
11
19
  hasUsableNodeModules,
12
20
  buildPackedRegressionEnvironment,
@@ -16,15 +24,20 @@ import {
16
24
  MANAGED_CODEX_HOOK_EVENTS,
17
25
  PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS,
18
26
  PACKED_INSTALL_NATIVE_HOOK_REGRESSION_PROMPTS,
27
+ PACKED_CODEX_01445_NO_POINTER_NO_TRACKER_FIXTURE,
19
28
  PACKED_INSTALL_SMOKE_CORE_COMMANDS,
20
29
  appendForeignHookGroups,
21
30
  appendDisplayOrderStableForeignHookGroups,
22
- buildNativeHookSmokePayload,
23
31
  createCodexBatchWriteEnvelope,
24
32
  createCodexHooksListEnvelope,
25
33
  createCodexInitializeEnvelope,
26
34
  foreignHookGroupSnapshot,
27
35
  generatedHookTrustState,
36
+ isForbiddenPackedInstallArtifact,
37
+ PACKED_INSTALL_FORBIDDEN_ARTIFACT_PATHS,
38
+ PACKED_INSTALL_REQUIRED_ARTIFACT_PATHS,
39
+ PACKED_INSTALL_PLUGIN_MCP_TARGETS,
40
+ parseFakeCodexLaunches,
28
41
  parseNpmPackJsonOutput,
29
42
  parseCodexHooksListResult,
30
43
  probeCodexVersion,
@@ -35,6 +48,7 @@ import {
35
48
  assertGeneratedTrustMatchesCodex,
36
49
  managedCodexHooksByEvent,
37
50
  } from '../smoke-packed-install.js';
51
+ import { parseNativeSubagentResultDisposition } from '../../leader/contract.js';
38
52
 
39
53
  function createFakeCodexAppServer(
40
54
  onRequest: (request: Record<string, unknown>, child: EventEmitter & Record<string, unknown>) => void,
@@ -68,6 +82,38 @@ test('packed install smoke retains narrow boot commands and adds the isolated li
68
82
  );
69
83
  });
70
84
 
85
+ test('packed 0.144.5 fixture is sanitized, pointer-free, and kept separate from the 0.142.5 lifecycle pin', () => {
86
+ assert.deepEqual(PACKED_CODEX_01445_NO_POINTER_NO_TRACKER_FIXTURE, {
87
+ hook_event_name: 'PreToolUse',
88
+ session_id: 'packed-01445-session',
89
+ turn_id: 'packed-01445-turn',
90
+ tool_name: 'Bash',
91
+ tool_use_id: 'packed-01445-tool',
92
+ tool_input: { command: 'omx ralplan role-intent write --role architect --parent-thread "$CODEX_THREAD_ID" --json' },
93
+ });
94
+ assert.equal(Object.hasOwn(PACKED_CODEX_01445_NO_POINTER_NO_TRACKER_FIXTURE, 'tracker'), false);
95
+ assert.equal(Object.hasOwn(PACKED_CODEX_01445_NO_POINTER_NO_TRACKER_FIXTURE, 'session_pointer'), false);
96
+ assert.equal(Object.hasOwn(PACKED_CODEX_01445_NO_POINTER_NO_TRACKER_FIXTURE, 'cwd'), false);
97
+ assert.equal(Object.hasOwn(PACKED_CODEX_01445_NO_POINTER_NO_TRACKER_FIXTURE, 'thread_id'), false);
98
+ assert.equal(PACKED_CODEX_01445_NO_POINTER_NO_TRACKER_FIXTURE.session_id.includes('-'), true);
99
+ });
100
+
101
+ test('packed plugin collaboration success stays authoritative over unrelated child prose', () => {
102
+ const packedResponse = JSON.stringify({
103
+ success: true,
104
+ status: 'completed',
105
+ output: 'Packed/plugin child succeeded; an optional adapter was unavailable, unsupported, and not found.',
106
+ });
107
+ for (const toolName of [
108
+ 'collaboration.spawn_agent',
109
+ 'collaboration.list_agents',
110
+ 'collaboration.followup_task',
111
+ 'collaboration.wait_agent',
112
+ ]) {
113
+ assert.equal(parseNativeSubagentResultDisposition(toolName, packedResponse).kind, 'success', toolName);
114
+ }
115
+ });
116
+
71
117
  test('packed lifecycle keeps the pinned newline-delimited Codex app-server envelopes literal', () => {
72
118
  assert.deepEqual(createCodexInitializeEnvelope('omx-hook-trust-regression'), {
73
119
  id: 1,
@@ -804,6 +850,17 @@ test('display-order-stable foreign fixture preserves pre-approved group and hand
804
850
  );
805
851
  });
806
852
 
853
+ test('packed install smoke probes every advertised plugin MCP target', () => {
854
+ assert.deepEqual(PACKED_INSTALL_PLUGIN_MCP_TARGETS, [
855
+ ['omx_state', 'state', 'omx-state'],
856
+ ['omx_memory', 'memory', 'omx-memory'],
857
+ ['omx_code_intel', 'code-intel', 'omx-code-intel'],
858
+ ['omx_trace', 'trace', 'omx-trace'],
859
+ ['omx_wiki', 'wiki', 'omx-wiki'],
860
+ ['omx_hermes', 'hermes', 'omx-hermes'],
861
+ ]);
862
+ });
863
+
807
864
  test('packed install smoke covers every installed native hook event with minimal payloads', () => {
808
865
  assert.deepEqual(PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS, [
809
866
  'SessionStart',
@@ -1048,6 +1105,31 @@ test('packed install native hook stdout validation enforces event output contrac
1048
1105
  );
1049
1106
  });
1050
1107
 
1108
+ test('fake Codex launch capture preserves argv and runtime side-effect evidence', () => {
1109
+ const capture = `${JSON.stringify({
1110
+ argv: ['--', '--spark'],
1111
+ cwd: '/tmp/omx-packed-launch',
1112
+ hasResumeSqlite: true,
1113
+ OMX_NOTIFY_TEMP_CONTRACT: null,
1114
+ OMX_TEAM_WORKER_LAUNCH_ARGS: null,
1115
+ })}\n`;
1116
+ assert.deepEqual(parseFakeCodexLaunches(capture), [{
1117
+ argv: ['--', '--spark'],
1118
+ cwd: '/tmp/omx-packed-launch',
1119
+ hasResumeSqlite: true,
1120
+ OMX_NOTIFY_TEMP_CONTRACT: null,
1121
+ OMX_TEAM_WORKER_LAUNCH_ARGS: null,
1122
+ }]);
1123
+ assert.throws(
1124
+ () => parseFakeCodexLaunches(`${JSON.stringify({
1125
+ argv: ['--spark'],
1126
+ cwd: '/tmp/omx-packed-launch',
1127
+ OMX_NOTIFY_TEMP_CONTRACT: null,
1128
+ })}\n`),
1129
+ /fake Codex capture did not contain a valid launch record/,
1130
+ );
1131
+ });
1132
+
1051
1133
  test('parseNpmPackJsonOutput ignores prepack logs before npm pack JSON', () => {
1052
1134
  const parsed = parseNpmPackJsonOutput([
1053
1135
  '[sync-plugin-mirror] synced 29 canonical skill directories and plugin metadata',
@@ -1062,6 +1144,242 @@ test('parseNpmPackJsonOutput ignores prepack logs before npm pack JSON', () => {
1062
1144
  assert.deepEqual(parsed, [{ filename: 'oh-my-codex-0.15.0.tgz' }]);
1063
1145
  });
1064
1146
 
1147
+ test('packed install metadata requires runtime, declarations, Team skills, and plugin assets only', () => {
1148
+ const files = PACKED_INSTALL_REQUIRED_ARTIFACT_PATHS.map((path) => ({ path }));
1149
+ assert.doesNotThrow(() => assertPackedInstallFileMetadata(files));
1150
+ assert.equal(
1151
+ PACKED_INSTALL_REQUIRED_ARTIFACT_PATHS.some((path) => path.startsWith('docs/')),
1152
+ false,
1153
+ 'repository documentation must not become an npm package requirement',
1154
+ );
1155
+ assert.throws(
1156
+ () => assertPackedInstallFileMetadata(files.slice(1)),
1157
+ /npm pack is missing required artifact: dist\/config\/models\.js/,
1158
+ );
1159
+ assert.throws(
1160
+ () => assertPackedInstallFileMetadata([...files, { path: 'docs/reference/omx-config-schema-routing.md' }]),
1161
+ /npm pack includes forbidden workspace artifact: docs\/reference\/omx-config-schema-routing\.md/,
1162
+ );
1163
+
1164
+ for (const path of [
1165
+ '.gjc/session/plan.md',
1166
+ 'docs/reference/page.md',
1167
+ '.omx/state/team.json',
1168
+ 'artifact.tgz',
1169
+ 'tmp/smoke-output.txt',
1170
+ 'temp/smoke-output.json',
1171
+ 'scratch.tmp',
1172
+ ]) {
1173
+ assert.equal(isForbiddenPackedInstallArtifact(path), true, `expected ${path} to be rejected`);
1174
+ }
1175
+ for (const prefix of PACKED_INSTALL_FORBIDDEN_ARTIFACT_PATHS) {
1176
+ assert.equal(isForbiddenPackedInstallArtifact(`${prefix}probe`), true);
1177
+ }
1178
+ assert.equal(isForbiddenPackedInstallArtifact('templates/AGENTS.md'), false);
1179
+ assert.equal(isForbiddenPackedInstallArtifact('dist/notifications/__tests__/temp-mode.test.d.ts'), false);
1180
+ });
1181
+
1182
+ test('packed install helpers enforce root rejection and no config mutation', () => {
1183
+ const help = 'Usage: omx reasoning <low|medium|high|xhigh>\n --xhigh\n';
1184
+ assert.doesNotThrow(() => assertInstalledRootReasoningHelp(help));
1185
+ assert.throws(() => assertInstalledRootReasoningHelp(`${help} --max\n`), /must not advertise --max/);
1186
+
1187
+ const maxStderr = [
1188
+ 'Reasoning mode "max" is not supported by "omx reasoning".',
1189
+ 'Per-agent "max" is configured with agentReasoning; direct -c model_reasoning_effort=... is passed to Codex and remains capability-dependent.',
1190
+ 'Invalid reasoning mode "max". Expected one of: low, medium, high, xhigh.',
1191
+ 'Usage: omx reasoning <low|medium|high|xhigh>',
1192
+ ].join('\n');
1193
+ assert.doesNotThrow(() => assertInstalledRootReasoningRejection(
1194
+ 'max',
1195
+ { status: 1, stdout: '', stderr: maxStderr },
1196
+ undefined,
1197
+ undefined,
1198
+ ));
1199
+ assert.throws(
1200
+ () => assertInstalledRootReasoningRejection('max', { status: 1, stdout: '', stderr: maxStderr }, undefined, 'created'),
1201
+ /must not create or mutate config\.toml/,
1202
+ );
1203
+
1204
+ const ultraStderr = [
1205
+ 'Reasoning mode "ultra" is not supported by OMX root or per-agent reasoning and is not an alias for "max".',
1206
+ 'Direct -c model_reasoning_effort=... remains opaque Codex passthrough.',
1207
+ 'Invalid reasoning mode "ultra". Expected one of: low, medium, high, xhigh.',
1208
+ 'Usage: omx reasoning <low|medium|high|xhigh>',
1209
+ ].join('\n');
1210
+ assert.doesNotThrow(() => assertInstalledRootReasoningRejection(
1211
+ 'ultra',
1212
+ { status: 1, stdout: '', stderr: ultraStderr },
1213
+ 'model = "preserve"\n',
1214
+ 'model = "preserve"\n',
1215
+ ));
1216
+ });
1217
+
1218
+ test('packed install helpers freeze installed runtime and declaration reasoning contracts', () => {
1219
+ const models = {
1220
+ CANONICAL_REASONING_EFFORTS: ['low', 'medium', 'high', 'xhigh'],
1221
+ AMBIGUOUS_UNSUPPORTED_REASONING_EFFORTS: ['max', 'ultra'],
1222
+ PER_AGENT_REASONING_EFFORTS: ['low', 'medium', 'high', 'xhigh', 'max'],
1223
+ ROOT_REASONING_EFFORTS: ['low', 'medium', 'high', 'xhigh'],
1224
+ ROOT_UNSUPPORTED_REASONING_EFFORTS: ['max', 'ultra'],
1225
+ isAmbiguousUnsupportedReasoningEffort: (value: string) => value.toLowerCase() === 'max' || value.toLowerCase() === 'ultra',
1226
+ isUnsupportedRootReasoningEffort: (value: string) => value.toLowerCase() === 'max' || value.toLowerCase() === 'ultra',
1227
+ normalizeUnsupportedRootReasoningEffort: (value: string) => {
1228
+ const normalized = value.trim().toLowerCase();
1229
+ return normalized === 'max' || normalized === 'ultra' ? normalized : undefined;
1230
+ },
1231
+ };
1232
+ assert.doesNotThrow(() => assertInstalledReasoningRuntimeContract(models));
1233
+
1234
+ const modelsDeclaration = [
1235
+ 'export declare const CANONICAL_REASONING_EFFORTS: readonly ["low", "medium", "high", "xhigh"];',
1236
+ 'export type ConfiguredAgentReasoningEffort = (typeof CANONICAL_REASONING_EFFORTS)[number];',
1237
+ 'export declare const AMBIGUOUS_UNSUPPORTED_REASONING_EFFORTS: readonly ["max", "ultra"];',
1238
+ 'export declare const PER_AGENT_REASONING_EFFORTS: readonly ["low", "medium", "high", "xhigh", "max"];',
1239
+ 'export type PerAgentReasoningEffort = (typeof PER_AGENT_REASONING_EFFORTS)[number];',
1240
+ 'export declare const ROOT_REASONING_EFFORTS: readonly ["low", "medium", "high", "xhigh"];',
1241
+ 'export type RootReasoningEffort = (typeof ROOT_REASONING_EFFORTS)[number];',
1242
+ 'export declare const ROOT_UNSUPPORTED_REASONING_EFFORTS: readonly ["max", "ultra"];',
1243
+ 'export declare function isUnsupportedRootReasoningEffort(value: string): boolean;',
1244
+ 'export declare function normalizeUnsupportedRootReasoningEffort(value: string): RootUnsupportedReasoningEffort | undefined;',
1245
+ ].join('\n');
1246
+ const definitionsDeclaration = [
1247
+ 'export interface AgentDefinition {',
1248
+ " reasoningEffort: 'low' | 'medium' | 'high' | 'xhigh';",
1249
+ '}',
1250
+ ].join('\n');
1251
+ assert.doesNotThrow(() => assertInstalledReasoningDeclarationContract({
1252
+ models: modelsDeclaration,
1253
+ definitions: definitionsDeclaration,
1254
+ nativeConfig: 'export interface GeneratedNativeAgentConfig {\n reasoningEffort?: PerAgentReasoningEffort;\n}',
1255
+ team: 'export type TeamReasoningEffort = PerAgentReasoningEffort;',
1256
+ }));
1257
+ assert.throws(
1258
+ () => assertInstalledReasoningDeclarationContract({
1259
+ models: modelsDeclaration.replace(': boolean;', ': value is RootUnsupportedReasoningEffort;'),
1260
+ definitions: definitionsDeclaration,
1261
+ nativeConfig: 'reasoningEffort?: PerAgentReasoningEffort;',
1262
+ team: 'export type TeamReasoningEffort = PerAgentReasoningEffort;',
1263
+ }),
1264
+ /plain boolean, not a type predicate/,
1265
+ );
1266
+ });
1267
+
1268
+ test('packed install contract requires canonical/plugin Team skill parity and text', async () => {
1269
+ const canonical = await readFile(join(process.cwd(), 'skills/team/SKILL.md'));
1270
+ const pluginMirror = await readFile(join(process.cwd(), 'plugins/oh-my-codex/skills/team/SKILL.md'));
1271
+ assert.doesNotThrow(() => assertInstalledTeamSkillContract(canonical, pluginMirror));
1272
+ });
1273
+
1274
+ test('packed install plugin assertions enforce the packaged plugin contract', async () => {
1275
+ const root = await mkdtemp(join(tmpdir(), 'omx-packed-plugin-surface-'));
1276
+ try {
1277
+ const pluginRoot = join(root, 'plugins/oh-my-codex');
1278
+ const pluginManifestPath = join(pluginRoot, '.codex-plugin/plugin.json');
1279
+ const mcpManifestPath = join(pluginRoot, '.mcp.json');
1280
+ const appManifestPath = join(pluginRoot, '.app.json');
1281
+ const hooksManifestPath = join(pluginRoot, 'hooks/hooks.json');
1282
+ const hookLauncherPath = join(pluginRoot, 'hooks/codex-native-hook.mjs');
1283
+ const hookCommand = 'node "${PLUGIN_ROOT}/hooks/codex-native-hook.mjs"';
1284
+ await mkdir(join(pluginRoot, '.codex-plugin'), { recursive: true });
1285
+ await mkdir(join(pluginRoot, 'hooks'), { recursive: true });
1286
+
1287
+ const writeValidPluginSurface = async (): Promise<void> => {
1288
+ await writeFile(pluginManifestPath, JSON.stringify({
1289
+ name: 'oh-my-codex',
1290
+ version: '0.0.0-test',
1291
+ skills: './skills/',
1292
+ mcpServers: './.mcp.json',
1293
+ apps: './.app.json',
1294
+ hooks: './hooks/hooks.json',
1295
+ interface: {
1296
+ displayName: 'OMX',
1297
+ shortDescription: 'Test plugin',
1298
+ longDescription: 'Structurally valid plugin test fixture.',
1299
+ developerName: 'Test',
1300
+ category: 'Developer Tools',
1301
+ },
1302
+ }));
1303
+ await writeFile(mcpManifestPath, JSON.stringify({
1304
+ mcpServers: Object.fromEntries([
1305
+ ['omx_state', 'state'],
1306
+ ['omx_memory', 'memory'],
1307
+ ['omx_code_intel', 'code-intel'],
1308
+ ['omx_trace', 'trace'],
1309
+ ['omx_wiki', 'wiki'],
1310
+ ['omx_hermes', 'hermes'],
1311
+ ].map(([name, service]) => [name, {
1312
+ command: 'omx',
1313
+ args: ['mcp-serve', service],
1314
+ enabled: false,
1315
+ }])),
1316
+ }));
1317
+ await writeFile(appManifestPath, JSON.stringify({ apps: {} }));
1318
+ await writeFile(hooksManifestPath, JSON.stringify({
1319
+ hooks: Object.fromEntries(PACKED_INSTALL_NATIVE_HOOK_SMOKE_EVENTS.map((eventName) => [eventName, [{
1320
+ hooks: [{ type: 'command', command: hookCommand }],
1321
+ }]])),
1322
+ }));
1323
+ await writeFile(hookLauncherPath, [
1324
+ '#!/usr/bin/env node',
1325
+ "import { spawn } from 'node:child_process';",
1326
+ "import { join } from 'node:path';",
1327
+ "const OMX_PLUGIN_HOOK_LAUNCHER_CONTRACT_MARKER = 'omx-plugin-hook-launcher:v1';",
1328
+ "const hookDir = new URL('.', import.meta.url).pathname;",
1329
+ 'function readPinnedLauncher() {',
1330
+ " const launcherPath = join(hookDir, 'omx-command.json');",
1331
+ ' return { command: process.execPath, argsPrefix: [], launcherPath };',
1332
+ '}',
1333
+ 'const input = Buffer.from(\'\');',
1334
+ 'const { command, argsPrefix } = readPinnedLauncher();',
1335
+ "const child = spawn(command, [...argsPrefix, 'codex-native-hook']);",
1336
+ 'child.stdin.end(input);',
1337
+ '',
1338
+ ].join('\n'));
1339
+ };
1340
+
1341
+ await writeValidPluginSurface();
1342
+ assert.doesNotThrow(() => assertInstalledPluginSurface(root));
1343
+
1344
+ await writeValidPluginSurface();
1345
+ await writeFile(hookLauncherPath, [
1346
+ '#!/usr/bin/env node',
1347
+ "const OMX_PLUGIN_HOOK_LAUNCHER_CONTRACT_MARKER = 'omx-plugin-hook-launcher:v1';",
1348
+ 'process.stdout.write(OMX_PLUGIN_HOOK_LAUNCHER_CONTRACT_MARKER);',
1349
+ '',
1350
+ ].join('\n'));
1351
+ assert.throws(
1352
+ () => assertInstalledPluginSurface(root),
1353
+ /must read its pinned omx-command\.json delegate configuration/,
1354
+ );
1355
+
1356
+ await writeFile(pluginManifestPath, '{}');
1357
+ assert.throws(() => assertInstalledPluginSurface(root), /plugin\.json\.name/);
1358
+
1359
+ await writeValidPluginSurface();
1360
+ await writeFile(mcpManifestPath, JSON.stringify({ mcpServers: {} }));
1361
+ assert.throws(() => assertInstalledPluginSurface(root), /omx_state/);
1362
+
1363
+ await writeValidPluginSurface();
1364
+ await writeFile(appManifestPath, JSON.stringify({ apps: [] }));
1365
+ assert.throws(() => assertInstalledPluginSurface(root), /\.app\.json\.apps/);
1366
+
1367
+ await writeValidPluginSurface();
1368
+ await writeFile(hooksManifestPath, JSON.stringify({ hooks: {} }));
1369
+ assert.throws(() => assertInstalledPluginSurface(root), /hook event is missing: SessionStart/);
1370
+
1371
+ await writeValidPluginSurface();
1372
+ await writeFile(hookLauncherPath, 'export {};\n');
1373
+ assert.throws(() => assertInstalledPluginSurface(root), /must start with a Node shebang/);
1374
+
1375
+ await writeValidPluginSurface();
1376
+ await writeFile(mcpManifestPath, '{not-json');
1377
+ assert.throws(() => assertInstalledPluginSurface(root), /plugin manifest is not parseable JSON/);
1378
+ } finally {
1379
+ await rm(root, { recursive: true, force: true });
1380
+ }
1381
+ });
1382
+
1065
1383
  test('resolveGitCommonDir resolves relative git common dir output against the repo root', () => {
1066
1384
  const commonDir = resolveGitCommonDir('/tmp/worktree', () => ({
1067
1385
  status: 0,