oh-my-codex 0.12.4 → 0.12.6

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 (475) hide show
  1. package/Cargo.lock +5 -5
  2. package/Cargo.toml +1 -1
  3. package/README.md +27 -3
  4. package/dist/cli/__tests__/ask.test.js +26 -0
  5. package/dist/cli/__tests__/ask.test.js.map +1 -1
  6. package/dist/cli/__tests__/doctor-warning-copy.test.js +28 -0
  7. package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
  8. package/dist/cli/__tests__/explore.test.js +95 -8
  9. package/dist/cli/__tests__/explore.test.js.map +1 -1
  10. package/dist/cli/__tests__/index.test.js +102 -4
  11. package/dist/cli/__tests__/index.test.js.map +1 -1
  12. package/dist/cli/__tests__/launch-fallback.test.js +169 -0
  13. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
  14. package/dist/cli/__tests__/mcp-parity.test.js +31 -0
  15. package/dist/cli/__tests__/mcp-parity.test.js.map +1 -1
  16. package/dist/cli/__tests__/setup-agents-overwrite.test.js +66 -2
  17. package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
  18. package/dist/cli/__tests__/setup-refresh.test.js +51 -1
  19. package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
  20. package/dist/cli/__tests__/team.test.js +148 -3
  21. package/dist/cli/__tests__/team.test.js.map +1 -1
  22. package/dist/cli/__tests__/uninstall.test.js +14 -1
  23. package/dist/cli/__tests__/uninstall.test.js.map +1 -1
  24. package/dist/cli/cleanup.js +1 -1
  25. package/dist/cli/cleanup.js.map +1 -1
  26. package/dist/cli/constants.d.ts +1 -0
  27. package/dist/cli/constants.d.ts.map +1 -1
  28. package/dist/cli/constants.js +1 -0
  29. package/dist/cli/constants.js.map +1 -1
  30. package/dist/cli/doctor.d.ts.map +1 -1
  31. package/dist/cli/doctor.js +15 -0
  32. package/dist/cli/doctor.js.map +1 -1
  33. package/dist/cli/explore.d.ts +1 -0
  34. package/dist/cli/explore.d.ts.map +1 -1
  35. package/dist/cli/explore.js +49 -1
  36. package/dist/cli/explore.js.map +1 -1
  37. package/dist/cli/index.d.ts +2 -1
  38. package/dist/cli/index.d.ts.map +1 -1
  39. package/dist/cli/index.js +127 -14
  40. package/dist/cli/index.js.map +1 -1
  41. package/dist/cli/mcp-parity.d.ts +1 -1
  42. package/dist/cli/mcp-parity.d.ts.map +1 -1
  43. package/dist/cli/mcp-parity.js +24 -0
  44. package/dist/cli/mcp-parity.js.map +1 -1
  45. package/dist/cli/setup.d.ts.map +1 -1
  46. package/dist/cli/setup.js +17 -5
  47. package/dist/cli/setup.js.map +1 -1
  48. package/dist/cli/team.d.ts.map +1 -1
  49. package/dist/cli/team.js +80 -6
  50. package/dist/cli/team.js.map +1 -1
  51. package/dist/cli/uninstall.d.ts.map +1 -1
  52. package/dist/cli/uninstall.js +1 -0
  53. package/dist/cli/uninstall.js.map +1 -1
  54. package/dist/config/__tests__/generator-idempotent.test.js +60 -0
  55. package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
  56. package/dist/config/__tests__/mcp-registry.test.js +61 -0
  57. package/dist/config/__tests__/mcp-registry.test.js.map +1 -1
  58. package/dist/config/__tests__/wiki-config-contract.test.d.ts +2 -0
  59. package/dist/config/__tests__/wiki-config-contract.test.d.ts.map +1 -0
  60. package/dist/config/__tests__/wiki-config-contract.test.js +19 -0
  61. package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -0
  62. package/dist/config/generator.d.ts +1 -0
  63. package/dist/config/generator.d.ts.map +1 -1
  64. package/dist/config/generator.js +88 -3
  65. package/dist/config/generator.js.map +1 -1
  66. package/dist/config/mcp-registry.d.ts +2 -0
  67. package/dist/config/mcp-registry.d.ts.map +1 -1
  68. package/dist/config/mcp-registry.js +12 -0
  69. package/dist/config/mcp-registry.js.map +1 -1
  70. package/dist/hooks/__tests__/agents-overlay.test.js +39 -0
  71. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  72. package/dist/hooks/__tests__/keyword-detector.test.js +297 -4
  73. package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
  74. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +392 -22
  75. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  76. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +166 -67
  77. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  78. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js +112 -2
  79. package/dist/hooks/__tests__/notify-hook-managed-tmux.test.js.map +1 -1
  80. package/dist/hooks/__tests__/notify-hook-modules.test.js +52 -12
  81. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  82. package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts +2 -3
  83. package/dist/hooks/__tests__/notify-hook-regression-205.test.d.ts.map +1 -1
  84. package/dist/hooks/__tests__/notify-hook-regression-205.test.js +18 -23
  85. package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
  86. package/dist/hooks/__tests__/notify-hook-session-scope.test.js +33 -0
  87. package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
  88. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +176 -1
  89. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  90. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +355 -7
  91. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  92. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +90 -2
  93. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  94. package/dist/hooks/__tests__/session.test.js +142 -2
  95. package/dist/hooks/__tests__/session.test.js.map +1 -1
  96. package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts +2 -0
  97. package/dist/hooks/__tests__/wiki-docs-contract.test.d.ts.map +1 -0
  98. package/dist/hooks/__tests__/wiki-docs-contract.test.js +34 -0
  99. package/dist/hooks/__tests__/wiki-docs-contract.test.js.map +1 -0
  100. package/dist/hooks/agents-overlay.d.ts.map +1 -1
  101. package/dist/hooks/agents-overlay.js +0 -1
  102. package/dist/hooks/agents-overlay.js.map +1 -1
  103. package/dist/hooks/extensibility/__tests__/dispatcher.test.js +32 -0
  104. package/dist/hooks/extensibility/__tests__/dispatcher.test.js.map +1 -1
  105. package/dist/hooks/extensibility/__tests__/runtime.test.js +31 -0
  106. package/dist/hooks/extensibility/__tests__/runtime.test.js.map +1 -1
  107. package/dist/hooks/extensibility/__tests__/sdk.test.js +33 -3
  108. package/dist/hooks/extensibility/__tests__/sdk.test.js.map +1 -1
  109. package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -1
  110. package/dist/hooks/extensibility/dispatcher.js +41 -0
  111. package/dist/hooks/extensibility/dispatcher.js.map +1 -1
  112. package/dist/hooks/extensibility/sdk/runtime-state.d.ts.map +1 -1
  113. package/dist/hooks/extensibility/sdk/runtime-state.js +7 -1
  114. package/dist/hooks/extensibility/sdk/runtime-state.js.map +1 -1
  115. package/dist/hooks/extensibility/types.d.ts +1 -0
  116. package/dist/hooks/extensibility/types.d.ts.map +1 -1
  117. package/dist/hooks/keyword-detector.d.ts +6 -1
  118. package/dist/hooks/keyword-detector.d.ts.map +1 -1
  119. package/dist/hooks/keyword-detector.js +207 -10
  120. package/dist/hooks/keyword-detector.js.map +1 -1
  121. package/dist/hooks/keyword-registry.d.ts.map +1 -1
  122. package/dist/hooks/keyword-registry.js +3 -0
  123. package/dist/hooks/keyword-registry.js.map +1 -1
  124. package/dist/hooks/session.d.ts +14 -2
  125. package/dist/hooks/session.d.ts.map +1 -1
  126. package/dist/hooks/session.js +120 -16
  127. package/dist/hooks/session.js.map +1 -1
  128. package/dist/hud/__tests__/state.test.js +111 -2
  129. package/dist/hud/__tests__/state.test.js.map +1 -1
  130. package/dist/hud/state.d.ts.map +1 -1
  131. package/dist/hud/state.js +18 -21
  132. package/dist/hud/state.js.map +1 -1
  133. package/dist/mcp/__tests__/bootstrap.test.js +88 -1
  134. package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
  135. package/dist/mcp/__tests__/server-lifecycle.test.js +3 -0
  136. package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
  137. package/dist/mcp/__tests__/state-paths.test.js +30 -2
  138. package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
  139. package/dist/mcp/__tests__/state-server.test.js +415 -0
  140. package/dist/mcp/__tests__/state-server.test.js.map +1 -1
  141. package/dist/mcp/__tests__/wiki-server.test.d.ts +2 -0
  142. package/dist/mcp/__tests__/wiki-server.test.d.ts.map +1 -0
  143. package/dist/mcp/__tests__/wiki-server.test.js +30 -0
  144. package/dist/mcp/__tests__/wiki-server.test.js.map +1 -0
  145. package/dist/mcp/bootstrap.d.ts +19 -1
  146. package/dist/mcp/bootstrap.d.ts.map +1 -1
  147. package/dist/mcp/bootstrap.js +185 -0
  148. package/dist/mcp/bootstrap.js.map +1 -1
  149. package/dist/mcp/state-paths.d.ts +5 -0
  150. package/dist/mcp/state-paths.d.ts.map +1 -1
  151. package/dist/mcp/state-paths.js +41 -11
  152. package/dist/mcp/state-paths.js.map +1 -1
  153. package/dist/mcp/state-server.d.ts +4 -4
  154. package/dist/mcp/state-server.d.ts.map +1 -1
  155. package/dist/mcp/state-server.js +49 -2
  156. package/dist/mcp/state-server.js.map +1 -1
  157. package/dist/mcp/wiki-server.d.ts +181 -0
  158. package/dist/mcp/wiki-server.d.ts.map +1 -0
  159. package/dist/mcp/wiki-server.js +235 -0
  160. package/dist/mcp/wiki-server.js.map +1 -0
  161. package/dist/modes/__tests__/base-autoresearch-contract.test.js +74 -2
  162. package/dist/modes/__tests__/base-autoresearch-contract.test.js.map +1 -1
  163. package/dist/modes/__tests__/base-multi-state-compat.test.d.ts +2 -0
  164. package/dist/modes/__tests__/base-multi-state-compat.test.d.ts.map +1 -0
  165. package/dist/modes/__tests__/base-multi-state-compat.test.js +38 -0
  166. package/dist/modes/__tests__/base-multi-state-compat.test.js.map +1 -0
  167. package/dist/modes/__tests__/base-tmux-pane.test.js +1 -1
  168. package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
  169. package/dist/modes/base.d.ts +2 -1
  170. package/dist/modes/base.d.ts.map +1 -1
  171. package/dist/modes/base.js +55 -31
  172. package/dist/modes/base.js.map +1 -1
  173. package/dist/notifications/__tests__/formatter.test.js +11 -0
  174. package/dist/notifications/__tests__/formatter.test.js.map +1 -1
  175. package/dist/notifications/__tests__/idle-cooldown.test.js +32 -1
  176. package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -1
  177. package/dist/notifications/__tests__/index.test.d.ts +2 -0
  178. package/dist/notifications/__tests__/index.test.d.ts.map +1 -0
  179. package/dist/notifications/__tests__/index.test.js +113 -0
  180. package/dist/notifications/__tests__/index.test.js.map +1 -0
  181. package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts +2 -0
  182. package/dist/notifications/__tests__/lifecycle-dedupe.test.d.ts.map +1 -0
  183. package/dist/notifications/__tests__/lifecycle-dedupe.test.js +86 -0
  184. package/dist/notifications/__tests__/lifecycle-dedupe.test.js.map +1 -0
  185. package/dist/notifications/__tests__/reply-listener.test.js +174 -0
  186. package/dist/notifications/__tests__/reply-listener.test.js.map +1 -1
  187. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts +2 -0
  188. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.d.ts.map +1 -0
  189. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js +93 -0
  190. package/dist/notifications/__tests__/session-idle-tail-dedupe.test.js.map +1 -0
  191. package/dist/notifications/__tests__/session-registry.test.js +48 -1
  192. package/dist/notifications/__tests__/session-registry.test.js.map +1 -1
  193. package/dist/notifications/__tests__/session-status.test.d.ts +2 -0
  194. package/dist/notifications/__tests__/session-status.test.d.ts.map +1 -0
  195. package/dist/notifications/__tests__/session-status.test.js +159 -0
  196. package/dist/notifications/__tests__/session-status.test.js.map +1 -0
  197. package/dist/notifications/__tests__/tmux.test.js +58 -1
  198. package/dist/notifications/__tests__/tmux.test.js.map +1 -1
  199. package/dist/notifications/idle-cooldown.d.ts +11 -0
  200. package/dist/notifications/idle-cooldown.d.ts.map +1 -1
  201. package/dist/notifications/idle-cooldown.js +42 -8
  202. package/dist/notifications/idle-cooldown.js.map +1 -1
  203. package/dist/notifications/index.d.ts +1 -1
  204. package/dist/notifications/index.d.ts.map +1 -1
  205. package/dist/notifications/index.js +41 -8
  206. package/dist/notifications/index.js.map +1 -1
  207. package/dist/notifications/lifecycle-dedupe.d.ts +8 -0
  208. package/dist/notifications/lifecycle-dedupe.d.ts.map +1 -0
  209. package/dist/notifications/lifecycle-dedupe.js +112 -0
  210. package/dist/notifications/lifecycle-dedupe.js.map +1 -0
  211. package/dist/notifications/reply-listener.d.ts +10 -1
  212. package/dist/notifications/reply-listener.d.ts.map +1 -1
  213. package/dist/notifications/reply-listener.js +49 -11
  214. package/dist/notifications/reply-listener.js.map +1 -1
  215. package/dist/notifications/session-registry.d.ts.map +1 -1
  216. package/dist/notifications/session-registry.js +7 -1
  217. package/dist/notifications/session-registry.js.map +1 -1
  218. package/dist/notifications/session-status.d.ts +23 -0
  219. package/dist/notifications/session-status.d.ts.map +1 -0
  220. package/dist/notifications/session-status.js +187 -0
  221. package/dist/notifications/session-status.js.map +1 -0
  222. package/dist/notifications/tmux.d.ts +10 -0
  223. package/dist/notifications/tmux.d.ts.map +1 -1
  224. package/dist/notifications/tmux.js +59 -5
  225. package/dist/notifications/tmux.js.map +1 -1
  226. package/dist/notifications/types.d.ts +2 -0
  227. package/dist/notifications/types.d.ts.map +1 -1
  228. package/dist/openclaw/__tests__/index.test.js +84 -0
  229. package/dist/openclaw/__tests__/index.test.js.map +1 -1
  230. package/dist/openclaw/index.d.ts.map +1 -1
  231. package/dist/openclaw/index.js +7 -14
  232. package/dist/openclaw/index.js.map +1 -1
  233. package/dist/openclaw/types.d.ts +2 -2
  234. package/dist/openclaw/types.d.ts.map +1 -1
  235. package/dist/scripts/__tests__/codex-native-hook.test.js +692 -40
  236. package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
  237. package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts +2 -0
  238. package/dist/scripts/__tests__/hook-derived-watcher.test.d.ts.map +1 -0
  239. package/dist/scripts/__tests__/hook-derived-watcher.test.js +87 -0
  240. package/dist/scripts/__tests__/hook-derived-watcher.test.js.map +1 -0
  241. package/dist/scripts/codex-native-hook.d.ts.map +1 -1
  242. package/dist/scripts/codex-native-hook.js +309 -77
  243. package/dist/scripts/codex-native-hook.js.map +1 -1
  244. package/dist/scripts/hook-derived-watcher.js +43 -1
  245. package/dist/scripts/hook-derived-watcher.js.map +1 -1
  246. package/dist/scripts/notify-fallback-watcher.js +95 -21
  247. package/dist/scripts/notify-fallback-watcher.js.map +1 -1
  248. package/dist/scripts/notify-hook/active-team.d.ts +9 -0
  249. package/dist/scripts/notify-hook/active-team.d.ts.map +1 -0
  250. package/dist/scripts/notify-hook/active-team.js +44 -0
  251. package/dist/scripts/notify-hook/active-team.js.map +1 -0
  252. package/dist/scripts/notify-hook/auto-nudge.d.ts +5 -3
  253. package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
  254. package/dist/scripts/notify-hook/auto-nudge.js +121 -78
  255. package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
  256. package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -1
  257. package/dist/scripts/notify-hook/managed-tmux.js +18 -4
  258. package/dist/scripts/notify-hook/managed-tmux.js.map +1 -1
  259. package/dist/scripts/notify-hook/operational-events.d.ts.map +1 -1
  260. package/dist/scripts/notify-hook/operational-events.js +21 -0
  261. package/dist/scripts/notify-hook/operational-events.js.map +1 -1
  262. package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -1
  263. package/dist/scripts/notify-hook/ralph-session-resume.js +3 -2
  264. package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -1
  265. package/dist/scripts/notify-hook/state-io.d.ts +10 -1
  266. package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
  267. package/dist/scripts/notify-hook/state-io.js +56 -12
  268. package/dist/scripts/notify-hook/state-io.js.map +1 -1
  269. package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
  270. package/dist/scripts/notify-hook/team-dispatch.js +305 -167
  271. package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
  272. package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
  273. package/dist/scripts/notify-hook/team-leader-nudge.js +87 -15
  274. package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
  275. package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
  276. package/dist/scripts/notify-hook/tmux-injection.js +11 -2
  277. package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
  278. package/dist/scripts/notify-hook.js +26 -16
  279. package/dist/scripts/notify-hook.js.map +1 -1
  280. package/dist/scripts/run-provider-advisor.js +20 -2
  281. package/dist/scripts/run-provider-advisor.js.map +1 -1
  282. package/dist/scripts/smoke-packed-install.d.ts +1 -8
  283. package/dist/scripts/smoke-packed-install.d.ts.map +1 -1
  284. package/dist/scripts/smoke-packed-install.js +12 -68
  285. package/dist/scripts/smoke-packed-install.js.map +1 -1
  286. package/dist/state/__tests__/operations.test.js +113 -0
  287. package/dist/state/__tests__/operations.test.js.map +1 -1
  288. package/dist/state/__tests__/skill-active.test.js +35 -0
  289. package/dist/state/__tests__/skill-active.test.js.map +1 -1
  290. package/dist/state/__tests__/workflow-transition.test.d.ts +2 -0
  291. package/dist/state/__tests__/workflow-transition.test.d.ts.map +1 -0
  292. package/dist/state/__tests__/workflow-transition.test.js +56 -0
  293. package/dist/state/__tests__/workflow-transition.test.js.map +1 -0
  294. package/dist/state/operations.d.ts +1 -1
  295. package/dist/state/operations.d.ts.map +1 -1
  296. package/dist/state/operations.js +88 -2
  297. package/dist/state/operations.js.map +1 -1
  298. package/dist/state/skill-active.d.ts +2 -2
  299. package/dist/state/skill-active.d.ts.map +1 -1
  300. package/dist/state/skill-active.js +119 -33
  301. package/dist/state/skill-active.js.map +1 -1
  302. package/dist/state/workflow-transition-reconcile.d.ts +15 -0
  303. package/dist/state/workflow-transition-reconcile.d.ts.map +1 -0
  304. package/dist/state/workflow-transition-reconcile.js +100 -0
  305. package/dist/state/workflow-transition-reconcile.js.map +1 -0
  306. package/dist/state/workflow-transition.d.ts +22 -0
  307. package/dist/state/workflow-transition.d.ts.map +1 -0
  308. package/dist/state/workflow-transition.js +188 -0
  309. package/dist/state/workflow-transition.js.map +1 -0
  310. package/dist/team/__tests__/api-interop.test.js +90 -0
  311. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  312. package/dist/team/__tests__/current-task-baseline.test.d.ts +2 -0
  313. package/dist/team/__tests__/current-task-baseline.test.d.ts.map +1 -0
  314. package/dist/team/__tests__/current-task-baseline.test.js +87 -0
  315. package/dist/team/__tests__/current-task-baseline.test.js.map +1 -0
  316. package/dist/team/__tests__/hardening-e2e.test.js +17 -0
  317. package/dist/team/__tests__/hardening-e2e.test.js.map +1 -1
  318. package/dist/team/__tests__/runtime.test.js +673 -65
  319. package/dist/team/__tests__/runtime.test.js.map +1 -1
  320. package/dist/team/__tests__/shutdown-fallback.test.js +11 -1
  321. package/dist/team/__tests__/shutdown-fallback.test.js.map +1 -1
  322. package/dist/team/__tests__/tmux-session.test.js +447 -4
  323. package/dist/team/__tests__/tmux-session.test.js.map +1 -1
  324. package/dist/team/api-interop.d.ts.map +1 -1
  325. package/dist/team/api-interop.js +10 -1
  326. package/dist/team/api-interop.js.map +1 -1
  327. package/dist/team/current-task-baseline.d.ts +32 -0
  328. package/dist/team/current-task-baseline.d.ts.map +1 -0
  329. package/dist/team/current-task-baseline.js +85 -0
  330. package/dist/team/current-task-baseline.js.map +1 -0
  331. package/dist/team/delivery-log.d.ts +1 -1
  332. package/dist/team/delivery-log.d.ts.map +1 -1
  333. package/dist/team/delivery-log.js.map +1 -1
  334. package/dist/team/leader-activity.d.ts +1 -0
  335. package/dist/team/leader-activity.d.ts.map +1 -1
  336. package/dist/team/leader-activity.js +4 -2
  337. package/dist/team/leader-activity.js.map +1 -1
  338. package/dist/team/progress-evidence.d.ts +2 -0
  339. package/dist/team/progress-evidence.d.ts.map +1 -0
  340. package/dist/team/progress-evidence.js +77 -0
  341. package/dist/team/progress-evidence.js.map +1 -0
  342. package/dist/team/runtime.d.ts.map +1 -1
  343. package/dist/team/runtime.js +269 -64
  344. package/dist/team/runtime.js.map +1 -1
  345. package/dist/team/scaling.d.ts.map +1 -1
  346. package/dist/team/scaling.js +1 -1
  347. package/dist/team/scaling.js.map +1 -1
  348. package/dist/team/state.d.ts.map +1 -1
  349. package/dist/team/state.js +2 -13
  350. package/dist/team/state.js.map +1 -1
  351. package/dist/team/tmux-session.d.ts +12 -3
  352. package/dist/team/tmux-session.d.ts.map +1 -1
  353. package/dist/team/tmux-session.js +174 -20
  354. package/dist/team/tmux-session.js.map +1 -1
  355. package/dist/team/worktree.d.ts +6 -1
  356. package/dist/team/worktree.d.ts.map +1 -1
  357. package/dist/team/worktree.js +28 -4
  358. package/dist/team/worktree.js.map +1 -1
  359. package/dist/utils/__tests__/agents-md.test.js +21 -1
  360. package/dist/utils/__tests__/agents-md.test.js.map +1 -1
  361. package/dist/utils/__tests__/repo-deps.test.d.ts +2 -0
  362. package/dist/utils/__tests__/repo-deps.test.d.ts.map +1 -0
  363. package/dist/utils/__tests__/repo-deps.test.js +71 -0
  364. package/dist/utils/__tests__/repo-deps.test.js.map +1 -0
  365. package/dist/utils/agents-md.d.ts +1 -0
  366. package/dist/utils/agents-md.d.ts.map +1 -1
  367. package/dist/utils/agents-md.js +7 -3
  368. package/dist/utils/agents-md.js.map +1 -1
  369. package/dist/utils/paths.d.ts +4 -0
  370. package/dist/utils/paths.d.ts.map +1 -1
  371. package/dist/utils/paths.js +20 -0
  372. package/dist/utils/paths.js.map +1 -1
  373. package/dist/utils/repo-deps.d.ts +20 -0
  374. package/dist/utils/repo-deps.d.ts.map +1 -0
  375. package/dist/utils/repo-deps.js +78 -0
  376. package/dist/utils/repo-deps.js.map +1 -0
  377. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts +2 -0
  378. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.d.ts.map +1 -0
  379. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +54 -0
  380. package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -0
  381. package/dist/wiki/__tests__/cjk-tokenize.test.d.ts +12 -0
  382. package/dist/wiki/__tests__/cjk-tokenize.test.d.ts.map +1 -0
  383. package/dist/wiki/__tests__/cjk-tokenize.test.js +139 -0
  384. package/dist/wiki/__tests__/cjk-tokenize.test.js.map +1 -0
  385. package/dist/wiki/__tests__/crlf-parse.test.d.ts +2 -0
  386. package/dist/wiki/__tests__/crlf-parse.test.d.ts.map +1 -0
  387. package/dist/wiki/__tests__/crlf-parse.test.js +24 -0
  388. package/dist/wiki/__tests__/crlf-parse.test.js.map +1 -0
  389. package/dist/wiki/__tests__/escape-newline.test.d.ts +2 -0
  390. package/dist/wiki/__tests__/escape-newline.test.d.ts.map +1 -0
  391. package/dist/wiki/__tests__/escape-newline.test.js +45 -0
  392. package/dist/wiki/__tests__/escape-newline.test.js.map +1 -0
  393. package/dist/wiki/__tests__/ingest.test.d.ts +5 -0
  394. package/dist/wiki/__tests__/ingest.test.d.ts.map +1 -0
  395. package/dist/wiki/__tests__/ingest.test.js +181 -0
  396. package/dist/wiki/__tests__/ingest.test.js.map +1 -0
  397. package/dist/wiki/__tests__/lint.test.d.ts +5 -0
  398. package/dist/wiki/__tests__/lint.test.d.ts.map +1 -0
  399. package/dist/wiki/__tests__/lint.test.js +163 -0
  400. package/dist/wiki/__tests__/lint.test.js.map +1 -0
  401. package/dist/wiki/__tests__/query.test.d.ts +5 -0
  402. package/dist/wiki/__tests__/query.test.d.ts.map +1 -0
  403. package/dist/wiki/__tests__/query.test.js +141 -0
  404. package/dist/wiki/__tests__/query.test.js.map +1 -0
  405. package/dist/wiki/__tests__/reserved-file-guard.test.d.ts +2 -0
  406. package/dist/wiki/__tests__/reserved-file-guard.test.d.ts.map +1 -0
  407. package/dist/wiki/__tests__/reserved-file-guard.test.js +44 -0
  408. package/dist/wiki/__tests__/reserved-file-guard.test.js.map +1 -0
  409. package/dist/wiki/__tests__/session-hooks.test.d.ts +5 -0
  410. package/dist/wiki/__tests__/session-hooks.test.d.ts.map +1 -0
  411. package/dist/wiki/__tests__/session-hooks.test.js +36 -0
  412. package/dist/wiki/__tests__/session-hooks.test.js.map +1 -0
  413. package/dist/wiki/__tests__/slug-nonascii.test.d.ts +2 -0
  414. package/dist/wiki/__tests__/slug-nonascii.test.d.ts.map +1 -0
  415. package/dist/wiki/__tests__/slug-nonascii.test.js +24 -0
  416. package/dist/wiki/__tests__/slug-nonascii.test.js.map +1 -0
  417. package/dist/wiki/__tests__/storage.test.d.ts +5 -0
  418. package/dist/wiki/__tests__/storage.test.d.ts.map +1 -0
  419. package/dist/wiki/__tests__/storage.test.js +278 -0
  420. package/dist/wiki/__tests__/storage.test.js.map +1 -0
  421. package/dist/wiki/__tests__/test-helpers.d.ts +31 -0
  422. package/dist/wiki/__tests__/test-helpers.d.ts.map +1 -0
  423. package/dist/wiki/__tests__/test-helpers.js +108 -0
  424. package/dist/wiki/__tests__/test-helpers.js.map +1 -0
  425. package/dist/wiki/index.d.ts +14 -0
  426. package/dist/wiki/index.d.ts.map +1 -0
  427. package/dist/wiki/index.js +17 -0
  428. package/dist/wiki/index.js.map +1 -0
  429. package/dist/wiki/ingest.d.ts +20 -0
  430. package/dist/wiki/ingest.d.ts.map +1 -0
  431. package/dist/wiki/ingest.js +115 -0
  432. package/dist/wiki/ingest.js.map +1 -0
  433. package/dist/wiki/lifecycle.d.ts +20 -0
  434. package/dist/wiki/lifecycle.d.ts.map +1 -0
  435. package/dist/wiki/lifecycle.js +212 -0
  436. package/dist/wiki/lifecycle.js.map +1 -0
  437. package/dist/wiki/lint.d.ts +25 -0
  438. package/dist/wiki/lint.d.ts.map +1 -0
  439. package/dist/wiki/lint.js +166 -0
  440. package/dist/wiki/lint.js.map +1 -0
  441. package/dist/wiki/query.d.ts +36 -0
  442. package/dist/wiki/query.d.ts.map +1 -0
  443. package/dist/wiki/query.js +138 -0
  444. package/dist/wiki/query.js.map +1 -0
  445. package/dist/wiki/storage.d.ts +33 -0
  446. package/dist/wiki/storage.d.ts.map +1 -0
  447. package/dist/wiki/storage.js +321 -0
  448. package/dist/wiki/storage.js.map +1 -0
  449. package/dist/wiki/types.d.ts +83 -0
  450. package/dist/wiki/types.d.ts.map +1 -0
  451. package/dist/wiki/types.js +15 -0
  452. package/dist/wiki/types.js.map +1 -0
  453. package/package.json +3 -1
  454. package/skills/configure-notifications/SKILL.md +1 -0
  455. package/skills/doctor/SKILL.md +11 -0
  456. package/skills/omx-setup/SKILL.md +1 -1
  457. package/skills/wiki/SKILL.md +57 -0
  458. package/src/scripts/__tests__/codex-native-hook.test.ts +920 -56
  459. package/src/scripts/__tests__/hook-derived-watcher.test.ts +111 -0
  460. package/src/scripts/codex-native-hook.ts +377 -83
  461. package/src/scripts/hook-derived-watcher.ts +43 -1
  462. package/src/scripts/notify-fallback-watcher.ts +99 -20
  463. package/src/scripts/notify-hook/active-team.ts +54 -0
  464. package/src/scripts/notify-hook/auto-nudge.ts +132 -79
  465. package/src/scripts/notify-hook/managed-tmux.ts +22 -4
  466. package/src/scripts/notify-hook/operational-events.ts +21 -0
  467. package/src/scripts/notify-hook/ralph-session-resume.ts +3 -2
  468. package/src/scripts/notify-hook/state-io.ts +89 -12
  469. package/src/scripts/notify-hook/team-dispatch.ts +326 -168
  470. package/src/scripts/notify-hook/team-leader-nudge.ts +91 -14
  471. package/src/scripts/notify-hook/tmux-injection.ts +11 -2
  472. package/src/scripts/notify-hook.ts +36 -22
  473. package/src/scripts/run-provider-advisor.ts +20 -2
  474. package/src/scripts/smoke-packed-install.ts +16 -83
  475. package/templates/AGENTS.md +3 -4
