oh-my-codex 0.16.2 → 0.16.4

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 (340) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/README.md +3 -3
  4. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -0
  5. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
  6. package/dist/cli/__tests__/cleanup.test.js +27 -0
  7. package/dist/cli/__tests__/cleanup.test.js.map +1 -1
  8. package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -5
  9. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  10. package/dist/cli/__tests__/doctor-warning-copy.test.js +137 -6
  11. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  12. package/dist/cli/__tests__/index.test.js +303 -4
  13. package/dist/cli/__tests__/index.test.js.map +1 -1
  14. package/dist/cli/__tests__/launch-fallback.test.js +58 -0
  15. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  16. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +2 -0
  17. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  18. package/dist/cli/__tests__/ralph.test.js +48 -0
  19. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  20. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +8 -0
  21. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  22. package/dist/cli/__tests__/setup-install-mode.test.js +350 -27
  23. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  24. package/dist/cli/__tests__/setup-refresh.test.js +85 -3
  25. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  26. package/dist/cli/__tests__/setup-scope.test.js +1 -1
  27. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  28. package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -1
  29. package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
  30. package/dist/cli/__tests__/team.test.js +269 -0
  31. package/dist/cli/__tests__/team.test.js.map +1 -1
  32. package/dist/cli/__tests__/ultragoal.test.js +69 -0
  33. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  34. package/dist/cli/__tests__/uninstall.test.js +90 -6
  35. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  36. package/dist/cli/__tests__/update.test.js +109 -19
  37. package/dist/cli/__tests__/update.test.js.map +1 -1
  38. package/dist/cli/cleanup.d.ts.map +1 -1
  39. package/dist/cli/cleanup.js +8 -4
  40. package/dist/cli/cleanup.js.map +1 -1
  41. package/dist/cli/codex-feature-probe.d.ts +9 -0
  42. package/dist/cli/codex-feature-probe.d.ts.map +1 -0
  43. package/dist/cli/codex-feature-probe.js +28 -0
  44. package/dist/cli/codex-feature-probe.js.map +1 -0
  45. package/dist/cli/doctor.d.ts +1 -0
  46. package/dist/cli/doctor.d.ts.map +1 -1
  47. package/dist/cli/doctor.js +168 -16
  48. package/dist/cli/doctor.js.map +1 -1
  49. package/dist/cli/index.d.ts +9 -2
  50. package/dist/cli/index.d.ts.map +1 -1
  51. package/dist/cli/index.js +168 -20
  52. package/dist/cli/index.js.map +1 -1
  53. package/dist/cli/mcp-parity.js +8 -8
  54. package/dist/cli/mcp-parity.js.map +1 -1
  55. package/dist/cli/plugin-marketplace.d.ts +3 -0
  56. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  57. package/dist/cli/plugin-marketplace.js +88 -0
  58. package/dist/cli/plugin-marketplace.js.map +1 -1
  59. package/dist/cli/ralph.d.ts.map +1 -1
  60. package/dist/cli/ralph.js +21 -0
  61. package/dist/cli/ralph.js.map +1 -1
  62. package/dist/cli/setup-preferences.d.ts +4 -0
  63. package/dist/cli/setup-preferences.d.ts.map +1 -1
  64. package/dist/cli/setup-preferences.js +7 -0
  65. package/dist/cli/setup-preferences.js.map +1 -1
  66. package/dist/cli/setup.d.ts +5 -3
  67. package/dist/cli/setup.d.ts.map +1 -1
  68. package/dist/cli/setup.js +177 -43
  69. package/dist/cli/setup.js.map +1 -1
  70. package/dist/cli/team.d.ts.map +1 -1
  71. package/dist/cli/team.js +54 -15
  72. package/dist/cli/team.js.map +1 -1
  73. package/dist/cli/ultragoal.d.ts +1 -1
  74. package/dist/cli/ultragoal.d.ts.map +1 -1
  75. package/dist/cli/ultragoal.js +64 -5
  76. package/dist/cli/ultragoal.js.map +1 -1
  77. package/dist/cli/uninstall.d.ts +2 -0
  78. package/dist/cli/uninstall.d.ts.map +1 -1
  79. package/dist/cli/uninstall.js +76 -5
  80. package/dist/cli/uninstall.js.map +1 -1
  81. package/dist/cli/update.d.ts +10 -2
  82. package/dist/cli/update.d.ts.map +1 -1
  83. package/dist/cli/update.js +99 -5
  84. package/dist/cli/update.js.map +1 -1
  85. package/dist/config/__tests__/codex-feature-flags.test.d.ts +2 -0
  86. package/dist/config/__tests__/codex-feature-flags.test.d.ts.map +1 -0
  87. package/dist/config/__tests__/codex-feature-flags.test.js +35 -0
  88. package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
  89. package/dist/config/__tests__/codex-hooks.test.js +188 -4
  90. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  91. package/dist/config/__tests__/generator-idempotent.test.js +129 -10
  92. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  93. package/dist/config/__tests__/generator-notify.test.js +148 -7
  94. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  95. package/dist/config/__tests__/wiki-config-contract.test.js +6 -3
  96. package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -1
  97. package/dist/config/codex-feature-flags.d.ts +21 -0
  98. package/dist/config/codex-feature-flags.d.ts.map +1 -0
  99. package/dist/config/codex-feature-flags.js +56 -0
  100. package/dist/config/codex-feature-flags.js.map +1 -0
  101. package/dist/config/codex-hooks.d.ts +40 -4
  102. package/dist/config/codex-hooks.d.ts.map +1 -1
  103. package/dist/config/codex-hooks.js +204 -18
  104. package/dist/config/codex-hooks.js.map +1 -1
  105. package/dist/config/generator.d.ts +19 -1
  106. package/dist/config/generator.d.ts.map +1 -1
  107. package/dist/config/generator.js +319 -83
  108. package/dist/config/generator.js.map +1 -1
  109. package/dist/config/omx-first-party-mcp.d.ts +3 -1
  110. package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
  111. package/dist/config/omx-first-party-mcp.js +2 -2
  112. package/dist/config/omx-first-party-mcp.js.map +1 -1
  113. package/dist/hooks/__tests__/keyword-detector.test.js +92 -2
  114. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  115. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +29 -1
  116. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  117. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +10 -0
  118. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  119. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js +1 -0
  120. package/dist/hooks/__tests__/notify-hook-cross-worktree-heartbeat.test.js.map +1 -1
  121. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.d.ts +2 -0
  122. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.d.ts.map +1 -0
  123. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +176 -0
  124. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -0
  125. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +148 -0
  126. package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -1
  127. package/dist/hooks/__tests__/notify-hook-session-scope.test.js +3 -0
  128. package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
  129. package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts +2 -0
  130. package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts.map +1 -0
  131. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +84 -0
  132. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -0
  133. package/dist/hooks/__tests__/wiki-docs-contract.test.js +1 -2
  134. package/dist/hooks/__tests__/wiki-docs-contract.test.js.map +1 -1
  135. package/dist/hooks/agents-overlay.js +2 -2
  136. package/dist/hooks/agents-overlay.js.map +1 -1
  137. package/dist/hooks/keyword-detector.d.ts +1 -0
  138. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  139. package/dist/hooks/keyword-detector.js +7 -5
  140. package/dist/hooks/keyword-detector.js.map +1 -1
  141. package/dist/hud/__tests__/state.test.js +164 -0
  142. package/dist/hud/__tests__/state.test.js.map +1 -1
  143. package/dist/hud/state.d.ts.map +1 -1
  144. package/dist/hud/state.js +4 -5
  145. package/dist/hud/state.js.map +1 -1
  146. package/dist/mcp/__tests__/state-paths.test.js +61 -0
  147. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  148. package/dist/mcp/__tests__/state-server.test.js +166 -0
  149. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  150. package/dist/mcp/state-paths.d.ts.map +1 -1
  151. package/dist/mcp/state-paths.js +23 -2
  152. package/dist/mcp/state-paths.js.map +1 -1
  153. package/dist/modes/__tests__/base-session-scope.test.js +22 -0
  154. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  155. package/dist/modes/__tests__/base-tmux-pane.test.js +57 -26
  156. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  157. package/dist/modes/base.d.ts.map +1 -1
  158. package/dist/modes/base.js +5 -0
  159. package/dist/modes/base.js.map +1 -1
  160. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts +2 -0
  161. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts.map +1 -0
  162. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +316 -0
  163. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -0
  164. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts +2 -0
  165. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts.map +1 -0
  166. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +481 -0
  167. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
  168. package/dist/planning/__tests__/artifacts.test.js +597 -4
  169. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  170. package/dist/planning/__tests__/context-pack-status.test.js +524 -0
  171. package/dist/planning/__tests__/context-pack-status.test.js.map +1 -1
  172. package/dist/planning/__tests__/markdown-structure.test.d.ts +2 -0
  173. package/dist/planning/__tests__/markdown-structure.test.d.ts.map +1 -0
  174. package/dist/planning/__tests__/markdown-structure.test.js +459 -0
  175. package/dist/planning/__tests__/markdown-structure.test.js.map +1 -0
  176. package/dist/planning/__tests__/ready-context-pack-role-refs.test.d.ts +2 -0
  177. package/dist/planning/__tests__/ready-context-pack-role-refs.test.d.ts.map +1 -0
  178. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +612 -0
  179. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +1 -0
  180. package/dist/planning/artifacts.d.ts +7 -2
  181. package/dist/planning/artifacts.d.ts.map +1 -1
  182. package/dist/planning/artifacts.js +279 -26
  183. package/dist/planning/artifacts.js.map +1 -1
  184. package/dist/planning/context-pack-status.d.ts +31 -0
  185. package/dist/planning/context-pack-status.d.ts.map +1 -1
  186. package/dist/planning/context-pack-status.js +291 -25
  187. package/dist/planning/context-pack-status.js.map +1 -1
  188. package/dist/planning/markdown-structure.d.ts +20 -0
  189. package/dist/planning/markdown-structure.d.ts.map +1 -0
  190. package/dist/planning/markdown-structure.js +137 -0
  191. package/dist/planning/markdown-structure.js.map +1 -0
  192. package/dist/ralph/__tests__/completion-audit.test.d.ts +2 -0
  193. package/dist/ralph/__tests__/completion-audit.test.d.ts.map +1 -0
  194. package/dist/ralph/__tests__/completion-audit.test.js +121 -0
  195. package/dist/ralph/__tests__/completion-audit.test.js.map +1 -0
  196. package/dist/ralph/completion-audit.d.ts +8 -0
  197. package/dist/ralph/completion-audit.d.ts.map +1 -0
  198. package/dist/ralph/completion-audit.js +99 -0
  199. package/dist/ralph/completion-audit.js.map +1 -0
  200. package/dist/ralph/persistence.d.ts +1 -1
  201. package/dist/ralph/persistence.d.ts.map +1 -1
  202. package/dist/ralph/persistence.js +8 -2
  203. package/dist/ralph/persistence.js.map +1 -1
  204. package/dist/scripts/__tests__/codex-native-hook.test.js +359 -24
  205. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  206. package/dist/scripts/__tests__/notify-dispatcher.test.d.ts +2 -0
  207. package/dist/scripts/__tests__/notify-dispatcher.test.d.ts.map +1 -0
  208. package/dist/scripts/__tests__/notify-dispatcher.test.js +126 -0
  209. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
  210. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  211. package/dist/scripts/codex-native-hook.js +142 -76
  212. package/dist/scripts/codex-native-hook.js.map +1 -1
  213. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  214. package/dist/scripts/codex-native-pre-post.js +4 -2
  215. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  216. package/dist/scripts/notify-dispatcher.d.ts +7 -0
  217. package/dist/scripts/notify-dispatcher.d.ts.map +1 -0
  218. package/dist/scripts/notify-dispatcher.js +87 -0
  219. package/dist/scripts/notify-dispatcher.js.map +1 -0
  220. package/dist/scripts/notify-fallback-watcher.js +4 -0
  221. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  222. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  223. package/dist/scripts/notify-hook/ralph-session-resume.js +96 -8
  224. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  225. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  226. package/dist/scripts/notify-hook/state-io.js +6 -2
  227. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  228. package/dist/scripts/notify-hook/visual-verdict.js +3 -3
  229. package/dist/scripts/notify-hook/visual-verdict.js.map +1 -1
  230. package/dist/scripts/notify-hook.js +127 -1
  231. package/dist/scripts/notify-hook.js.map +1 -1
  232. package/dist/state/__tests__/workflow-transition.test.js +102 -27
  233. package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
  234. package/dist/state/operations.d.ts.map +1 -1
  235. package/dist/state/operations.js +9 -3
  236. package/dist/state/operations.js.map +1 -1
  237. package/dist/state/skill-active.d.ts +7 -0
  238. package/dist/state/skill-active.d.ts.map +1 -1
  239. package/dist/state/skill-active.js +25 -8
  240. package/dist/state/skill-active.js.map +1 -1
  241. package/dist/state/workflow-transition-reconcile.d.ts +1 -0
  242. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  243. package/dist/state/workflow-transition-reconcile.js +22 -15
  244. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  245. package/dist/state/workflow-transition.js +3 -3
  246. package/dist/state/workflow-transition.js.map +1 -1
  247. package/dist/team/__tests__/approved-execution.test.js +84 -1
  248. package/dist/team/__tests__/approved-execution.test.js.map +1 -1
  249. package/dist/team/__tests__/runtime.test.js +178 -19
  250. package/dist/team/__tests__/runtime.test.js.map +1 -1
  251. package/dist/team/__tests__/scaling.test.js +497 -2
  252. package/dist/team/__tests__/scaling.test.js.map +1 -1
  253. package/dist/team/__tests__/state-root.test.js +1 -1
  254. package/dist/team/__tests__/state-root.test.js.map +1 -1
  255. package/dist/team/__tests__/worker-bootstrap.test.js +45 -0
  256. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  257. package/dist/team/approved-execution.d.ts +1 -0
  258. package/dist/team/approved-execution.d.ts.map +1 -1
  259. package/dist/team/approved-execution.js +53 -0
  260. package/dist/team/approved-execution.js.map +1 -1
  261. package/dist/team/delivery-log.d.ts.map +1 -1
  262. package/dist/team/delivery-log.js +8 -1
  263. package/dist/team/delivery-log.js.map +1 -1
  264. package/dist/team/runtime.d.ts.map +1 -1
  265. package/dist/team/runtime.js +104 -18
  266. package/dist/team/runtime.js.map +1 -1
  267. package/dist/team/scaling.d.ts.map +1 -1
  268. package/dist/team/scaling.js +43 -0
  269. package/dist/team/scaling.js.map +1 -1
  270. package/dist/team/state/mailbox.d.ts +1 -0
  271. package/dist/team/state/mailbox.d.ts.map +1 -1
  272. package/dist/team/state/mailbox.js +10 -1
  273. package/dist/team/state/mailbox.js.map +1 -1
  274. package/dist/team/state-root.d.ts.map +1 -1
  275. package/dist/team/state-root.js +5 -1
  276. package/dist/team/state-root.js.map +1 -1
  277. package/dist/team/state.d.ts.map +1 -1
  278. package/dist/team/state.js +3 -7
  279. package/dist/team/state.js.map +1 -1
  280. package/dist/team/worker-bootstrap.d.ts +7 -2
  281. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  282. package/dist/team/worker-bootstrap.js +17 -4
  283. package/dist/team/worker-bootstrap.js.map +1 -1
  284. package/dist/ultragoal/__tests__/artifacts.test.js +124 -1
  285. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  286. package/dist/ultragoal/__tests__/docs-contract.test.js +21 -0
  287. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  288. package/dist/ultragoal/artifacts.d.ts +44 -2
  289. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  290. package/dist/ultragoal/artifacts.js +197 -13
  291. package/dist/ultragoal/artifacts.js.map +1 -1
  292. package/dist/wiki/lifecycle.js +1 -1
  293. package/dist/wiki/lifecycle.js.map +1 -1
  294. package/package.json +1 -1
  295. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  296. package/plugins/oh-my-codex/.mcp.json +5 -5
  297. package/plugins/oh-my-codex/skills/analyze/SKILL.md +0 -2
  298. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +2 -2
  299. package/plugins/oh-my-codex/skills/code-review/SKILL.md +1 -3
  300. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +5 -7
  301. package/plugins/oh-my-codex/skills/doctor/SKILL.md +2 -2
  302. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +3 -3
  303. package/plugins/oh-my-codex/skills/pipeline/SKILL.md +3 -3
  304. package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -6
  305. package/plugins/oh-my-codex/skills/ralph/SKILL.md +9 -10
  306. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +36 -3
  307. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +21 -24
  308. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +8 -8
  309. package/plugins/oh-my-codex/skills/wiki/SKILL.md +13 -13
  310. package/skills/analyze/SKILL.md +0 -2
  311. package/skills/ask-claude/SKILL.md +5 -3
  312. package/skills/ask-gemini/SKILL.md +5 -3
  313. package/skills/autopilot/SKILL.md +2 -2
  314. package/skills/code-review/SKILL.md +1 -3
  315. package/skills/deep-interview/SKILL.md +5 -7
  316. package/skills/doctor/SKILL.md +2 -2
  317. package/skills/ecomode/SKILL.md +105 -1
  318. package/skills/frontend-ui-ux/SKILL.md +4 -26
  319. package/skills/git-master/SKILL.md +2 -4
  320. package/skills/omx-setup/SKILL.md +3 -3
  321. package/skills/pipeline/SKILL.md +3 -3
  322. package/skills/plan/SKILL.md +3 -6
  323. package/skills/ralph/SKILL.md +9 -10
  324. package/skills/swarm/SKILL.md +5 -3
  325. package/skills/tdd/SKILL.md +95 -1
  326. package/skills/ultragoal/SKILL.md +36 -3
  327. package/skills/ultraqa/SKILL.md +21 -24
  328. package/skills/ultrawork/SKILL.md +8 -8
  329. package/skills/web-clone/SKILL.md +348 -1
  330. package/skills/wiki/SKILL.md +13 -13
  331. package/src/scripts/__tests__/codex-native-hook.test.ts +389 -24
  332. package/src/scripts/__tests__/notify-dispatcher.test.ts +153 -0
  333. package/src/scripts/codex-native-hook.ts +168 -64
  334. package/src/scripts/codex-native-pre-post.ts +4 -1
  335. package/src/scripts/notify-dispatcher.ts +113 -0
  336. package/src/scripts/notify-fallback-watcher.ts +6 -2
  337. package/src/scripts/notify-hook/ralph-session-resume.ts +117 -8
  338. package/src/scripts/notify-hook/state-io.ts +4 -2
  339. package/src/scripts/notify-hook/visual-verdict.ts +3 -3
  340. package/src/scripts/notify-hook.ts +119 -1
