oh-my-codex 0.16.3 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (339) 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__/generator.test.js +2 -0
  5. package/dist/catalog/__tests__/generator.test.js.map +1 -1
  6. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -0
  7. package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
  8. package/dist/cli/__tests__/cleanup.test.js +27 -0
  9. package/dist/cli/__tests__/cleanup.test.js.map +1 -1
  10. package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -5
  11. package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
  12. package/dist/cli/__tests__/doctor-warning-copy.test.js +175 -7
  13. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  14. package/dist/cli/__tests__/index.test.js +147 -12
  15. package/dist/cli/__tests__/index.test.js.map +1 -1
  16. package/dist/cli/__tests__/mcp-serve.test.js +4 -0
  17. package/dist/cli/__tests__/mcp-serve.test.js.map +1 -1
  18. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +2 -0
  19. package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
  20. package/dist/cli/__tests__/ralph.test.js +47 -0
  21. package/dist/cli/__tests__/ralph.test.js.map +1 -1
  22. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +10 -5
  23. package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
  24. package/dist/cli/__tests__/setup-install-mode.test.js +299 -27
  25. package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
  26. package/dist/cli/__tests__/setup-refresh.test.js +85 -3
  27. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  28. package/dist/cli/__tests__/setup-scope.test.js +1 -1
  29. package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
  30. package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -1
  31. package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
  32. package/dist/cli/__tests__/team.test.js +108 -0
  33. package/dist/cli/__tests__/team.test.js.map +1 -1
  34. package/dist/cli/__tests__/ultragoal.test.js +91 -0
  35. package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
  36. package/dist/cli/__tests__/uninstall.test.js +54 -8
  37. package/dist/cli/__tests__/uninstall.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 +214 -23
  48. package/dist/cli/doctor.js.map +1 -1
  49. package/dist/cli/index.d.ts +17 -4
  50. package/dist/cli/index.d.ts.map +1 -1
  51. package/dist/cli/index.js +152 -24
  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/mcp-serve.d.ts.map +1 -1
  56. package/dist/cli/mcp-serve.js +4 -0
  57. package/dist/cli/mcp-serve.js.map +1 -1
  58. package/dist/cli/plugin-marketplace.d.ts +23 -0
  59. package/dist/cli/plugin-marketplace.d.ts.map +1 -1
  60. package/dist/cli/plugin-marketplace.js +203 -1
  61. package/dist/cli/plugin-marketplace.js.map +1 -1
  62. package/dist/cli/ralph.d.ts.map +1 -1
  63. package/dist/cli/ralph.js +21 -0
  64. package/dist/cli/ralph.js.map +1 -1
  65. package/dist/cli/setup-preferences.d.ts +4 -0
  66. package/dist/cli/setup-preferences.d.ts.map +1 -1
  67. package/dist/cli/setup-preferences.js +7 -0
  68. package/dist/cli/setup-preferences.js.map +1 -1
  69. package/dist/cli/setup.d.ts +5 -3
  70. package/dist/cli/setup.d.ts.map +1 -1
  71. package/dist/cli/setup.js +140 -51
  72. package/dist/cli/setup.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 +70 -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 +12 -3
  80. package/dist/cli/uninstall.js.map +1 -1
  81. package/dist/config/__tests__/codex-feature-flags.test.d.ts +2 -0
  82. package/dist/config/__tests__/codex-feature-flags.test.d.ts.map +1 -0
  83. package/dist/config/__tests__/codex-feature-flags.test.js +35 -0
  84. package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
  85. package/dist/config/__tests__/codex-hooks.test.js +143 -9
  86. package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
  87. package/dist/config/__tests__/generator-idempotent.test.js +85 -9
  88. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  89. package/dist/config/__tests__/generator-notify.test.js +116 -11
  90. package/dist/config/__tests__/generator-notify.test.js.map +1 -1
  91. package/dist/config/__tests__/wiki-config-contract.test.js +6 -3
  92. package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -1
  93. package/dist/config/codex-feature-flags.d.ts +21 -0
  94. package/dist/config/codex-feature-flags.d.ts.map +1 -0
  95. package/dist/config/codex-feature-flags.js +56 -0
  96. package/dist/config/codex-feature-flags.js.map +1 -0
  97. package/dist/config/codex-hooks.d.ts +14 -13
  98. package/dist/config/codex-hooks.d.ts.map +1 -1
  99. package/dist/config/codex-hooks.js +108 -8
  100. package/dist/config/codex-hooks.js.map +1 -1
  101. package/dist/config/generator.d.ts +15 -3
  102. package/dist/config/generator.d.ts.map +1 -1
  103. package/dist/config/generator.js +233 -129
  104. package/dist/config/generator.js.map +1 -1
  105. package/dist/config/omx-first-party-mcp.d.ts +3 -1
  106. package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
  107. package/dist/config/omx-first-party-mcp.js +9 -2
  108. package/dist/config/omx-first-party-mcp.js.map +1 -1
  109. package/dist/hooks/__tests__/design-skill.test.d.ts +2 -0
  110. package/dist/hooks/__tests__/design-skill.test.d.ts.map +1 -0
  111. package/dist/hooks/__tests__/design-skill.test.js +55 -0
  112. package/dist/hooks/__tests__/design-skill.test.js.map +1 -0
  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-hook-non-omx-guard.test.js +125 -1
  116. package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
  117. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +265 -0
  118. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  119. package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts +2 -0
  120. package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts.map +1 -0
  121. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +84 -0
  122. package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -0
  123. package/dist/hooks/__tests__/skill-guidance-contract.test.js +41 -0
  124. package/dist/hooks/__tests__/skill-guidance-contract.test.js.map +1 -1
  125. package/dist/hooks/agents-overlay.js +2 -2
  126. package/dist/hooks/agents-overlay.js.map +1 -1
  127. package/dist/hooks/keyword-detector.d.ts +1 -0
  128. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  129. package/dist/hooks/keyword-detector.js +12 -6
  130. package/dist/hooks/keyword-detector.js.map +1 -1
  131. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  132. package/dist/hooks/keyword-registry.js +2 -0
  133. package/dist/hooks/keyword-registry.js.map +1 -1
  134. package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
  135. package/dist/hooks/prompt-guidance-contract.js +47 -2
  136. package/dist/hooks/prompt-guidance-contract.js.map +1 -1
  137. package/dist/hud/__tests__/state.test.js +164 -0
  138. package/dist/hud/__tests__/state.test.js.map +1 -1
  139. package/dist/hud/state.d.ts.map +1 -1
  140. package/dist/hud/state.js +4 -5
  141. package/dist/hud/state.js.map +1 -1
  142. package/dist/mcp/__tests__/bootstrap.test.js +3 -0
  143. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  144. package/dist/mcp/__tests__/hermes-bridge.test.d.ts +2 -0
  145. package/dist/mcp/__tests__/hermes-bridge.test.d.ts.map +1 -0
  146. package/dist/mcp/__tests__/hermes-bridge.test.js +374 -0
  147. package/dist/mcp/__tests__/hermes-bridge.test.js.map +1 -0
  148. package/dist/mcp/__tests__/state-paths.test.js +155 -11
  149. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  150. package/dist/mcp/__tests__/state-server.test.js +166 -0
  151. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  152. package/dist/mcp/bootstrap.d.ts +1 -1
  153. package/dist/mcp/bootstrap.d.ts.map +1 -1
  154. package/dist/mcp/bootstrap.js +2 -0
  155. package/dist/mcp/bootstrap.js.map +1 -1
  156. package/dist/mcp/hermes-bridge.d.ts +81 -0
  157. package/dist/mcp/hermes-bridge.d.ts.map +1 -0
  158. package/dist/mcp/hermes-bridge.js +400 -0
  159. package/dist/mcp/hermes-bridge.js.map +1 -0
  160. package/dist/mcp/hermes-server.d.ts +269 -0
  161. package/dist/mcp/hermes-server.d.ts.map +1 -0
  162. package/dist/mcp/hermes-server.js +121 -0
  163. package/dist/mcp/hermes-server.js.map +1 -0
  164. package/dist/mcp/state-paths.d.ts.map +1 -1
  165. package/dist/mcp/state-paths.js +64 -11
  166. package/dist/mcp/state-paths.js.map +1 -1
  167. package/dist/modes/__tests__/base-session-scope.test.js +22 -0
  168. package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
  169. package/dist/modes/__tests__/base-tmux-pane.test.js +88 -27
  170. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  171. package/dist/modes/base.d.ts.map +1 -1
  172. package/dist/modes/base.js +5 -0
  173. package/dist/modes/base.js.map +1 -1
  174. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts +2 -0
  175. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts.map +1 -0
  176. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +316 -0
  177. package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -0
  178. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts +2 -0
  179. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts.map +1 -0
  180. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +481 -0
  181. package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
  182. package/dist/planning/__tests__/artifacts.test.js +533 -4
  183. package/dist/planning/__tests__/artifacts.test.js.map +1 -1
  184. package/dist/planning/__tests__/context-pack-status.test.js +524 -0
  185. package/dist/planning/__tests__/context-pack-status.test.js.map +1 -1
  186. package/dist/planning/__tests__/markdown-structure.test.d.ts +2 -0
  187. package/dist/planning/__tests__/markdown-structure.test.d.ts.map +1 -0
  188. package/dist/planning/__tests__/markdown-structure.test.js +459 -0
  189. package/dist/planning/__tests__/markdown-structure.test.js.map +1 -0
  190. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +523 -1
  191. package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +1 -1
  192. package/dist/planning/artifacts.d.ts +1 -1
  193. package/dist/planning/artifacts.d.ts.map +1 -1
  194. package/dist/planning/artifacts.js +227 -28
  195. package/dist/planning/artifacts.js.map +1 -1
  196. package/dist/planning/context-pack-status.d.ts +25 -0
  197. package/dist/planning/context-pack-status.d.ts.map +1 -1
  198. package/dist/planning/context-pack-status.js +272 -31
  199. package/dist/planning/context-pack-status.js.map +1 -1
  200. package/dist/planning/markdown-structure.d.ts +20 -0
  201. package/dist/planning/markdown-structure.d.ts.map +1 -0
  202. package/dist/planning/markdown-structure.js +137 -0
  203. package/dist/planning/markdown-structure.js.map +1 -0
  204. package/dist/ralph/__tests__/completion-audit.test.d.ts +2 -0
  205. package/dist/ralph/__tests__/completion-audit.test.d.ts.map +1 -0
  206. package/dist/ralph/__tests__/completion-audit.test.js +121 -0
  207. package/dist/ralph/__tests__/completion-audit.test.js.map +1 -0
  208. package/dist/ralph/completion-audit.d.ts +8 -0
  209. package/dist/ralph/completion-audit.d.ts.map +1 -0
  210. package/dist/ralph/completion-audit.js +99 -0
  211. package/dist/ralph/completion-audit.js.map +1 -0
  212. package/dist/scripts/__tests__/codex-native-hook.test.js +407 -15
  213. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  214. package/dist/scripts/__tests__/notify-dispatcher.test.d.ts +2 -0
  215. package/dist/scripts/__tests__/notify-dispatcher.test.d.ts.map +1 -0
  216. package/dist/scripts/__tests__/notify-dispatcher.test.js +126 -0
  217. package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
  218. package/dist/scripts/codex-native-hook.d.ts +1 -0
  219. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  220. package/dist/scripts/codex-native-hook.js +177 -71
  221. package/dist/scripts/codex-native-hook.js.map +1 -1
  222. package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
  223. package/dist/scripts/codex-native-pre-post.js +4 -2
  224. package/dist/scripts/codex-native-pre-post.js.map +1 -1
  225. package/dist/scripts/notify-dispatcher.js +30 -1
  226. package/dist/scripts/notify-dispatcher.js.map +1 -1
  227. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  228. package/dist/scripts/notify-hook/tmux-injection.js +91 -2
  229. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  230. package/dist/scripts/notify-hook.js +3 -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/mode-state-context.d.ts +2 -0
  235. package/dist/state/mode-state-context.d.ts.map +1 -1
  236. package/dist/state/mode-state-context.js +21 -0
  237. package/dist/state/mode-state-context.js.map +1 -1
  238. package/dist/state/operations.d.ts.map +1 -1
  239. package/dist/state/operations.js +9 -3
  240. package/dist/state/operations.js.map +1 -1
  241. package/dist/state/skill-active.d.ts +7 -0
  242. package/dist/state/skill-active.d.ts.map +1 -1
  243. package/dist/state/skill-active.js +25 -8
  244. package/dist/state/skill-active.js.map +1 -1
  245. package/dist/state/workflow-transition-reconcile.d.ts +1 -0
  246. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
  247. package/dist/state/workflow-transition-reconcile.js +22 -15
  248. package/dist/state/workflow-transition-reconcile.js.map +1 -1
  249. package/dist/state/workflow-transition.js +3 -3
  250. package/dist/state/workflow-transition.js.map +1 -1
  251. package/dist/team/__tests__/approved-execution.test.js +39 -0
  252. package/dist/team/__tests__/approved-execution.test.js.map +1 -1
  253. package/dist/team/__tests__/runtime.test.js +5 -0
  254. package/dist/team/__tests__/runtime.test.js.map +1 -1
  255. package/dist/team/__tests__/scaling.test.js +497 -2
  256. package/dist/team/__tests__/scaling.test.js.map +1 -1
  257. package/dist/team/__tests__/state-root.test.js +1 -1
  258. package/dist/team/__tests__/state-root.test.js.map +1 -1
  259. package/dist/team/__tests__/worker-bootstrap.test.js +8 -0
  260. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  261. package/dist/team/approved-execution.d.ts.map +1 -1
  262. package/dist/team/approved-execution.js +3 -0
  263. package/dist/team/approved-execution.js.map +1 -1
  264. package/dist/team/scaling.d.ts.map +1 -1
  265. package/dist/team/scaling.js +43 -0
  266. package/dist/team/scaling.js.map +1 -1
  267. package/dist/team/state-root.d.ts.map +1 -1
  268. package/dist/team/state-root.js +4 -0
  269. package/dist/team/state-root.js.map +1 -1
  270. package/dist/team/state.d.ts.map +1 -1
  271. package/dist/team/state.js +2 -6
  272. package/dist/team/state.js.map +1 -1
  273. package/dist/ultragoal/__tests__/artifacts.test.js +245 -1
  274. package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
  275. package/dist/ultragoal/__tests__/docs-contract.test.js +21 -0
  276. package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
  277. package/dist/ultragoal/artifacts.d.ts +52 -2
  278. package/dist/ultragoal/artifacts.d.ts.map +1 -1
  279. package/dist/ultragoal/artifacts.js +301 -15
  280. package/dist/ultragoal/artifacts.js.map +1 -1
  281. package/dist/utils/__tests__/paths.test.js +31 -1
  282. package/dist/utils/__tests__/paths.test.js.map +1 -1
  283. package/dist/utils/paths.d.ts +6 -0
  284. package/dist/utils/paths.d.ts.map +1 -1
  285. package/dist/utils/paths.js +18 -0
  286. package/dist/utils/paths.js.map +1 -1
  287. package/dist/wiki/lifecycle.js +4 -4
  288. package/dist/wiki/lifecycle.js.map +1 -1
  289. package/package.json +1 -1
  290. package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
  291. package/plugins/oh-my-codex/.mcp.json +13 -5
  292. package/plugins/oh-my-codex/skills/analyze/SKILL.md +0 -2
  293. package/plugins/oh-my-codex/skills/autopilot/SKILL.md +2 -2
  294. package/plugins/oh-my-codex/skills/code-review/SKILL.md +1 -3
  295. package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +5 -7
  296. package/plugins/oh-my-codex/skills/design/SKILL.md +180 -0
  297. package/plugins/oh-my-codex/skills/doctor/SKILL.md +2 -2
  298. package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +3 -3
  299. package/plugins/oh-my-codex/skills/pipeline/SKILL.md +3 -3
  300. package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -6
  301. package/plugins/oh-my-codex/skills/ralph/SKILL.md +9 -10
  302. package/plugins/oh-my-codex/skills/skill/SKILL.md +2 -1
  303. package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +36 -3
  304. package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +175 -64
  305. package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +8 -8
  306. package/plugins/oh-my-codex/skills/visual-ralph/SKILL.md +2 -2
  307. package/plugins/oh-my-codex/skills/wiki/SKILL.md +13 -13
  308. package/skills/analyze/SKILL.md +0 -2
  309. package/skills/ask-claude/SKILL.md +5 -3
  310. package/skills/ask-gemini/SKILL.md +5 -3
  311. package/skills/autopilot/SKILL.md +2 -2
  312. package/skills/code-review/SKILL.md +1 -3
  313. package/skills/deep-interview/SKILL.md +5 -7
  314. package/skills/design/SKILL.md +180 -0
  315. package/skills/doctor/SKILL.md +2 -2
  316. package/skills/ecomode/SKILL.md +105 -1
  317. package/skills/frontend-ui-ux/SKILL.md +6 -24
  318. package/skills/git-master/SKILL.md +2 -4
  319. package/skills/omx-setup/SKILL.md +3 -3
  320. package/skills/pipeline/SKILL.md +3 -3
  321. package/skills/plan/SKILL.md +3 -6
  322. package/skills/ralph/SKILL.md +9 -10
  323. package/skills/skill/SKILL.md +2 -1
  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 +175 -64
  328. package/skills/ultrawork/SKILL.md +8 -8
  329. package/skills/visual-ralph/SKILL.md +2 -2
  330. package/skills/web-clone/SKILL.md +348 -1
  331. package/skills/wiki/SKILL.md +13 -13
  332. package/src/scripts/__tests__/codex-native-hook.test.ts +437 -14
  333. package/src/scripts/__tests__/notify-dispatcher.test.ts +153 -0
  334. package/src/scripts/codex-native-hook.ts +205 -61
  335. package/src/scripts/codex-native-pre-post.ts +4 -1
  336. package/src/scripts/notify-dispatcher.ts +40 -1
  337. package/src/scripts/notify-hook/tmux-injection.ts +110 -3
  338. package/src/scripts/notify-hook.ts +3 -1
  339. package/templates/catalog-manifest.json +9 -2