@@ -27,6 +27,16 @@ function withoutTeamWorkerEnv(fn) {
27
27
  delete process.env.OMX_TEAM_WORKER;
28
28
  });
29
29
  }
30
+ function withMockPromptModeCodexAllowed(fn) {
31
+ const previous = process.env.OMX_TEST_ALLOW_NONTTY_CODEX_PROMPT;
32
+ process.env.OMX_TEST_ALLOW_NONTTY_CODEX_PROMPT = '1';
33
+ return fn().finally(() => {
34
+ if (typeof previous === 'string')
35
+ process.env.OMX_TEST_ALLOW_NONTTY_CODEX_PROMPT = previous;
36
+ else
37
+ delete process.env.OMX_TEST_ALLOW_NONTTY_CODEX_PROMPT;
38
+ });
39
+ }
30
40
  describe('shutdown fallback worktree reports', () => {
31
41
  it('shutdownTeam checkpoints dirty detached worker worktrees, merges them, and writes a report', async () => {
32
42
  const repo = await initRepo();
@@ -48,7 +58,7 @@ process.on('SIGTERM', () => process.exit(0));
48
58
  let runtime = null;
49
59
  let preservedWorktreePath = null;
50
60
  try {
51
- runtime = await withoutTeamWorkerEnv(() => startTeam('team-shutdown-fallback-report', 'shutdown fallback merge report', 'executor', 1, [], repo, { worktreeMode: { enabled: true, detached: true, name: null } }));
61
+ runtime = await withMockPromptModeCodexAllowed(() => withoutTeamWorkerEnv(() => startTeam('team-shutdown-fallback-report', 'shutdown fallback merge report', 'executor', 1, [], repo, { worktreeMode: { enabled: true, detached: true, name: null } })));
52
62
  const worktreePath = runtime.config.workers[0]?.worktree_path;
53
63
  assert.ok(worktreePath, 'worker worktree path should be present');
54
64
  preservedWorktreePath = worktreePath ?? null;
@@ -1 +1 @@
1
- {"version":3,"file":"shutdown-fallback.test.js","sourceRoot":"","sources":["../../../src/team/__tests__/shutdown-fallback.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shutdown-fallback.test.js","sourceRoot":"","sources":["../../../src/team/__tests__/shutdown-fallback.test.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import { PassThrough } from 'node:stream';
6
6
  import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from 'fs/promises';
7
7
  import { join } from 'path';
8
8
  import { tmpdir } from 'os';
9
- import { buildClientAttachedReconcileHookName, assertTeamWorkerCliBinaryAvailable, buildWorkerProcessLaunchSpec, buildReconcileHudResizeArgs, buildRegisterClientAttachedReconcileArgs, buildRegisterResizeHookArgs, buildResizeHookName, buildResizeHookTarget, buildScheduleDelayedHudResizeArgs, buildUnregisterClientAttachedReconcileArgs, buildUnregisterResizeHookArgs, buildWorkerStartupCommand, buildHudPaneTarget, chooseTeamLeaderPaneId, createTeamSession, enableMouseScrolling, isMsysOrGitBash, isNativeWindows, isTmuxAvailable, restoreStandaloneHudPane, translatePathForMsys, isWsl2, isWorkerAlive, killWorker, killWorkerByPaneId, teardownWorkerPanes, listTeamSessions, resolveTeamWorkerCli, resolveTeamWorkerLaunchMode, resolveWorkerCliForSend, resolveTeamWorkerCliPlan, buildWorkerSubmitPlan, sanitizeTeamName, shouldAttemptAdaptiveRetry, sendToWorker, sendToWorkerStdin, sleepFractionalSeconds, translateWorkerLaunchArgsForCli, waitForWorkerReady, paneIsBootstrapping, dismissTrustPromptIfPresent, } from '../tmux-session.js';
9
+ import { buildClientAttachedReconcileHookName, assertTeamWorkerCliBinaryAvailable, buildWorkerProcessLaunchSpec, buildReconcileHudResizeArgs, buildRegisterClientAttachedReconcileArgs, buildRegisterResizeHookArgs, buildResizeHookName, buildResizeHookTarget, buildScheduleDelayedHudResizeArgs, buildUnregisterClientAttachedReconcileArgs, buildUnregisterResizeHookArgs, buildWorkerStartupCommand, buildHudPaneTarget, chooseTeamLeaderPaneId, createTeamSession, enableMouseScrolling, isMsysOrGitBash, isNativeWindows, isTmuxAvailable, restoreStandaloneHudPane, translatePathForMsys, isWsl2, isWorkerAlive, killWorker, killWorkerByPaneId, teardownWorkerPanes, listTeamSessions, resolveTeamWorkerCli, resolveTeamWorkerLaunchMode, resolveWorkerCliForSend, resolveTeamWorkerCliPlan, buildWorkerSubmitPlan, sanitizeTeamName, shouldAttemptAdaptiveRetry, sendToWorker, sendToWorkerStdin, sleepFractionalSeconds, translateWorkerLaunchArgsForCli, waitForWorkerReady, paneIsBootstrapping, dismissTrustPromptIfPresent, mitigateCopyModeUnderlineArtifacts, } from '../tmux-session.js';
10
10
  import { HUD_RESIZE_RECONCILE_DELAY_SECONDS, HUD_TMUX_TEAM_HEIGHT_LINES } from '../../hud/constants.js';
11
11
  import * as tmuxSessionModule from '../tmux-session.js';
12
12
  import { OMX_ENTRY_PATH_ENV, OMX_STARTUP_CWD_ENV } from '../../utils/paths.js';
@@ -63,6 +63,10 @@ const VIEWPORT_WITHOUT_VISIBLE_PROMPT_CAPTURE = `╭─────────
63
63
  const VIEWPORT_SCROLLBACK_READY_CAPTURE = `${VIEWPORT_WITHOUT_VISIBLE_PROMPT_CAPTURE}
64
64
 
65
65
  › support lane on multi-image attach`;
66
+ const QUEUED_AFTER_TOOL_CALL_CAPTURE = `• Messages to be submitted after next tool call (press esc to interrupt and send immediately)
67
+ ↳ Read $OMX_TEAM_STATE_ROOT/team/demo/workers/worker-1/inbox.md, work now, report progress
68
+
69
+ › Write tests for @filename`;
66
70
  async function withMockTmuxFixture(dirPrefix, tmuxScript, run) {
67
71
  const fakeBinDir = await mkdtemp(join(tmpdir(), dirPrefix));
68
72
  const logPath = join(fakeBinDir, 'tmux.log');
@@ -306,6 +310,111 @@ esac
306
310
  assert.ok(acceptIndex < submitIndex, `expected bypass acceptance before worker text:\n${log}`);
307
311
  });
308
312
  });
313
+ it('ignores stale queued-next-tool-call banner text that only survives in scrollback history', async () => {
314
+ await withMockTmuxFixture('omx-tmux-codex-stale-queued-scrollback-', (logPath) => `#!/bin/sh
315
+ set -eu
316
+ state_dir="$(dirname "${logPath}")"
317
+ text_sent_file="$state_dir/text-sent"
318
+ printf '%s\n' "$*" >> "${logPath}"
319
+ case "$1" in
320
+ capture-pane)
321
+ if printf '%s\n' "$*" | grep -q -- ' -S -80'; then
322
+ if [ -f "$text_sent_file" ]; then
323
+ cat <<'EOF'
324
+ ${QUEUED_AFTER_TOOL_CALL_CAPTURE}
325
+ EOF
326
+ else
327
+ cat <<'EOF'
328
+ ${READY_HELPER_CAPTURE}
329
+ EOF
330
+ fi
331
+ else
332
+ cat <<'EOF'
333
+ ${READY_HELPER_CAPTURE}
334
+ EOF
335
+ fi
336
+ exit 0
337
+ ;;
338
+ send-keys)
339
+ if [ "\${4:-}" = "-l" ] && [ "\${6:-}" = "check inbox" ]; then
340
+ : > "$text_sent_file"
341
+ fi
342
+ exit 0
343
+ ;;
344
+ *)
345
+ exit 0
346
+ ;;
347
+ esac
348
+ `, async ({ logPath }) => {
349
+ await sendToWorker('omx-team-x', 1, 'check inbox');
350
+ const log = await readFile(logPath, 'utf-8');
351
+ const enterCount = (log.match(/send-keys -t omx-team-x:1 C-m/g) || []).length;
352
+ assert.equal(enterCount, 2, `expected only the baseline submit presses when the queued banner is stale scrollback:\n${log}`);
353
+ assert.match(log, /capture-pane -t omx-team-x:1 -p/);
354
+ assert.match(log, /capture-pane -t omx-team-x:1 -p -S -80/);
355
+ });
356
+ });
357
+ it('keeps nudging Codex when the visible pane still shows a live queued-next-tool-call banner', async () => {
358
+ await withMockTmuxFixture('omx-tmux-codex-visible-queued-submit-', (logPath) => `#!/bin/sh
359
+ set -eu
360
+ state_dir="$(dirname "${logPath}")"
361
+ text_sent_file="$state_dir/text-sent"
362
+ enter_count_file="$state_dir/enter-count"
363
+ printf '%s\n' "$*" >> "${logPath}"
364
+ case "$1" in
365
+ capture-pane)
366
+ enter_count=0
367
+ if [ -f "$enter_count_file" ]; then
368
+ enter_count=$(cat "$enter_count_file")
369
+ fi
370
+ if printf '%s\n' "$*" | grep -q -- ' -S -80'; then
371
+ cat <<'EOF'
372
+ ${READY_HELPER_CAPTURE}
373
+ EOF
374
+ else
375
+ if [ "$enter_count" -ge 4 ]; then
376
+ cat <<'EOF'
377
+ initialized in .
378
+
379
+ ◦ Waiting for background terminal (59s…)
380
+ EOF
381
+ elif [ -f "$text_sent_file" ]; then
382
+ cat <<'EOF'
383
+ ${QUEUED_AFTER_TOOL_CALL_CAPTURE}
384
+ EOF
385
+ else
386
+ cat <<'EOF'
387
+ ${READY_HELPER_CAPTURE}
388
+ EOF
389
+ fi
390
+ fi
391
+ exit 0
392
+ ;;
393
+ send-keys)
394
+ if [ "\${4:-}" = "-l" ] && [ "\${6:-}" = "check inbox" ]; then
395
+ : > "$text_sent_file"
396
+ fi
397
+ if [ "\${4:-}" = "C-m" ]; then
398
+ enter_count=0
399
+ if [ -f "$enter_count_file" ]; then
400
+ enter_count=$(cat "$enter_count_file")
401
+ fi
402
+ enter_count=$((enter_count + 1))
403
+ printf '%s' "$enter_count" > "$enter_count_file"
404
+ fi
405
+ exit 0
406
+ ;;
407
+ *)
408
+ exit 0
409
+ ;;
410
+ esac
411
+ `, async ({ logPath }) => {
412
+ await sendToWorker('omx-team-x', 1, 'check inbox');
413
+ const log = await readFile(logPath, 'utf-8');
414
+ const enterCount = (log.match(/send-keys -t omx-team-x:1 C-m/g) || []).length;
415
+ assert.ok(enterCount >= 4, `expected extra submit nudges when Codex queues the trigger:\n${log}`);
416
+ });
417
+ });
309
418
  });
310
419
  describe('shouldAttemptAdaptiveRetry', () => {
311
420
  it('returns false when adaptive retry is disabled', () => {
@@ -576,7 +685,7 @@ describe('buildWorkerStartupCommand', () => {
576
685
  delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
577
686
  }
578
687
  });
579
- it('uses zsh with ~/.zshrc and exec codex', () => {
688
+ it('uses zsh with ~/.zshrc and non-login shell exec semantics', () => {
580
689
  const prevShell = process.env.SHELL;
581
690
  process.env.SHELL = '/bin/zsh';
582
691
  const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
@@ -584,7 +693,8 @@ describe('buildWorkerStartupCommand', () => {
584
693
  try {
585
694
  const cmd = withMockedExistsSync((candidate) => candidate === '/bin/zsh', () => buildWorkerStartupCommand('alpha', 2));
586
695
  assert.match(cmd, /OMX_TEAM_WORKER=alpha\/worker-2/);
587
- assert.match(cmd, /'\/bin\/zsh' -lc/);
696
+ assert.match(cmd, /'\/bin\/zsh' -c/);
697
+ assert.doesNotMatch(cmd, /'\/bin\/zsh' -lc\b/);
588
698
  assert.match(cmd, /source ~\/\.zshrc/);
589
699
  assert.match(cmd, /exec .*codex/);
590
700
  }
@@ -599,6 +709,28 @@ describe('buildWorkerStartupCommand', () => {
599
709
  delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
600
710
  }
601
711
  });
712
+ it('accepts Homebrew zsh as a supported worker shell without falling back', () => {
713
+ const prevShell = process.env.SHELL;
714
+ const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
715
+ process.env.SHELL = '/opt/homebrew/bin/zsh';
716
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
717
+ try {
718
+ const cmd = withMockedExistsSync((candidate) => candidate === '/opt/homebrew/bin/zsh', () => buildWorkerStartupCommand('alpha', 2));
719
+ assert.match(cmd, /'\/opt\/homebrew\/bin\/zsh' -c/);
720
+ assert.doesNotMatch(cmd, /'\/bin\/sh' -c/);
721
+ assert.match(cmd, /source ~\/\.zshrc/);
722
+ }
723
+ finally {
724
+ if (typeof prevShell === 'string')
725
+ process.env.SHELL = prevShell;
726
+ else
727
+ delete process.env.SHELL;
728
+ if (typeof prevBypass === 'string')
729
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
730
+ else
731
+ delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
732
+ }
733
+ });
602
734
  it('uses bash with ~/.bashrc and preserves launch args', () => {
603
735
  const prevShell = process.env.SHELL;
604
736
  process.env.SHELL = '/bin/bash';
@@ -646,6 +778,87 @@ describe('buildWorkerStartupCommand', () => {
646
778
  delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
647
779
  }
648
780
  });
781
+ it('inherits only allowlisted ambient proxy env vars for tmux startup commands', () => {
782
+ const prevShell = process.env.SHELL;
783
+ const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
784
+ const prevHttpsProxy = process.env.HTTPS_PROXY;
785
+ const prevHttpProxy = process.env.HTTP_PROXY;
786
+ const prevNoProxy = process.env.NO_PROXY;
787
+ const prevLowerHttpsProxy = process.env.https_proxy;
788
+ const prevCustom = process.env.AWS_SECRET_ACCESS_KEY;
789
+ process.env.SHELL = '/bin/bash';
790
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
791
+ process.env.HTTPS_PROXY = 'https://upper-proxy.example:443';
792
+ process.env.HTTP_PROXY = 'http://upper-proxy.example:80';
793
+ process.env.NO_PROXY = 'localhost,127.0.0.1';
794
+ process.env.https_proxy = 'https://lower-proxy.example:443';
795
+ process.env.AWS_SECRET_ACCESS_KEY = 'should-not-inherit';
796
+ try {
797
+ const cmd = buildWorkerStartupCommand('alpha', 1, [], '/tmp/project');
798
+ assert.match(cmd, /HTTPS_PROXY=https:\/\/upper-proxy\.example:443/);
799
+ assert.match(cmd, /HTTP_PROXY=http:\/\/upper-proxy\.example:80/);
800
+ assert.match(cmd, /NO_PROXY=localhost,127\.0\.0\.1/);
801
+ assert.match(cmd, /https_proxy=https:\/\/lower-proxy\.example:443/);
802
+ assert.doesNotMatch(cmd, /AWS_SECRET_ACCESS_KEY=should-not-inherit/);
803
+ }
804
+ finally {
805
+ if (typeof prevShell === 'string')
806
+ process.env.SHELL = prevShell;
807
+ else
808
+ delete process.env.SHELL;
809
+ if (typeof prevBypass === 'string')
810
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
811
+ else
812
+ delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
813
+ if (typeof prevHttpsProxy === 'string')
814
+ process.env.HTTPS_PROXY = prevHttpsProxy;
815
+ else
816
+ delete process.env.HTTPS_PROXY;
817
+ if (typeof prevHttpProxy === 'string')
818
+ process.env.HTTP_PROXY = prevHttpProxy;
819
+ else
820
+ delete process.env.HTTP_PROXY;
821
+ if (typeof prevNoProxy === 'string')
822
+ process.env.NO_PROXY = prevNoProxy;
823
+ else
824
+ delete process.env.NO_PROXY;
825
+ if (typeof prevLowerHttpsProxy === 'string')
826
+ process.env.https_proxy = prevLowerHttpsProxy;
827
+ else
828
+ delete process.env.https_proxy;
829
+ if (typeof prevCustom === 'string')
830
+ process.env.AWS_SECRET_ACCESS_KEY = prevCustom;
831
+ else
832
+ delete process.env.AWS_SECRET_ACCESS_KEY;
833
+ }
834
+ });
835
+ it('preserves explicit worker env precedence over inherited ambient proxy vars', () => {
836
+ const prevShell = process.env.SHELL;
837
+ const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
838
+ const prevHttpsProxy = process.env.HTTPS_PROXY;
839
+ process.env.SHELL = '/bin/bash';
840
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
841
+ process.env.HTTPS_PROXY = 'https://ambient-proxy.example:443';
842
+ try {
843
+ const cmd = buildWorkerStartupCommand('alpha', 1, [], '/tmp/project', { HTTPS_PROXY: 'https://explicit-proxy.example:8443' });
844
+ assert.match(cmd, /HTTPS_PROXY=https:\/\/explicit-proxy\.example:8443/);
845
+ assert.doesNotMatch(cmd, /HTTPS_PROXY=https:\/\/ambient-proxy\.example:443/);
846
+ }
847
+ finally {
848
+ if (typeof prevShell === 'string')
849
+ process.env.SHELL = prevShell;
850
+ else
851
+ delete process.env.SHELL;
852
+ if (typeof prevBypass === 'string')
853
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
854
+ else
855
+ delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
856
+ if (typeof prevHttpsProxy === 'string')
857
+ process.env.HTTPS_PROXY = prevHttpsProxy;
858
+ else
859
+ delete process.env.HTTPS_PROXY;
860
+ }
861
+ });
649
862
  it('resolves POSIX leader paths before building fish worker startup commands', async () => {
650
863
  const fakeBin = await mkdtemp(join(tmpdir(), 'omx-worker-startup-posix-'));
651
864
  const prevPath = process.env.PATH;
@@ -1089,6 +1302,86 @@ describe('buildWorkerStartupCommand', () => {
1089
1302
  await rm(fakeBin, { recursive: true, force: true });
1090
1303
  }
1091
1304
  });
1305
+ it('uses the resolved node-hosted Codex launcher in native Windows startup commands', async () => {
1306
+ const fakeRoot = await mkdtemp(join(tmpdir(), 'omx-worker-startup-win32-node-hosted-'));
1307
+ const fakeBin = join(fakeRoot, 'node_modules', '.bin');
1308
+ const prevPath = process.env.PATH;
1309
+ const prevPathext = process.env.PATHEXT;
1310
+ const prevShell = process.env.SHELL;
1311
+ const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1312
+ const prevLeaderNodePath = process.env.OMX_LEADER_NODE_PATH;
1313
+ const prevMsystem = process.env.MSYSTEM;
1314
+ const prevOstype = process.env.OSTYPE;
1315
+ const prevWsl = process.env.WSL_DISTRO_NAME;
1316
+ const prevWslInterop = process.env.WSL_INTEROP;
1317
+ const origPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
1318
+ process.env.PATH = fakeBin;
1319
+ process.env.PATHEXT = '.CMD;.PS1';
1320
+ process.env.SHELL = '/bin/zsh';
1321
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
1322
+ process.env.OMX_LEADER_NODE_PATH = 'C:\\Program Files\\nodejs\\node.exe';
1323
+ delete process.env.MSYSTEM;
1324
+ delete process.env.OSTYPE;
1325
+ delete process.env.WSL_DISTRO_NAME;
1326
+ delete process.env.WSL_INTEROP;
1327
+ Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
1328
+ try {
1329
+ const codexCmdPath = join(fakeBin, 'codex.cmd');
1330
+ const codexJsPath = join(fakeRoot, 'node_modules', '@openai', 'codex', 'bin', 'codex.js');
1331
+ await mkdir(fakeBin, { recursive: true });
1332
+ await mkdir(join(fakeRoot, 'node_modules', '@openai', 'codex', 'bin'), { recursive: true });
1333
+ await writeFile(codexCmdPath, '@echo off\r\n');
1334
+ await writeFile(codexJsPath, '');
1335
+ const cmd = buildWorkerStartupCommand('alpha', 1, ['--model', 'gpt-5'], 'C:\\repo');
1336
+ const prefix = 'powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -EncodedCommand ';
1337
+ assert.ok(cmd.startsWith(prefix));
1338
+ const decoded = Buffer.from(cmd.slice(prefix.length), 'base64').toString('utf16le');
1339
+ assert.match(decoded, new RegExp(escapeRegExp(`$env:OMX_LEADER_CLI_PATH = '${codexJsPath}'`)));
1340
+ assert.match(decoded, new RegExp(escapeRegExp(`& '${process.execPath}' '${codexJsPath}' '--model' 'gpt-5' '--dangerously-bypass-approvals-and-sandbox'`)));
1341
+ assert.doesNotMatch(decoded, new RegExp(escapeRegExp(codexCmdPath)));
1342
+ }
1343
+ finally {
1344
+ if (origPlatform)
1345
+ Object.defineProperty(process, 'platform', origPlatform);
1346
+ if (typeof prevPath === 'string')
1347
+ process.env.PATH = prevPath;
1348
+ else
1349
+ delete process.env.PATH;
1350
+ if (typeof prevPathext === 'string')
1351
+ process.env.PATHEXT = prevPathext;
1352
+ else
1353
+ delete process.env.PATHEXT;
1354
+ if (typeof prevShell === 'string')
1355
+ process.env.SHELL = prevShell;
1356
+ else
1357
+ delete process.env.SHELL;
1358
+ if (typeof prevBypass === 'string')
1359
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
1360
+ else
1361
+ delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1362
+ if (typeof prevLeaderNodePath === 'string')
1363
+ process.env.OMX_LEADER_NODE_PATH = prevLeaderNodePath;
1364
+ else
1365
+ delete process.env.OMX_LEADER_NODE_PATH;
1366
+ if (typeof prevMsystem === 'string')
1367
+ process.env.MSYSTEM = prevMsystem;
1368
+ else
1369
+ delete process.env.MSYSTEM;
1370
+ if (typeof prevOstype === 'string')
1371
+ process.env.OSTYPE = prevOstype;
1372
+ else
1373
+ delete process.env.OSTYPE;
1374
+ if (typeof prevWsl === 'string')
1375
+ process.env.WSL_DISTRO_NAME = prevWsl;
1376
+ else
1377
+ delete process.env.WSL_DISTRO_NAME;
1378
+ if (typeof prevWslInterop === 'string')
1379
+ process.env.WSL_INTEROP = prevWslInterop;
1380
+ else
1381
+ delete process.env.WSL_INTEROP;
1382
+ await rm(fakeRoot, { recursive: true, force: true });
1383
+ }
1384
+ });
1092
1385
  it('falls back to bash when SHELL is unsupported and zsh candidates are unavailable', () => {
1093
1386
  const prevShell = process.env.SHELL;
1094
1387
  const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
@@ -1118,7 +1411,8 @@ describe('buildWorkerStartupCommand', () => {
1118
1411
  process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
1119
1412
  try {
1120
1413
  const cmd = withMockedExistsSync((candidate) => candidate === '/opt/custom/fish', () => buildWorkerStartupCommand('alpha', 1, [], process.cwd()));
1121
- assert.match(cmd, /'\/bin\/sh' -lc\b/, 'must launch workers through /bin/sh when no supported shells exist');
1414
+ assert.match(cmd, /'\/bin\/sh' -c\b/, 'must launch workers through /bin/sh when no supported shells exist');
1415
+ assert.doesNotMatch(cmd, /'\/bin\/sh' -lc\b/);
1122
1416
  assert.doesNotMatch(cmd, /\.zshrc|\.bashrc/, 'must not source zsh/bash rc files for /bin/sh fallback');
1123
1417
  }
1124
1418
  finally {
@@ -1155,6 +1449,9 @@ describe('team worker CLI helpers', () => {
1155
1449
  it('translateWorkerLaunchArgsForCli returns only skip-permissions for claude', () => {
1156
1450
  assert.deepEqual(translateWorkerLaunchArgsForCli('claude', ['-c', 'model_reasoning_effort="xhigh"', '--model', 'claude-3-7-sonnet']), ['--dangerously-skip-permissions']);
1157
1451
  });
1452
+ it('translateWorkerLaunchArgsForCli keeps read-only claude roles out of skip-permissions mode', () => {
1453
+ assert.deepEqual(translateWorkerLaunchArgsForCli('claude', ['--model', 'claude-3-7-sonnet'], undefined, 'architect'), []);
1454
+ });
1158
1455
  it('translateWorkerLaunchArgsForCli emits gemini approval-mode by default and adds -i when initial prompt is provided', () => {
1159
1456
  assert.deepEqual(translateWorkerLaunchArgsForCli('gemini', ['--model', 'gemini-2.0-pro', '--json']), ['--approval-mode', 'yolo', '--model', 'gemini-2.0-pro']);
1160
1457
  assert.deepEqual(translateWorkerLaunchArgsForCli('gemini', ['--model', 'gemini-2.0-pro', '--json'], 'Read worker inbox'), ['--approval-mode', 'yolo', '-i', 'Read worker inbox', '--model', 'gemini-2.0-pro']);
@@ -1164,6 +1461,9 @@ describe('team worker CLI helpers', () => {
1164
1461
  it('translateWorkerLaunchArgsForCli omits non-gemini default models for gemini workers', () => {
1165
1462
  assert.deepEqual(translateWorkerLaunchArgsForCli('gemini', ['--model', 'gpt-5.3-codex-spark'], 'Read worker inbox'), ['--approval-mode', 'yolo', '-i', 'Read worker inbox']);
1166
1463
  });
1464
+ it('translateWorkerLaunchArgsForCli keeps planning/read-only gemini roles out of yolo mode', () => {
1465
+ assert.deepEqual(translateWorkerLaunchArgsForCli('gemini', ['--model', 'gemini-2.0-pro'], 'Read worker inbox', 'planner'), ['-i', 'Read worker inbox', '--model', 'gemini-2.0-pro']);
1466
+ });
1167
1467
  it('assertTeamWorkerCliBinaryAvailable throws clear error when binary missing', () => {
1168
1468
  assert.throws(() => assertTeamWorkerCliBinaryAvailable('claude', () => false), /not available on PATH/i);
1169
1469
  });
@@ -1243,6 +1543,20 @@ describe('team worker launch mode helpers', () => {
1243
1543
  delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1244
1544
  }
1245
1545
  });
1546
+ it('buildWorkerProcessLaunchSpec does not force codex bypass for read-only roles', () => {
1547
+ const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1548
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
1549
+ try {
1550
+ const spec = buildWorkerProcessLaunchSpec('alpha-team', 2, ['--model', 'gpt-5.3-codex-spark'], '/tmp/workspace', { OMX_TEAM_STATE_ROOT: '/tmp/workspace/.omx/state' }, 'codex', undefined, 'explore');
1551
+ assert.deepEqual(spec.args, ['--model', 'gpt-5.3-codex-spark']);
1552
+ }
1553
+ finally {
1554
+ if (typeof prevBypass === 'string')
1555
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
1556
+ else
1557
+ delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1558
+ }
1559
+ });
1246
1560
  it('buildWorkerProcessLaunchSpec includes leader node and CLI path env vars', () => {
1247
1561
  const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1248
1562
  process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
@@ -1323,6 +1637,72 @@ describe('team worker launch mode helpers', () => {
1323
1637
  await rm(fakeBin, { recursive: true, force: true });
1324
1638
  }
1325
1639
  });
1640
+ it('buildWorkerProcessLaunchSpec records the resolved node-hosted Codex launcher on native Windows', async () => {
1641
+ const fakeRoot = await mkdtemp(join(tmpdir(), 'omx-worker-spec-win32-node-hosted-'));
1642
+ const fakeBin = join(fakeRoot, 'node_modules', '.bin');
1643
+ const prevPath = process.env.PATH;
1644
+ const prevPathext = process.env.PATHEXT;
1645
+ const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1646
+ const prevMsystem = process.env.MSYSTEM;
1647
+ const prevOstype = process.env.OSTYPE;
1648
+ const prevWsl = process.env.WSL_DISTRO_NAME;
1649
+ const prevWslInterop = process.env.WSL_INTEROP;
1650
+ const origPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
1651
+ process.env.PATH = fakeBin;
1652
+ process.env.PATHEXT = '.CMD;.PS1';
1653
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
1654
+ delete process.env.MSYSTEM;
1655
+ delete process.env.OSTYPE;
1656
+ delete process.env.WSL_DISTRO_NAME;
1657
+ delete process.env.WSL_INTEROP;
1658
+ Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
1659
+ try {
1660
+ const codexCmdPath = join(fakeBin, 'codex.cmd');
1661
+ const codexJsPath = join(fakeRoot, 'node_modules', '@openai', 'codex', 'bin', 'codex.js');
1662
+ await mkdir(fakeBin, { recursive: true });
1663
+ await mkdir(join(fakeRoot, 'node_modules', '@openai', 'codex', 'bin'), { recursive: true });
1664
+ await writeFile(codexCmdPath, '@echo off\r\n');
1665
+ await writeFile(codexJsPath, '');
1666
+ const spec = buildWorkerProcessLaunchSpec('beta-team', 1, ['--model', 'gpt-5'], 'C:\\workspace', {}, 'codex');
1667
+ assert.equal(spec.command, process.execPath);
1668
+ assert.deepEqual(spec.args, [codexJsPath, '--model', 'gpt-5', '--dangerously-bypass-approvals-and-sandbox']);
1669
+ assert.equal(spec.env.OMX_LEADER_CLI_PATH, codexJsPath);
1670
+ assert.notEqual(spec.env.OMX_LEADER_CLI_PATH, codexCmdPath);
1671
+ }
1672
+ finally {
1673
+ if (origPlatform)
1674
+ Object.defineProperty(process, 'platform', origPlatform);
1675
+ if (typeof prevPath === 'string')
1676
+ process.env.PATH = prevPath;
1677
+ else
1678
+ delete process.env.PATH;
1679
+ if (typeof prevPathext === 'string')
1680
+ process.env.PATHEXT = prevPathext;
1681
+ else
1682
+ delete process.env.PATHEXT;
1683
+ if (typeof prevBypass === 'string')
1684
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
1685
+ else
1686
+ delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1687
+ if (typeof prevMsystem === 'string')
1688
+ process.env.MSYSTEM = prevMsystem;
1689
+ else
1690
+ delete process.env.MSYSTEM;
1691
+ if (typeof prevOstype === 'string')
1692
+ process.env.OSTYPE = prevOstype;
1693
+ else
1694
+ delete process.env.OSTYPE;
1695
+ if (typeof prevWsl === 'string')
1696
+ process.env.WSL_DISTRO_NAME = prevWsl;
1697
+ else
1698
+ delete process.env.WSL_DISTRO_NAME;
1699
+ if (typeof prevWslInterop === 'string')
1700
+ process.env.WSL_INTEROP = prevWslInterop;
1701
+ else
1702
+ delete process.env.WSL_INTEROP;
1703
+ await rm(fakeRoot, { recursive: true, force: true });
1704
+ }
1705
+ });
1326
1706
  it('buildWorkerProcessLaunchSpec injects the active provider env_key from CODEX_HOME config.toml', async () => {
1327
1707
  const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1328
1708
  const prevCodexHome = process.env.CODEX_HOME;
@@ -1462,6 +1842,26 @@ describe('team worker launch mode helpers', () => {
1462
1842
  await rm(workerCodexHome, { recursive: true, force: true });
1463
1843
  }
1464
1844
  });
1845
+ it('buildWorkerProcessLaunchSpec keeps the worker env contract unchanged for ambient proxy vars', () => {
1846
+ const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1847
+ const prevHttpsProxy = process.env.HTTPS_PROXY;
1848
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
1849
+ process.env.HTTPS_PROXY = 'https://ambient-proxy.example:443';
1850
+ try {
1851
+ const spec = buildWorkerProcessLaunchSpec('eta-team', 1, [], '/tmp/workspace', {}, 'codex');
1852
+ assert.equal(spec.env.HTTPS_PROXY, undefined);
1853
+ }
1854
+ finally {
1855
+ if (typeof prevBypass === 'string')
1856
+ process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
1857
+ else
1858
+ delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1859
+ if (typeof prevHttpsProxy === 'string')
1860
+ process.env.HTTPS_PROXY = prevHttpsProxy;
1861
+ else
1862
+ delete process.env.HTTPS_PROXY;
1863
+ }
1864
+ });
1465
1865
  it('buildWorkerProcessLaunchSpec resolves relative worker CODEX_HOME against the worker cwd', async () => {
1466
1866
  const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
1467
1867
  const prevCodexHome = process.env.CODEX_HOME;
@@ -2463,6 +2863,13 @@ describe('enableMouseScrolling session scoping (issue #817)', () => {
2463
2863
  await withMockTmuxFixture('omx-tmux-enable-mouse-scope-', (tmuxLogPath) => `#!/bin/sh
2464
2864
  printf '%s\n' "$*" >> "${tmuxLogPath}"
2465
2865
  case "$1" in
2866
+ show-options)
2867
+ if [ "$2" = "-gv" ] && [ "$3" = "-t" ] && [ "$4" = "omx-team-x" ] && [ "$5" = "mode-style" ]; then
2868
+ printf '%s\n' 'bg=yellow,fg=black,underscore'
2869
+ exit 0
2870
+ fi
2871
+ exit 1
2872
+ ;;
2466
2873
  set-option)