package/dist/cli/setup.js CHANGED
@@ -9,7 +9,7 @@ import { spawnSync } from "child_process";
9
9
  import { createInterface } from "readline/promises";
10
10
  import { homedir } from "os";
11
11
  import { codexHome, codexConfigPath, codexPromptsDir, codexAgentsDir, userSkillsDir, omxStateDir, detectLegacySkillRootOverlap, omxPlansDir, omxLogsDir, } from "../utils/paths.js";
12
- import { buildMergedConfig, getRootModelName, hasLegacyOmxTeamRunTable, stripExistingOmxBlocks, stripExistingSharedMcpRegistryBlock, stripOmxEnvSettings, stripOmxFeatureFlags, stripOmxSeededBehavioralDefaults, upsertPluginModeRuntimeFeatureFlags, upsertManagedCodexHookTrustState, stripManagedCodexHookTrustState, OMX_PLUGIN_DEVELOPER_INSTRUCTIONS, } from "../config/generator.js";
12
+ import { buildMergedConfig, getRootModelName, getRootTomlArray, hasLegacyOmxTeamRunTable, isOmxManagedNotifyCommand, sanitizePreviousNotifyCommand, stripExistingOmxBlocks, stripExistingSharedMcpRegistryBlock, mergeSharedMcpRegistryBlock, stripOmxEnvSettings, stripOmxFeatureFlags, stripOmxSeededBehavioralDefaults, upsertPluginModeRuntimeFeatureFlags, upsertManagedCodexHookTrustState, stripManagedCodexHookTrustState, OMX_PLUGIN_DEVELOPER_INSTRUCTIONS, } from "../config/generator.js";
13
13
  import { mergeManagedCodexHooksConfig } from "../config/codex-hooks.js";