@@ -13,6 +13,7 @@ interface NotifyDispatcherMetadata {
13
13
  version?: number;
14
14
  previousNotify?: string[] | null;
15
15
  omxNotify?: string[];
16
+ dispatcherNotify?: string[];
16
17
  }
17
18
 
18
19
  function parseArgs(): { metadataPath: string; payloadArg: string } {
@@ -36,6 +37,42 @@ function isCommand(value: unknown): value is string[] {
36
37
  );
37
38
  }
38
39
 
40
+ function sameCommand(
41
+ left: readonly string[] | null | undefined,
42
+ right: readonly string[] | null | undefined,
43
+ ): boolean {
44
+ if (!left || !right || left.length !== right.length) return false;
45
+ return left.every((part, index) => part === right[index]);
46
+ }
47
+
48
+ function resolveNotifyEntrypoint(command: readonly string[]): string | undefined {
49
+ if (!/(?:^|[\\/])node(?:\.exe)?$/i.test(command[0] ?? "")) {
50
+ return command[0];
51
+ }
52
+ return command.slice(1).find((arg) => !arg.startsWith("-"));
53
+ }
54
+
55
+ function isOmxManagedNotifyCommand(command: readonly string[] | null | undefined): boolean {
56
+ if (!command) return false;
57
+ const entrypoint = resolveNotifyEntrypoint(command);
58
+ if (!entrypoint) return false;
59
+ if (!/(?:^|[\\/])notify-(?:hook|dispatcher)\.js$/.test(entrypoint)) {
60
+ return false;
61
+ }
62
+ return /(?:^|[\\/])oh-my-codex(?:[\\/]|$)/.test(entrypoint);
63
+ }
64
+
65
+ function isManagedPreviousNotify(
66
+ previousNotify: readonly string[] | null | undefined,
67
+ metadata: NotifyDispatcherMetadata | null,
68
+ ): boolean {
69
+ return (
70
+ isOmxManagedNotifyCommand(previousNotify) ||
71
+ sameCommand(previousNotify, metadata?.omxNotify) ||
72
+ sameCommand(previousNotify, metadata?.dispatcherNotify)
73
+ );
74
+ }
75
+
39
76
  async function readMetadata(
40
77
  path: string,
41
78
  ): Promise<NotifyDispatcherMetadata | null> {
@@ -67,7 +104,9 @@ async function main(): Promise<void> {
67
104
  const { metadataPath, payloadArg } = parseArgs();
68
105
  if (!payloadArg || payloadArg.startsWith("-")) return;
69
106
  const metadata = await readMetadata(metadataPath);
70
- runNotify(metadata?.previousNotify, payloadArg);
107
+ if (!isManagedPreviousNotify(metadata?.previousNotify, metadata)) {
108
+ runNotify(metadata?.previousNotify, payloadArg);
109
+ }
71
110
  runNotify(metadata?.omxNotify, payloadArg);
72
111
  }
73
112
 
@@ -99,7 +99,7 @@ async function resolveCanonicalPaneFromPaneTarget(paneTarget: any, expectedCwd:
99
99
  return finalizeResolvedPane(healedPaneId, 'healed_hud_pane_target', expectedCwd);
100
100
  }
101
101
 
102
- async function resolvePreferredModePane(stateDir: string, allowedModes: string[]): Promise<{ mode: string; state: any; pane: string } | null> {
102
+ async function resolvePreferredModePane(stateDir: string, allowedModes: string[]): Promise<{ mode: string; state: any; pane: string; stateDir: string } | null> {
103
103
  const scopedDirs = await getScopedStateDirsForCurrentSession(stateDir).catch(() => [stateDir]);
104
104
  const dirs = [...scopedDirs];
105
105
  if (!dirs.map((dir) => resolvePath(dir)).includes(resolvePath(stateDir))) {
@@ -111,13 +111,84 @@ async function resolvePreferredModePane(stateDir: string, allowedModes: string[]
111
111
  const parsed = await readJsonIfExists(path, null);
112
112
  const pane = safeString(parsed?.tmux_pane_id || '').trim();
113
113
  if (parsed?.active && pane) {
114
- return { mode, state: parsed, pane };
114
+ return { mode, state: parsed, pane, stateDir: dir };
115
115
  }
116
116
  }
117
117
  }
118
118
  return null;
119
119
  }
120
120
 
121
+ function modeStateMatchesInvocationOwner(modeState: any, payload: any, managedContext: any): { ok: true } | { ok: false; reason: string } {
122
+ const invocationSessionId = resolveInvocationSessionId(payload);
123
+ const canonicalSessionId = safeString(managedContext?.canonicalSessionId || managedContext?.sessionState?.session_id).trim();
124
+ const nativeSessionId = safeString(managedContext?.nativeSessionId || managedContext?.sessionState?.native_session_id || managedContext?.sessionState?.codex_session_id).trim();
125
+ const allowedSessionIds = new Set([
126
+ invocationSessionId,
127
+ canonicalSessionId,
128
+ nativeSessionId,
129
+ ].filter(Boolean));
130
+
131
+ const ownerOmxSessionId = safeString(modeState?.owner_omx_session_id).trim();
132
+ if (ownerOmxSessionId && !allowedSessionIds.has(ownerOmxSessionId)) {
133
+ return { ok: false, reason: 'mode_owner_session_mismatch' };
134
+ }
135
+
136
+ const stateSessionId = safeString(modeState?.session_id).trim();
137
+ if (!ownerOmxSessionId && stateSessionId && !allowedSessionIds.has(stateSessionId)) {
138
+ return { ok: false, reason: 'mode_session_mismatch' };
139
+ }
140
+
141
+ const ownerCodexSessionId = safeString(modeState?.owner_codex_session_id || modeState?.codex_session_id).trim();
142
+ if (ownerCodexSessionId && !allowedSessionIds.has(ownerCodexSessionId)) {
143
+ return { ok: false, reason: 'mode_codex_session_mismatch' };
144
+ }
145
+
146
+ return { ok: true };
147
+ }
148
+
149
+ async function validateResolvedInjectionOwnership({
150
+ paneTarget,
151
+ cwd,
152
+ payload,
153
+ modeState,
154
+ modePane,
155
+ managedCurrentPane,
156
+ }: any): Promise<{ ok: true } | { ok: false; reason: string; managedContext?: any }> {
157
+ const ownership = await verifyManagedPaneTarget(paneTarget, cwd, payload, { allowTeamWorker: false });
158
+ if (!ownership.ok) {
159
+ return { ok: false, reason: ownership.reason || 'pane_not_managed_session', managedContext: ownership.managedContext };
160
+ }
161
+
162
+ const modeOwner = modeStateMatchesInvocationOwner(modeState, payload, ownership.managedContext);
163
+ if (!modeOwner.ok) return { ...modeOwner, managedContext: ownership.managedContext };
164
+
165
+ const statePane = safeString(modePane || modeState?.tmux_pane_id).trim();
166
+ const currentPane = safeString(managedCurrentPane).trim();
167
+ if (statePane && currentPane && statePane !== currentPane) {
168
+ return { ok: false, reason: 'mode_pane_current_pane_mismatch', managedContext: ownership.managedContext };
169
+ }
170
+
171
+ const expectedWindowId = safeString(modeState?.tmux_window_id || modeState?.tmuxWindowId).trim();
172
+ if (!expectedWindowId) {
173
+ return { ok: true };
174
+ }
175
+
176
+ try {
177
+ const windowResult = await runProcess('tmux', ['display-message', '-p', '-t', paneTarget, '#{window_id}'], 2000);
178
+ const paneWindowId = safeString(windowResult.stdout).trim();
179
+ if (!paneWindowId) {
180
+ return { ok: false, reason: 'pane_window_unverified', managedContext: ownership.managedContext };
181
+ }
182
+ if (paneWindowId !== expectedWindowId) {
183
+ return { ok: false, reason: 'pane_window_mismatch', managedContext: ownership.managedContext };
184
+ }
185
+ } catch {
186
+ return { ok: false, reason: 'pane_window_unverified', managedContext: ownership.managedContext };
187
+ }
188
+
189
+ return { ok: true };
190
+ }
191
+
121
192
  async function readVisibleAllowedModes(
122
193
  cwd: string,
123
194
  stateDir: string,
@@ -460,7 +531,22 @@ export async function handleTmuxInjection({
460
531
  turnId,
461
532
  timestamp: nowIso,
462
533
  }), sourceText);
463
- const preferredPaneTarget = modePane || await resolveManagedCurrentPane(cwd, payload, { allowTeamWorker: false });
534
+ const managedCurrentPane = await resolveManagedCurrentPane(cwd, payload, { allowTeamWorker: false });
535
+ if (modePane && managedCurrentPane && modePane !== managedCurrentPane) {
536
+ state.last_reason = 'mode_pane_current_pane_mismatch';
537
+ state.last_event_at = nowIso;
538
+ await writeFile(hookStatePath, JSON.stringify(state, null, 2)).catch(() => {});
539
+ await logTmuxHookEvent(logsDir, {
540
+ ...baseLog,
541
+ event: 'injection_skipped',
542
+ reason: 'mode_pane_current_pane_mismatch',
543
+ mode_pane: modePane,
544
+ current_pane: managedCurrentPane,
545
+ });
546
+ return;
547
+ }
548
+
549
+ const preferredPaneTarget = modePane || managedCurrentPane;
464
550
  let resolution = preferredModePane
465
551
  ? await resolvePaneTarget({ type: 'pane', value: preferredModePane.pane }, cwd, preferredModePane.pane, cwd, payload)
466
552
  : preferredPaneTarget
@@ -484,6 +570,27 @@ export async function handleTmuxInjection({
484
570
  }
485
571
  const paneTarget = resolution.paneTarget;
486
572
 
573
+ const ownership = await validateResolvedInjectionOwnership({
574
+ paneTarget,
575
+ cwd,
576
+ payload,
577
+ modeState,
578
+ modePane,
579
+ managedCurrentPane,
580
+ });
581
+ if (!ownership.ok) {
582
+ state.last_reason = ownership.reason;
583
+ state.last_event_at = nowIso;
584
+ await writeFile(hookStatePath, JSON.stringify(state, null, 2)).catch(() => {});
585
+ await logTmuxHookEvent(logsDir, {
586
+ ...baseLog,
587
+ event: 'injection_skipped',
588
+ reason: ownership.reason,
589
+ pane_target: paneTarget,
590
+ });
591
+ return;
592
+ }
593
+
487
594
  // Final guard phase: pane is canonical identity for quota/cooldown.
488
595
  const guard = evaluateInjectionGuards({
489
596
  config,
@@ -29,6 +29,7 @@ import {
29
29
  getQuotaUsage,
30
30
  normalizeInputMessages,
31
31
  } from './notify-hook/payload-parser.js';
32
+ import { getBaseStateDir } from '../mcp/state-paths.js';
32
33
  import {
33
34
  getScopedStatePath,
34
35
  readCurrentSessionId,
@@ -303,7 +304,7 @@ async function main() {
303
304
  ? await resolveTeamStateDirForWorker(cwd, parsedTeamWorker)
304
305
  : null;
305
306
  const workerStateRootResolved = !isTeamWorker || !!resolvedWorkerStateDir;
306
- const stateDir = resolvedWorkerStateDir || join(cwd, '.omx', 'state');
307
+ const stateDir = resolvedWorkerStateDir || getBaseStateDir(cwd);
307
308
  const logsDir = join(cwd, '.omx', 'logs');
308
309
  const omxDir = join(cwd, '.omx');
309
310
  let currentOmxSessionId = '';
@@ -621,6 +622,7 @@ async function main() {
621
622
  if (latestUserInput) {
622
623
  await recordSkillActivation({
623
624
  stateDir,
625
+ sourceCwd: cwd,
624
626
  text: latestUserInput,
625
627
  sessionId: getEffectiveSessionId(),
626
628
  threadId: payloadThreadId,
@@ -181,13 +181,20 @@
181
181
  "internalRequired": false
182
182
  },
183
183
  {
184
- "name": "frontend-ui-ux",
184
+ "name": "design",
185
185
  "category": "shortcut",
186
- "status": "alias",
186
+ "status": "active",
187
187
  "canonical": "designer",
188
188
  "core": false,
189
189
  "internalRequired": false
190
190
  },
191
+ {
192
+ "name": "frontend-ui-ux",
193
+ "category": "shortcut",
194
+ "status": "deprecated",
195
+ "core": false,
196
+ "internalRequired": false
197
+ },
191
198
  {
192
199
  "name": "git-master",
193
200
  "category": "shortcut",