2467
2874
  if [ "$2" = "-t" ]; then
2468
2875
  exit 0
@@ -2478,11 +2885,47 @@ esac
2478
2885
  const tmuxLog = await readFile(logPath, 'utf-8');
2479
2886
  assert.match(tmuxLog, /set-option -t omx-team-x mouse on/);
2480
2887
  assert.match(tmuxLog, /set-option -t omx-team-x set-clipboard on/);
2888
+ assert.match(tmuxLog, /set-option -t omx-team-x mode-style bg=yellow,fg=black,underscore,nounderscore,nodouble-underscore,nocurly-underscore,nodotted-underscore,nodashed-underscore/);
2481
2889
  assert.doesNotMatch(tmuxLog, /bind-key/);
2482
2890
  assert.doesNotMatch(tmuxLog, /terminal-overrides/);
2483
2891
  });
2484
2892
  });
2485
2893
  });
2894
+ describe('mitigateCopyModeUnderlineArtifacts', () => {
2895
+ it('best-effort sanitizes copy-mode style options without requiring global tmux changes', async () => {
2896
+ await withMockTmuxFixture('omx-tmux-sanitize-copy-style-', (tmuxLogPath) => `#!/bin/sh
2897
+ printf '%s\n' "$*" >> "${tmuxLogPath}"
2898
+ case "$1" in
2899
+ show-options)
2900
+ if [ "$2" = "-gv" ] && [ "$3" = "-t" ] && [ "$4" = "omx-team-x" ] && [ "$5" = "mode-style" ]; then
2901
+ printf '%s\n' 'bg=yellow,fg=black,underscore'
2902
+ exit 0
2903
+ fi
2904
+ if [ "$2" = "-gv" ] && [ "$3" = "-t" ] && [ "$4" = "omx-team-x" ] && [ "$5" = "copy-mode-selection-style" ]; then
2905
+ printf '%s\n' 'fg=white,bg=blue,curly-underscore'
2906
+ exit 0
2907
+ fi
2908
+ exit 1
2909
+ ;;
2910
+ set-option)
2911
+ if [ "$2" = "-t" ]; then
2912
+ exit 0
2913
+ fi
2914
+ exit 1
2915
+ ;;
2916
+ *)
2917
+ exit 0
2918
+ ;;
2919
+ esac
2920
+ `, async ({ logPath }) => {
2921
+ assert.equal(mitigateCopyModeUnderlineArtifacts('omx-team-x'), true);
2922
+ const tmuxLog = await readFile(logPath, 'utf-8');
2923
+ assert.match(tmuxLog, /set-option -t omx-team-x mode-style bg=yellow,fg=black,underscore,nounderscore,nodouble-underscore,nocurly-underscore,nodotted-underscore,nodashed-underscore/);
2924
+ assert.match(tmuxLog, /set-option -t omx-team-x copy-mode-selection-style fg=white,bg=blue,curly-underscore,nounderscore,nodouble-underscore,nocurly-underscore,nodotted-underscore,nodashed-underscore/);
2925
+ assert.doesNotMatch(tmuxLog, /set-option -g/);
2926
+ });
2927
+ });
2928
+ });
2486
2929
  describe('killWorker leader pane guard', () => {
2487
2930
  it('returns immediately when workerPaneId matches leaderPaneId', () => {
2488
2931
  // Guard fires before any tmux send-keys call, so no error even with empty PATH.