14
14
  import { getLegacyUnifiedMcpRegistryCandidate, getUnifiedMcpRegistryCandidates, loadUnifiedMcpRegistry, planClaudeCodeMcpSettingsSync, } from "../config/mcp-registry.js";
15
15
  import { generateAgentToml } from "../agents/native-config.js";
@@ -22,8 +22,9 @@ import { tryReadCatalogManifest } from "../catalog/reader.js";
22
22
  import { DEFAULT_FRONTIER_MODEL } from "../config/models.js";
23
23
  import { addGeneratedAgentsMarker, hasOmxManagedAgentsSections, isOmxGeneratedAgentsMd, upsertManagedAgentsBlock, } from "../utils/agents-md.js";
24
24
  import { DEFAULT_HUD_CONFIG } from "../hud/types.js";
25
- import { SETUP_INSTALL_MODES, SETUP_SCOPES, getSetupScopeFilePath, readPersistedSetupPreferences, } from "./setup-preferences.js";
26
- import { OMX_LOCAL_MARKETPLACE_NAME, resolvePackagedOmxMarketplace, upsertLocalOmxMarketplaceRegistration, } from "./plugin-marketplace.js";
25
+ import { SETUP_INSTALL_MODES, SETUP_MCP_MODES, SETUP_SCOPES, getSetupScopeFilePath, readPersistedSetupPreferences, } from "./setup-preferences.js";
26
+ import { OMX_LOCAL_MARKETPLACE_NAME, resolvePackagedOmxMarketplace, upsertLocalOmxMarketplaceRegistration, upsertLocalOmxPluginEnablement, upsertLocalOmxPluginMcpServerEnablement, } from "./plugin-marketplace.js";
27
+ import { resolveCodexHookFeatureFlagForCli } from "./codex-feature-probe.js";
27
28
  async function resolveStatusLinePresetForSetup(projectRoot, options) {
28
29
  if (options.force) {
29
30
  return DEFAULT_HUD_CONFIG.statusLine.preset;
@@ -44,7 +45,7 @@ async function resolveStatusLinePresetForSetup(projectRoot, options) {
44
45
  return undefined;
45
46
  }
46
47
  import { resolveAgentsModelTableContext, upsertAgentsModelTable, } from "../utils/agents-model-table.js";
47
- export { SETUP_INSTALL_MODES, SETUP_SCOPES };
48
+ export { SETUP_INSTALL_MODES, SETUP_MCP_MODES, SETUP_SCOPES };
48
49
  const PROJECT_GITIGNORE_ENTRIES = [
49
50
  ".omx/",
50
51
  ".codex/*",
@@ -58,6 +59,7 @@ const PROJECT_GITIGNORE_ENTRIES = [
58
59
  ];
59
60
  const LEGACY_PROJECT_GITIGNORE_ENTRIES = [".codex/"];
60
61
  const SETUP_ONLY_INSTALLABLE_SKILLS = new Set(["wiki"]);
62
+ const DEFAULT_SETUP_MCP_MODE = "none";
61
63
  const HARD_DEPRECATED_SKILL_NAMES = new Set(["web-clone"]);
62
64
  function isCatalogInstallableStatus(status) {
63
65
  return status === "active" || status === "internal";
@@ -354,6 +356,7 @@ function formatPersistedSetupPreferenceSummary(preferences) {
354
356
  return [
355
357
  `scope=${preferences.scope ?? "not recorded"}`,
356
358
  `installMode=${preferences.installMode ?? "not recorded"}`,
359
+ `mcpMode=${preferences.mcpMode ?? "not recorded"}`,
357
360
  ].join(", ");
358
361
  }
359
362
  async function promptForPersistedSetupReview(preferences) {
@@ -628,6 +631,17 @@ async function refreshOmxPluginDiscoveryCache(pkgRoot, options) {
628
631
  staleDirs,
629
632
  };
630
633
  }
634
+ function resolveSetupMcpMode(scope, requestedMcpMode, persistedReviewDecision, persistedPreferences) {
635
+ if (requestedMcpMode) {
636
+ return { mcpMode: requestedMcpMode, source: "cli" };
637
+ }
638
+ if (persistedPreferences?.mcpMode &&
639
+ persistedReviewDecision === "keep" &&
640
+ persistedPreferences.scope === scope) {
641
+ return { mcpMode: persistedPreferences.mcpMode, source: "persisted" };
642
+ }
643
+ return { mcpMode: DEFAULT_SETUP_MCP_MODE, source: "default" };
644
+ }
631
645
  async function resolveSetupInstallMode(projectRoot, scope, requestedInstallMode, installModePrompt, persistedReviewDecision = "keep", persistedPreferences) {
632
646
  if (requestedInstallMode) {
633
647
  return { installMode: requestedInstallMode, source: "cli" };
@@ -888,7 +902,7 @@ function insertRootTomlKey(config, line) {
888
902
  const after = lines.slice(firstTableIndex);
889
903
  return [...before, line, "", ...after].join("\n") + "\n";
890
904
  }
891
- async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, backupContext, summary, options) {
905
+ async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, mcpMode, backupContext, summary, options) {
892
906
  const packagedMarketplace = await resolvePackagedOmxMarketplace(pkgRoot);
893
907
  if (!packagedMarketplace) {
894
908
  summary.skipped += 1;
@@ -897,7 +911,7 @@ async function ensurePluginMarketplaceRegistration(configPath, pkgRoot, backupCo
897
911
  const existingConfig = existsSync(configPath)
898
912
  ? await readFile(configPath, "utf-8")
899
913
  : "";
900
- const nextConfig = upsertLocalOmxMarketplaceRegistration(existingConfig, pkgRoot);
914
+ const nextConfig = upsertLocalOmxMarketplaceRegistration(upsertLocalOmxPluginMcpServerEnablement(upsertLocalOmxPluginEnablement(existingConfig), mcpMode === "compat"), pkgRoot);
901
915
  const destinationExists = existsSync(configPath);
902
916
  if (nextConfig === existingConfig) {
903
917
  summary.unchanged += 1;
@@ -920,7 +934,7 @@ async function applyPluginModeHooksConfig(configPath, hooksPath, pkgRoot, backup
920
934
  const existingConfig = existsSync(configPath)
921
935
  ? await readFile(configPath, "utf-8")
922
936
  : "";
923
- const nextConfig = upsertManagedCodexHookTrustState(upsertPluginModeRuntimeFeatureFlags(stripManagedCodexHookTrustState(existingConfig)), pkgRoot, hooksPath);
937
+ const nextConfig = upsertManagedCodexHookTrustState(upsertPluginModeRuntimeFeatureFlags(stripManagedCodexHookTrustState(existingConfig), options.codexHookFeatureFlag), pkgRoot, hooksPath);
924
938
  if (nextConfig !== existingConfig) {
925
939
  if (await ensureBackup(configPath, existsSync(configPath), backupContext, options)) {
926
940
  summary.backedUp += 1;
@@ -1028,7 +1042,7 @@ async function cleanupPluginModeLegacyAgentsMd(agentsMdPath, backupContext, opti
1028
1042
  return true;
1029
1043
  }
1030
1044
  export async function setup(options = {}) {
1031
- const { force = false, dryRun = false, installMode: requestedInstallMode, scope: requestedScope, verbose = false, setupScopePrompt, persistedSetupReviewPrompt, installModePrompt, modelUpgradePrompt, pluginAgentsMdPrompt, pluginDeveloperInstructionsPrompt, pluginDeveloperInstructionsOverwritePrompt, } = options;
1045
+ const { force = false, dryRun = false, installMode: requestedInstallMode, mcpMode: requestedMcpMode, scope: requestedScope, verbose = false, setupScopePrompt, persistedSetupReviewPrompt, installModePrompt, modelUpgradePrompt, pluginAgentsMdPrompt, pluginDeveloperInstructionsPrompt, pluginDeveloperInstructionsOverwritePrompt, } = options;
1032
1046
  const pkgRoot = getPackageRoot();
1033
1047
  const projectRoot = process.cwd();
1034
1048
  const persistedPreferences = await readPersistedSetupPreferences(projectRoot, { warnOnLegacyScope: true });
@@ -1039,8 +1053,12 @@ export async function setup(options = {}) {
1039
1053
  Boolean(persistedPreferences?.installMode) &&
1040
1054
  (!persistedPreferences?.scope ||
1041
1055
  persistedPreferences.scope === effectiveScopeForInstallMode);
1056
+ const wouldUsePersistedMcpMode = !requestedMcpMode &&
1057
+ Boolean(persistedPreferences?.mcpMode) &&
1058
+ (!persistedPreferences?.scope ||
1059
+ persistedPreferences.scope === effectiveScopeForInstallMode);
1042
1060
  const shouldReviewPersistedSetup = hasPersistedSetupPreferences(persistedPreferences) &&
1043
- (wouldUsePersistedScope || wouldUsePersistedInstallMode) &&
1061
+ (wouldUsePersistedScope || wouldUsePersistedInstallMode || wouldUsePersistedMcpMode) &&
1044
1062
  (typeof persistedSetupReviewPrompt === "function" ||
1045
1063
  (process.stdin.isTTY && process.stdout.isTTY));
1046
1064
  if (shouldReviewPersistedSetup) {
@@ -1051,6 +1069,7 @@ export async function setup(options = {}) {
1051
1069
  }
1052
1070
  const resolvedScope = await resolveSetupScope(projectRoot, requestedScope, persistedReviewDecision, persistedPreferences, setupScopePrompt);
1053
1071
  const resolvedInstallMode = await resolveSetupInstallMode(projectRoot, resolvedScope.scope, requestedInstallMode, installModePrompt, persistedReviewDecision, persistedPreferences);
1072
+ const resolvedMcpMode = resolveSetupMcpMode(resolvedScope.scope, requestedMcpMode, persistedReviewDecision, persistedPreferences);
1054
1073
  const scopeDirs = resolveScopeDirectories(resolvedScope.scope, projectRoot);
1055
1074
  const scopeSourceMessage = resolvedScope.source === "persisted" ? " (from .omx/setup-scope.json)" : "";
1056
1075
  const backupContext = getBackupContext(resolvedScope.scope, projectRoot);
@@ -1077,6 +1096,10 @@ export async function setup(options = {}) {
1077
1096
  : "";
1078
1097
  console.log(`Using setup install mode: ${resolvedInstallMode.installMode}${installModeSourceMessage}\n`);
1079
1098
  }
1099
+ const mcpModeSourceMessage = resolvedMcpMode.source === "persisted"
1100
+ ? " (from .omx/setup-scope.json)"
1101
+ : "";
1102
+ console.log(`Using setup MCP mode: ${resolvedMcpMode.mcpMode}${mcpModeSourceMessage}\n`);
1080
1103
  // Step 1: Ensure directories exist
1081
1104
  console.log("[1/8] Creating directories...");
1082
1105
  const dirs = isPluginInstallMode
@@ -1102,16 +1125,15 @@ export async function setup(options = {}) {
1102
1125
  if (verbose)
1103
1126
  console.log(` mkdir ${dir}`);
1104
1127
  }
1105
- const setupPreferencesToPersist = resolvedInstallMode &&
1106
- (resolvedScope.scope === "user" ||
1107
- resolvedInstallMode.installMode === "plugin")
1108
- ? {
1109
- scope: resolvedScope.scope,
1110
- installMode: resolvedInstallMode.installMode,
1111
- }
1112
- : {
1113
- scope: resolvedScope.scope,
1114
- };
1128
+ const setupPreferencesToPersist = {
1129
+ scope: resolvedScope.scope,
1130
+ mcpMode: resolvedMcpMode.mcpMode,
1131
+ ...(resolvedInstallMode &&
1132
+ (resolvedScope.scope === "user" ||
1133
+ resolvedInstallMode.installMode === "plugin")
1134
+ ? { installMode: resolvedInstallMode.installMode }
1135
+ : {}),
1136
+ };
1115
1137
  await persistSetupPreferences(projectRoot, setupPreferencesToPersist, {
1116
1138
  dryRun,
1117
1139
  verbose,
@@ -1217,6 +1239,35 @@ export async function setup(options = {}) {
1217
1239
  console.log("[5/8] Updating config.toml...");
1218
1240
  let resolvedConfig = "";
1219
1241
  let omxManagesTui = false;
1242
+ const codexHookFeatureFlag = resolveCodexHookFeatureFlagForCli({
1243
+ codexFeaturesProbe: options.codexFeaturesProbe,
1244
+ codexVersionProbe: options.codexVersionProbe,
1245
+ });
1246
+ if (verbose) {
1247
+ console.log(` Native Codex hook feature flag: [features].${codexHookFeatureFlag}`);
1248
+ }
1249
+ const shouldSyncSharedMcpRegistry = resolvedMcpMode.mcpMode === "compat";
1250
+ const registryCandidates = getUnifiedMcpRegistryCandidates();
1251
+ const defaultRegistryCandidates = registryCandidates.slice(0, 1);
1252
+ const sharedMcpRegistry = shouldSyncSharedMcpRegistry
1253
+ ? await loadUnifiedMcpRegistry({
1254
+ candidates: options.mcpRegistryCandidates ?? defaultRegistryCandidates,
1255
+ })
1256
+ : { servers: [], warnings: [] };
1257
+ const legacyRegistryCandidate = getLegacyUnifiedMcpRegistryCandidate();
1258
+ if (shouldSyncSharedMcpRegistry &&
1259
+ !options.mcpRegistryCandidates &&
1260
+ !sharedMcpRegistry.sourcePath &&
1261
+ existsSync(legacyRegistryCandidate) &&
1262
+ !existsSync(defaultRegistryCandidates[0])) {
1263
+ console.log(` warning: legacy shared MCP registry detected at ${legacyRegistryCandidate} but ignored by default; move or copy it to ${defaultRegistryCandidates[0]} and rerun setup with --mcp compat if you still want setup to sync those servers`);
1264
+ }
1265
+ if (verbose && sharedMcpRegistry.sourcePath) {
1266
+ console.log(` shared MCP registry: ${sharedMcpRegistry.sourcePath} (${sharedMcpRegistry.servers.length} servers)`);
1267
+ }
1268
+ for (const warning of sharedMcpRegistry.warnings) {
1269
+ console.log(` warning: ${warning}`);
1270
+ }
1220
1271
  if (isPluginInstallMode) {
1221
1272
  const configCleaned = await cleanupPluginModeLegacyConfig(scopeDirs.codexConfigFile, backupContext, { dryRun, verbose });
1222
1273
  if (configCleaned)
@@ -1224,8 +1275,8 @@ export async function setup(options = {}) {
1224
1275
  console.log(configCleaned
1225
1276
  ? ` ${dryRun ? "Would clean" : "Cleaned"} legacy OMX config entries for plugin mode.\n`
1226
1277
  : " Config refresh skipped; no legacy OMX config entries found.\n");
1227
- await applyPluginModeHooksConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, backupContext, summary.config, { dryRun, verbose });
1228
- const pluginMarketplaceResult = await ensurePluginMarketplaceRegistration(scopeDirs.codexConfigFile, pkgRoot, backupContext, summary.config, { dryRun, verbose });
1278
+ await applyPluginModeHooksConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, backupContext, summary.config, { dryRun, verbose, codexHookFeatureFlag });
1279
+ const pluginMarketplaceResult = await ensurePluginMarketplaceRegistration(scopeDirs.codexConfigFile, pkgRoot, resolvedMcpMode.mcpMode, backupContext, summary.config, { dryRun, verbose });
1229
1280
  if (pluginMarketplaceResult === "unavailable") {
1230
1281
  console.log(` warning: packaged ${OMX_LOCAL_MARKETPLACE_NAME} Codex plugin marketplace metadata not found; /skills plugin discovery was not registered.`);
1231
1282
  }
@@ -1245,10 +1296,16 @@ export async function setup(options = {}) {
1245
1296
  else if (pluginCacheRefresh.status === "unchanged") {
1246
1297
  console.log(" Codex plugin discovery cache already matches packaged plugin metadata.");
1247
1298
  }
1299
+ if (shouldSyncSharedMcpRegistry) {
1300
+ resolvedConfig = await syncSharedMcpRegistryIntoConfig(scopeDirs.codexConfigFile, sharedMcpRegistry, summary.config, backupContext, { dryRun, verbose });
1301
+ if (resolvedScope.scope === "user") {
1302
+ await syncClaudeCodeMcpSettings(sharedMcpRegistry, summary.config, backupContext, { dryRun, verbose });
1303
+ }
1304
+ }
1248
1305
  resolvedConfig = existsSync(scopeDirs.codexConfigFile)
1249
1306
  ? await readFile(scopeDirs.codexConfigFile, "utf-8")
1250
1307
  : "";
1251
- console.log(` Native Codex hooks and runtime feature flags refresh complete (${scopeDirs.codexHooksFile}; codex_hooks, goals).\n`);
1308
+ console.log(` Native Codex hooks and runtime feature flags refresh complete (${scopeDirs.codexHooksFile}; hooks, goals).\n`);
1252
1309
  if (usePluginDeveloperInstructionsDefault) {
1253
1310
  const developerInstructionsResult = await applyPluginDeveloperInstructionsDefault(scopeDirs.codexConfigFile, backupContext, summary.config, {
1254
1311
  dryRun,
@@ -1270,38 +1327,21 @@ export async function setup(options = {}) {
1270
1327
  }
1271
1328
  }
1272
1329
  else {
1273
- const registryCandidates = getUnifiedMcpRegistryCandidates();
1274
- const defaultRegistryCandidates = registryCandidates.slice(0, 1);
1275
- const legacyRegistryCandidate = getLegacyUnifiedMcpRegistryCandidate();
1276
- const sharedMcpRegistry = await loadUnifiedMcpRegistry({
1277
- candidates: options.mcpRegistryCandidates ?? defaultRegistryCandidates,
1278
- });
1279
- if (!options.mcpRegistryCandidates &&
1280
- !sharedMcpRegistry.sourcePath &&
1281
- existsSync(legacyRegistryCandidate) &&
1282
- !existsSync(defaultRegistryCandidates[0])) {
1283
- console.log(` warning: legacy shared MCP registry detected at ${legacyRegistryCandidate} but ignored by default; move it to ${defaultRegistryCandidates[0]} if you still want setup to sync those servers`);
1284
- }
1285
- if (verbose && sharedMcpRegistry.sourcePath) {
1286
- console.log(` shared MCP registry: ${sharedMcpRegistry.sourcePath} (${sharedMcpRegistry.servers.length} servers)`);
1287
- }
1288
- for (const warning of sharedMcpRegistry.warnings) {
1289
- console.log(` warning: ${warning}`);
1290
- }
1291
1330
  const statusLinePreset = await resolveStatusLinePresetForSetup(projectRoot, { force });
1292
- const managedConfig = await updateManagedConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, sharedMcpRegistry, summary.config, backupContext, {
1331
+ const managedConfig = await updateManagedConfig(scopeDirs.codexConfigFile, scopeDirs.codexHooksFile, pkgRoot, sharedMcpRegistry, resolvedMcpMode.mcpMode, resolvedScope.scope, scopeDirs.codexHomeDir, summary.config, backupContext, {
1293
1332
  dryRun,
1294
1333
  modelUpgradePrompt,
1295
1334
  verbose,
1296
1335
  statusLinePreset,
1297
1336
  forceStatusLinePreset: force,
1337
+ codexHookFeatureFlag,
1298
1338
  });
1299
1339
  resolvedConfig = managedConfig.finalConfig;
1300
1340
  omxManagesTui = managedConfig.omxManagesTui;
1301
1341
  if (managedConfig.repairedLegacyTeamRunTable) {
1302
1342
  console.log(" Removed retired [mcp_servers.omx_team_run] config during refresh.");
1303
1343
  }
1304
- if (resolvedScope.scope === "user") {
1344
+ if (shouldSyncSharedMcpRegistry && resolvedScope.scope === "user") {
1305
1345
  await syncClaudeCodeMcpSettings(sharedMcpRegistry, summary.config, backupContext, { dryRun, verbose });
1306
1346
  }
1307
1347
  console.log(` Config refresh complete (${scopeDirs.codexConfigFile}).\n`);
@@ -2031,7 +2071,69 @@ async function cleanupLegacyManagedSkills(srcDir, dstDir, backupContext, options
2031
2071
  }
2032
2072
  return result;
2033
2073
  }
2034
- async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegistry, summary, backupContext, options) {
2074
+ function getNotifyMetadataPath(codexHomeDir) {
2075
+ return join(codexHomeDir, ".omx", "notify-dispatch.json");
2076
+ }
2077
+ async function buildNotifyMergePlan(existingConfig, pkgRoot, codexHomeDir, scope) {
2078
+ if (scope === "project") {
2079
+ return { notifyCommand: false };
2080
+ }
2081
+ const omxNotify = ["node", join(pkgRoot, "dist", "scripts", "notify-hook.js")];
2082
+ const metadataPath = getNotifyMetadataPath(codexHomeDir);
2083
+ const dispatcherNotify = [
2084
+ "node",
2085
+ join(pkgRoot, "dist", "scripts", "notify-dispatcher.js"),
2086
+ "--metadata",
2087
+ metadataPath,
2088
+ ];
2089
+ const existingNotify = getRootTomlArray(existingConfig, "notify");
2090
+ if (!existingNotify) {
2091
+ return { notifyCommand: omxNotify };
2092
+ }
2093
+ if (isOmxManagedNotifyCommand(existingNotify, pkgRoot)) {
2094
+ if (!existingNotify.some((part) => /(?:^|[\\/])notify-dispatcher\.js$/.test(part))) {
2095
+ return { notifyCommand: omxNotify };
2096
+ }
2097
+ try {
2098
+ const metadata = JSON.parse(await readFile(metadataPath, "utf-8"));
2099
+ const previousNotify = metadata.previousNotify;
2100
+ if (Array.isArray(previousNotify) &&
2101
+ previousNotify.every((item) => typeof item === "string")) {
2102
+ const sanitizedPreviousNotify = sanitizePreviousNotifyCommand(previousNotify, pkgRoot);
2103
+ if (!sanitizedPreviousNotify) {
2104
+ return { notifyCommand: omxNotify };
2105
+ }
2106
+ return {
2107
+ notifyCommand: dispatcherNotify,
2108
+ metadataPath,
2109
+ metadata: {
2110
+ managedBy: "oh-my-codex",
2111
+ version: 1,
2112
+ previousNotify: sanitizedPreviousNotify,
2113
+ omxNotify,
2114
+ dispatcherNotify,
2115
+ },
2116
+ };
2117
+ }
2118
+ }
2119
+ catch {
2120
+ // Missing dispatcher metadata: fall back to plain OMX notify instead of nesting.
2121
+ }
2122
+ return { notifyCommand: omxNotify };
2123
+ }
2124
+ return {
2125
+ notifyCommand: dispatcherNotify,
2126
+ metadataPath,
2127
+ metadata: {
2128
+ managedBy: "oh-my-codex",
2129
+ version: 1,
2130
+ previousNotify: sanitizePreviousNotifyCommand(existingNotify, pkgRoot),
2131
+ omxNotify,
2132
+ dispatcherNotify,
2133
+ },
2134
+ };
2135
+ }
2136
+ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegistry, mcpMode, scope, codexHomeDir, summary, backupContext, options) {
2035
2137
  const existing = existsSync(configPath)
2036
2138
  ? await readFile(configPath, "utf-8")
2037
2139
  : "";
@@ -2051,15 +2153,19 @@ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegi
2051
2153
  }
2052
2154
  }
2053
2155
  }
2156
+ const notifyPlan = await buildNotifyMergePlan(existing, pkgRoot, codexHomeDir, scope);
2054
2157
  const finalConfig = buildMergedConfig(existing, pkgRoot, {
2055
2158
  includeTui: omxManagesTui,
2056
2159
  codexHooksFile: hooksPath,
2160
+ codexHookFeatureFlag: options.codexHookFeatureFlag,
2057
2161
  modelOverride,
2058
2162
  sharedMcpServers: sharedMcpRegistry.servers,
2059
2163
  sharedMcpRegistrySource: sharedMcpRegistry.sourcePath,
2060
2164
  verbose: options.verbose,
2061
2165
  statusLinePreset: options.statusLinePreset,
2062
2166
  forceStatusLinePreset: options.forceStatusLinePreset,
2167
+ notifyCommand: notifyPlan.notifyCommand,
2168
+ includeFirstPartyMcp: mcpMode === "compat",
2063
2169
  });
2064
2170
  const changed = existing !== finalConfig;
2065
2171
  if (!changed) {
@@ -2075,6 +2181,10 @@ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegi
2075
2181
  }
2076
2182
  if (!options.dryRun) {
2077
2183
  await writeFile(configPath, finalConfig);
2184
+ if (notifyPlan.metadataPath && notifyPlan.metadata) {
2185
+ await mkdir(dirname(notifyPlan.metadataPath), { recursive: true });
2186
+ await writeFile(notifyPlan.metadataPath, JSON.stringify(notifyPlan.metadata, null, 2) + "\n");
2187
+ }
2078
2188
  }
2079
2189
  if (options.verbose &&
2080
2190
  modelOverride &&
@@ -2092,6 +2202,30 @@ async function updateManagedConfig(configPath, hooksPath, pkgRoot, sharedMcpRegi
2092
2202
  repairedLegacyTeamRunTable: hadLegacyTeamRunTable && !hasLegacyOmxTeamRunTable(finalConfig),
2093
2203
  };
2094
2204
  }
2205
+ async function syncSharedMcpRegistryIntoConfig(configPath, sharedMcpRegistry, summary, backupContext, options) {
2206
+ if (sharedMcpRegistry.servers.length === 0) {
2207
+ return existsSync(configPath) ? await readFile(configPath, "utf-8") : "";
2208
+ }
2209
+ const existing = existsSync(configPath)
2210
+ ? await readFile(configPath, "utf-8")
2211
+ : "";
2212
+ const finalConfig = mergeSharedMcpRegistryBlock(existing, sharedMcpRegistry.servers, sharedMcpRegistry.sourcePath);
2213
+ if (existing === finalConfig) {
2214
+ summary.unchanged += 1;
2215
+ return finalConfig;
2216
+ }
2217
+ if (await ensureBackup(configPath, existsSync(configPath), backupContext, options)) {
2218
+ summary.backedUp += 1;
2219
+ }
2220
+ if (!options.dryRun) {
2221
+ await writeFile(configPath, finalConfig);
2222
+ }
2223
+ summary.updated += 1;
2224
+ if (options.verbose) {
2225
+ console.log(` ${options.dryRun ? "would sync" : "synced"} shared MCP registry servers into ${configPath}`);
2226
+ }
2227
+ return finalConfig;
2228
+ }
2095
2229
  function getClaudeCodeSettingsPath(homeDir = homedir()) {
2096
2230
  return join(homeDir, ".claude", "settings.json");
2097
2231
  }