oh-my-opencode 4.8.1 → 4.9.1

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 (509) hide show
  1. package/dist/agents/prometheus/system-prompt.d.ts +1 -1
  2. package/dist/agents/sisyphus/claude-fable-5.d.ts +19 -0
  3. package/dist/agents/sisyphus/claude-opus-4-7.d.ts +3 -1
  4. package/dist/agents/sisyphus/claude-opus-4-8.d.ts +19 -0
  5. package/dist/agents/sisyphus/index.d.ts +4 -0
  6. package/dist/agents/types.d.ts +2 -2
  7. package/dist/cli/doctor/checks/codex.d.ts +1 -0
  8. package/dist/cli/doctor/checks/dependencies.d.ts +2 -2
  9. package/dist/cli/doctor/checks/tools-gh.d.ts +8 -1
  10. package/dist/cli/doctor/index.d.ts +1 -0
  11. package/dist/cli/doctor/types.d.ts +2 -0
  12. package/dist/cli/index.js +1908 -787
  13. package/dist/cli/install-codex/codex-config-permissions.d.ts +1 -1
  14. package/dist/cli/install-codex/codex-config-plugins.d.ts +1 -0
  15. package/dist/cli/install-codex/codex-config-toml.d.ts +1 -0
  16. package/dist/cli/install-codex/codex-installer-bin-dir.d.ts +8 -0
  17. package/dist/cli/install-codex/install-codex.d.ts +1 -8
  18. package/dist/cli/install-codex/lsp-daemon-reaper.d.ts +5 -0
  19. package/dist/cli/sparkshell-condense.d.ts +10 -0
  20. package/dist/cli/sparkshell-parse.d.ts +3 -0
  21. package/dist/cli/sparkshell-session-context.d.ts +20 -0
  22. package/dist/cli/sparkshell-spark.d.ts +23 -0
  23. package/dist/cli/sparkshell.d.ts +8 -1
  24. package/dist/cli-node/index.js +92564 -0
  25. package/dist/config/schema/agent-names.d.ts +2 -0
  26. package/dist/config/schema/hooks.d.ts +0 -2
  27. package/dist/config/schema/keyword-detector.d.ts +0 -6
  28. package/dist/config/schema/oh-my-opencode-config.d.ts +2 -4
  29. package/dist/create-hooks.d.ts +0 -2
  30. package/dist/features/background-agent/parent-wake-dedupe.d.ts +2 -0
  31. package/dist/features/background-agent/parent-wake-flush-runner.d.ts +2 -0
  32. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -0
  33. package/dist/features/background-agent/parent-wake-session-history.d.ts +4 -0
  34. package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -0
  35. package/dist/features/builtin-commands/templates/handoff.d.ts +1 -1
  36. package/dist/features/builtin-skills/index.d.ts +1 -1
  37. package/dist/features/builtin-skills/skills.d.ts +4 -0
  38. package/dist/features/opencode-runtime-skills/source-server.d.ts +16 -1
  39. package/dist/features/opencode-skill-loader/skill-definition-record.d.ts +2 -0
  40. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +2 -0
  41. package/dist/features/team-mode/types.d.ts +1 -0
  42. package/dist/features/tmux-subagent/failed-readiness-cache.d.ts +28 -0
  43. package/dist/features/tmux-subagent/manager.d.ts +1 -9
  44. package/dist/features/tmux-subagent/resolve-server-url.d.ts +3 -0
  45. package/dist/hooks/anthropic-context-window-limit-recovery/executor.d.ts +1 -1
  46. package/dist/hooks/index.d.ts +0 -1
  47. package/dist/hooks/keyword-detector/constants.d.ts +0 -4
  48. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +1 -1
  49. package/dist/index.js +9001 -1795
  50. package/dist/oh-my-opencode.schema.json +2 -4
  51. package/dist/plugin/chat-params.d.ts +1 -8
  52. package/dist/plugin/hooks/create-core-hooks.d.ts +0 -2
  53. package/dist/plugin/hooks/create-session-hooks.d.ts +0 -2
  54. package/dist/plugin/hooks/create-transform-hooks.d.ts +1 -2
  55. package/dist/plugin/messages-transform.d.ts +0 -1
  56. package/dist/shared/model-availability.d.ts +10 -2
  57. package/dist/shared/module-resolution-failure.d.ts +7 -0
  58. package/package.json +25 -18
  59. package/packages/ast-grep-mcp/dist/cli.js +2 -10
  60. package/packages/git-bash-mcp/dist/cli.js +11 -4
  61. package/packages/lsp-daemon/dist/cli.d.ts +2 -0
  62. package/packages/lsp-daemon/dist/cli.js +3711 -0
  63. package/packages/lsp-daemon/dist/daemon-client.d.ts +19 -0
  64. package/packages/lsp-daemon/dist/daemon-client.js +114 -0
  65. package/packages/lsp-daemon/dist/daemon-server.d.ts +12 -0
  66. package/packages/lsp-daemon/dist/daemon-server.js +106 -0
  67. package/packages/lsp-daemon/dist/ensure-daemon.d.ts +21 -0
  68. package/packages/lsp-daemon/dist/ensure-daemon.js +97 -0
  69. package/packages/lsp-daemon/dist/index.d.ts +5 -0
  70. package/packages/lsp-daemon/dist/index.js +3573 -0
  71. package/packages/lsp-daemon/dist/lock.d.ts +7 -0
  72. package/packages/lsp-daemon/dist/lock.js +61 -0
  73. package/packages/lsp-daemon/dist/package.json +6 -0
  74. package/packages/lsp-daemon/dist/paths.d.ts +11 -0
  75. package/packages/lsp-daemon/dist/paths.js +49 -0
  76. package/packages/lsp-daemon/dist/proxy.d.ts +10 -0
  77. package/packages/lsp-daemon/dist/proxy.js +61 -0
  78. package/packages/lsp-daemon/dist/request-routing.d.ts +9 -0
  79. package/packages/lsp-daemon/dist/request-routing.js +44 -0
  80. package/packages/lsp-daemon/dist/run-daemon.d.ts +1 -0
  81. package/packages/lsp-daemon/dist/run-daemon.js +11 -0
  82. package/packages/lsp-daemon/dist/socket-jsonrpc.d.ts +5 -0
  83. package/packages/lsp-daemon/dist/socket-jsonrpc.js +25 -0
  84. package/packages/lsp-daemon/package.json +38 -0
  85. package/packages/lsp-tools-mcp/dist/cli.js +0 -0
  86. package/packages/lsp-tools-mcp/dist/lsp/client-wrapper.js +40 -17
  87. package/packages/lsp-tools-mcp/dist/lsp/client.js +11 -9
  88. package/packages/lsp-tools-mcp/dist/lsp/config-loader.js +5 -5
  89. package/packages/lsp-tools-mcp/dist/lsp/directory-diagnostics.js +5 -3
  90. package/packages/lsp-tools-mcp/dist/lsp/effective-extension.d.ts +1 -0
  91. package/packages/lsp-tools-mcp/dist/lsp/effective-extension.js +8 -0
  92. package/packages/lsp-tools-mcp/dist/lsp/infer-extension.js +3 -2
  93. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.js +1 -0
  94. package/packages/lsp-tools-mcp/dist/lsp/server-definitions.js +12 -0
  95. package/packages/lsp-tools-mcp/dist/lsp/server-install-state.d.ts +12 -0
  96. package/packages/lsp-tools-mcp/dist/lsp/server-install-state.js +51 -0
  97. package/packages/lsp-tools-mcp/dist/lsp/workspace-edit.js +2 -1
  98. package/packages/lsp-tools-mcp/dist/request-context.d.ts +7 -0
  99. package/packages/lsp-tools-mcp/dist/request-context.js +14 -0
  100. package/packages/lsp-tools-mcp/dist/tools.js +44 -1
  101. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +46 -33
  102. package/packages/omo-codex/plugin/.mcp.json +1 -1
  103. package/packages/omo-codex/plugin/components/comment-checker/dist/apply-patch.d.ts +7 -0
  104. package/packages/omo-codex/plugin/components/comment-checker/dist/apply-patch.js +173 -0
  105. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.d.ts +2 -0
  106. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +10 -0
  107. package/packages/omo-codex/plugin/components/comment-checker/dist/codex-hook.d.ts +22 -0
  108. package/packages/omo-codex/plugin/components/comment-checker/dist/codex-hook.js +165 -0
  109. package/packages/omo-codex/plugin/components/comment-checker/dist/core-values.d.ts +1 -0
  110. package/packages/omo-codex/plugin/components/comment-checker/dist/core-values.js +1 -0
  111. package/packages/omo-codex/plugin/components/comment-checker/dist/core.d.ts +5 -0
  112. package/packages/omo-codex/plugin/components/comment-checker/dist/core.js +4 -0
  113. package/packages/omo-codex/plugin/components/comment-checker/dist/hook-input.d.ts +6 -0
  114. package/packages/omo-codex/plugin/components/comment-checker/dist/hook-input.js +10 -0
  115. package/packages/omo-codex/plugin/components/comment-checker/dist/record.d.ts +2 -0
  116. package/packages/omo-codex/plugin/components/comment-checker/dist/record.js +11 -0
  117. package/packages/omo-codex/plugin/components/comment-checker/dist/request-extractor.d.ts +3 -0
  118. package/packages/omo-codex/plugin/components/comment-checker/dist/request-extractor.js +104 -0
  119. package/packages/omo-codex/plugin/components/comment-checker/dist/runner.d.ts +26 -0
  120. package/packages/omo-codex/plugin/components/comment-checker/dist/runner.js +144 -0
  121. package/packages/omo-codex/plugin/components/comment-checker/dist/types.d.ts +43 -0
  122. package/packages/omo-codex/plugin/components/comment-checker/dist/types.js +1 -0
  123. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  124. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  125. package/packages/omo-codex/plugin/components/git-bash/dist/cli.d.ts +2 -0
  126. package/packages/omo-codex/plugin/components/git-bash/dist/cli.js +29 -0
  127. package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.d.ts +28 -0
  128. package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.js +137 -0
  129. package/packages/omo-codex/plugin/components/git-bash/dist/index.d.ts +1 -0
  130. package/packages/omo-codex/plugin/components/git-bash/dist/index.js +1 -0
  131. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  132. package/packages/omo-codex/plugin/components/git-bash/package.json +5 -2
  133. package/packages/omo-codex/plugin/components/lsp/.mcp.json +1 -1
  134. package/packages/omo-codex/plugin/components/lsp/dist/cli.d.ts +2 -0
  135. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +42 -0
  136. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook-cli.d.ts +2 -0
  137. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook-cli.js +40 -0
  138. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook.d.ts +16 -0
  139. package/packages/omo-codex/plugin/components/lsp/dist/codex-hook.js +180 -0
  140. package/packages/omo-codex/plugin/components/lsp/dist/lsp-session-state.d.ts +12 -0
  141. package/packages/omo-codex/plugin/components/lsp/dist/lsp-session-state.js +95 -0
  142. package/packages/omo-codex/plugin/components/lsp/dist/mutated-file-paths.d.ts +6 -0
  143. package/packages/omo-codex/plugin/components/lsp/dist/mutated-file-paths.js +79 -0
  144. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  145. package/packages/omo-codex/plugin/components/lsp/package.json +7 -7
  146. package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-daemon.mjs +68 -0
  147. package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-tools.mjs +45 -22
  148. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  149. package/packages/omo-codex/plugin/components/lsp/src/codex-hook-cli.ts +1 -1
  150. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +6 -2
  151. package/packages/omo-codex/plugin/components/lsp/src/lsp-session-state.ts +4 -0
  152. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +68 -0
  153. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +8 -20
  154. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +69 -96
  155. package/packages/omo-codex/plugin/components/rules/dist/cli.d.ts +2 -0
  156. package/packages/omo-codex/plugin/components/rules/dist/cli.js +118 -0
  157. package/packages/omo-codex/plugin/components/rules/dist/codex-hook-options.d.ts +5 -0
  158. package/packages/omo-codex/plugin/components/rules/dist/codex-hook-options.js +1 -0
  159. package/packages/omo-codex/plugin/components/rules/dist/codex-hook.d.ts +47 -0
  160. package/packages/omo-codex/plugin/components/rules/dist/codex-hook.js +127 -0
  161. package/packages/omo-codex/plugin/components/rules/dist/config.d.ts +2 -0
  162. package/packages/omo-codex/plugin/components/rules/dist/config.js +100 -0
  163. package/packages/omo-codex/plugin/components/rules/dist/context-pressure.d.ts +2 -0
  164. package/packages/omo-codex/plugin/components/rules/dist/context-pressure.js +26 -0
  165. package/packages/omo-codex/plugin/components/rules/dist/debug-log.d.ts +8 -0
  166. package/packages/omo-codex/plugin/components/rules/dist/debug-log.js +36 -0
  167. package/packages/omo-codex/plugin/components/rules/dist/dynamic-target-fingerprints.d.ts +7 -0
  168. package/packages/omo-codex/plugin/components/rules/dist/dynamic-target-fingerprints.js +65 -0
  169. package/packages/omo-codex/plugin/components/rules/dist/event-budget.d.ts +3 -0
  170. package/packages/omo-codex/plugin/components/rules/dist/event-budget.js +14 -0
  171. package/packages/omo-codex/plugin/components/rules/dist/hook-output.d.ts +2 -0
  172. package/packages/omo-codex/plugin/components/rules/dist/hook-output.js +24 -0
  173. package/packages/omo-codex/plugin/components/rules/dist/path-utils.d.ts +4 -0
  174. package/packages/omo-codex/plugin/components/rules/dist/path-utils.js +24 -0
  175. package/packages/omo-codex/plugin/components/rules/dist/persistent-cache.d.ts +13 -0
  176. package/packages/omo-codex/plugin/components/rules/dist/persistent-cache.js +172 -0
  177. package/packages/omo-codex/plugin/components/rules/dist/post-compact-budget.d.ts +6 -0
  178. package/packages/omo-codex/plugin/components/rules/dist/post-compact-budget.js +74 -0
  179. package/packages/omo-codex/plugin/components/rules/dist/post-compact-claim.d.ts +4 -0
  180. package/packages/omo-codex/plugin/components/rules/dist/post-compact-claim.js +6 -0
  181. package/packages/omo-codex/plugin/components/rules/dist/post-compact-directive.d.ts +1 -0
  182. package/packages/omo-codex/plugin/components/rules/dist/post-compact-directive.js +32 -0
  183. package/packages/omo-codex/plugin/components/rules/dist/post-compact-state.d.ts +13 -0
  184. package/packages/omo-codex/plugin/components/rules/dist/post-compact-state.js +29 -0
  185. package/packages/omo-codex/plugin/components/rules/dist/rules/cache.d.ts +9 -0
  186. package/packages/omo-codex/plugin/components/rules/dist/rules/cache.js +51 -0
  187. package/packages/omo-codex/plugin/components/rules/dist/rules/constants.d.ts +70 -0
  188. package/packages/omo-codex/plugin/components/rules/dist/rules/constants.js +101 -0
  189. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-cache.d.ts +5 -0
  190. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-cache.js +60 -0
  191. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-loader.d.ts +6 -0
  192. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-dynamic-loader.js +61 -0
  193. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-loader.d.ts +7 -0
  194. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-loader.js +60 -0
  195. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-paths.d.ts +11 -0
  196. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-paths.js +75 -0
  197. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-static-loader.d.ts +6 -0
  198. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-static-loader.js +29 -0
  199. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-types.d.ts +44 -0
  200. package/packages/omo-codex/plugin/components/rules/dist/rules/engine-types.js +1 -0
  201. package/packages/omo-codex/plugin/components/rules/dist/rules/engine.d.ts +5 -0
  202. package/packages/omo-codex/plugin/components/rules/dist/rules/engine.js +85 -0
  203. package/packages/omo-codex/plugin/components/rules/dist/rules/errors.d.ts +6 -0
  204. package/packages/omo-codex/plugin/components/rules/dist/rules/errors.js +12 -0
  205. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-cache.d.ts +14 -0
  206. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-cache.js +51 -0
  207. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-paths.d.ts +6 -0
  208. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-paths.js +33 -0
  209. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-sources.d.ts +5 -0
  210. package/packages/omo-codex/plugin/components/rules/dist/rules/finder-sources.js +40 -0
  211. package/packages/omo-codex/plugin/components/rules/dist/rules/finder.d.ts +28 -0
  212. package/packages/omo-codex/plugin/components/rules/dist/rules/finder.js +146 -0
  213. package/packages/omo-codex/plugin/components/rules/dist/rules/formatter.d.ts +7 -0
  214. package/packages/omo-codex/plugin/components/rules/dist/rules/formatter.js +112 -0
  215. package/packages/omo-codex/plugin/components/rules/dist/rules/matcher.d.ts +18 -0
  216. package/packages/omo-codex/plugin/components/rules/dist/rules/matcher.js +93 -0
  217. package/packages/omo-codex/plugin/components/rules/dist/rules/ordering.d.ts +3 -0
  218. package/packages/omo-codex/plugin/components/rules/dist/rules/ordering.js +27 -0
  219. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-frontmatter.d.ts +7 -0
  220. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-frontmatter.js +30 -0
  221. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-yaml.d.ts +2 -0
  222. package/packages/omo-codex/plugin/components/rules/dist/rules/parser-yaml.js +237 -0
  223. package/packages/omo-codex/plugin/components/rules/dist/rules/parser.d.ts +3 -0
  224. package/packages/omo-codex/plugin/components/rules/dist/rules/parser.js +31 -0
  225. package/packages/omo-codex/plugin/components/rules/dist/rules/plugin-root.d.ts +1 -0
  226. package/packages/omo-codex/plugin/components/rules/dist/rules/plugin-root.js +48 -0
  227. package/packages/omo-codex/plugin/components/rules/dist/rules/project-root.d.ts +1 -0
  228. package/packages/omo-codex/plugin/components/rules/dist/rules/project-root.js +23 -0
  229. package/packages/omo-codex/plugin/components/rules/dist/rules/scanner.d.ts +14 -0
  230. package/packages/omo-codex/plugin/components/rules/dist/rules/scanner.js +111 -0
  231. package/packages/omo-codex/plugin/components/rules/dist/rules/sources.d.ts +3 -0
  232. package/packages/omo-codex/plugin/components/rules/dist/rules/sources.js +9 -0
  233. package/packages/omo-codex/plugin/components/rules/dist/rules/truncator.d.ts +18 -0
  234. package/packages/omo-codex/plugin/components/rules/dist/rules/truncator.js +59 -0
  235. package/packages/omo-codex/plugin/components/rules/dist/rules/types.d.ts +126 -0
  236. package/packages/omo-codex/plugin/components/rules/dist/rules/types.js +8 -0
  237. package/packages/omo-codex/plugin/components/rules/dist/rules-engine-factory.d.ts +6 -0
  238. package/packages/omo-codex/plugin/components/rules/dist/rules-engine-factory.js +20 -0
  239. package/packages/omo-codex/plugin/components/rules/dist/session-state-lock.d.ts +3 -0
  240. package/packages/omo-codex/plugin/components/rules/dist/session-state-lock.js +41 -0
  241. package/packages/omo-codex/plugin/components/rules/dist/sparkshell-awareness.d.ts +10 -0
  242. package/packages/omo-codex/plugin/components/rules/dist/sparkshell-awareness.js +90 -0
  243. package/packages/omo-codex/plugin/components/rules/dist/static-injection.d.ts +3 -0
  244. package/packages/omo-codex/plugin/components/rules/dist/static-injection.js +128 -0
  245. package/packages/omo-codex/plugin/components/rules/dist/tool-paths.d.ts +6 -0
  246. package/packages/omo-codex/plugin/components/rules/dist/tool-paths.js +168 -0
  247. package/packages/omo-codex/plugin/components/rules/dist/transcript-rule-filter.d.ts +4 -0
  248. package/packages/omo-codex/plugin/components/rules/dist/transcript-rule-filter.js +49 -0
  249. package/packages/omo-codex/plugin/components/rules/dist/transcript-search.d.ts +4 -0
  250. package/packages/omo-codex/plugin/components/rules/dist/transcript-search.js +91 -0
  251. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  252. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  253. package/packages/omo-codex/plugin/components/rules/src/codex-hook.ts +4 -2
  254. package/packages/omo-codex/plugin/components/rules/src/config.ts +13 -0
  255. package/packages/omo-codex/plugin/components/rules/src/event-budget.ts +17 -0
  256. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +4 -1
  257. package/packages/omo-codex/plugin/components/rules/src/post-compact-directive.ts +39 -0
  258. package/packages/omo-codex/plugin/components/rules/src/rules/constants.ts +16 -0
  259. package/packages/omo-codex/plugin/components/rules/src/rules/engine.ts +8 -0
  260. package/packages/omo-codex/plugin/components/rules/src/rules/types.ts +4 -0
  261. package/packages/omo-codex/plugin/components/rules/src/sparkshell-awareness.ts +53 -4
  262. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +127 -7
  263. package/packages/omo-codex/plugin/components/rules/src/transcript-rule-filter.ts +9 -1
  264. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +4 -2
  265. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +7 -2
  266. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +9 -9
  267. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +10 -4
  268. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +241 -0
  269. package/packages/omo-codex/plugin/components/rules/test/event-budget.test.ts +168 -0
  270. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +4 -0
  271. package/packages/omo-codex/plugin/components/rules/test/sparkshell-awareness.test.ts +86 -3
  272. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +15 -15
  273. package/packages/omo-codex/plugin/components/start-work-continuation/dist/boulder-reader.d.ts +16 -0
  274. package/packages/omo-codex/plugin/components/start-work-continuation/dist/boulder-reader.js +146 -0
  275. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.d.ts +2 -0
  276. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +49 -0
  277. package/packages/omo-codex/plugin/components/start-work-continuation/dist/codex-hook.d.ts +2 -0
  278. package/packages/omo-codex/plugin/components/start-work-continuation/dist/codex-hook.js +80 -0
  279. package/packages/omo-codex/plugin/components/start-work-continuation/dist/directive.d.ts +1 -0
  280. package/packages/omo-codex/plugin/components/start-work-continuation/dist/directive.js +2 -0
  281. package/packages/omo-codex/plugin/components/start-work-continuation/dist/index.d.ts +5 -0
  282. package/packages/omo-codex/plugin/components/start-work-continuation/dist/index.js +3 -0
  283. package/packages/omo-codex/plugin/components/start-work-continuation/dist/types.d.ts +20 -0
  284. package/packages/omo-codex/plugin/components/start-work-continuation/dist/types.js +1 -0
  285. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  286. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  287. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +24 -2
  288. package/packages/omo-codex/plugin/components/telemetry/dist/atomic-write.d.ts +1 -0
  289. package/packages/omo-codex/plugin/components/telemetry/dist/atomic-write.js +18 -0
  290. package/packages/omo-codex/plugin/components/telemetry/dist/cli.d.ts +2 -0
  291. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +62 -0
  292. package/packages/omo-codex/plugin/components/telemetry/dist/codex-hook.d.ts +15 -0
  293. package/packages/omo-codex/plugin/components/telemetry/dist/codex-hook.js +42 -0
  294. package/packages/omo-codex/plugin/components/telemetry/dist/data-path.d.ts +10 -0
  295. package/packages/omo-codex/plugin/components/telemetry/dist/data-path.js +35 -0
  296. package/packages/omo-codex/plugin/components/telemetry/dist/diagnostics.d.ts +12 -0
  297. package/packages/omo-codex/plugin/components/telemetry/dist/diagnostics.js +108 -0
  298. package/packages/omo-codex/plugin/components/telemetry/dist/env-flags.d.ts +4 -0
  299. package/packages/omo-codex/plugin/components/telemetry/dist/env-flags.js +31 -0
  300. package/packages/omo-codex/plugin/components/telemetry/dist/posthog-activity-state.d.ts +8 -0
  301. package/packages/omo-codex/plugin/components/telemetry/dist/posthog-activity-state.js +68 -0
  302. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.d.ts +21 -0
  303. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +133 -0
  304. package/packages/omo-codex/plugin/components/telemetry/dist/product-identity.d.ts +8 -0
  305. package/packages/omo-codex/plugin/components/telemetry/dist/product-identity.js +29 -0
  306. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  307. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  308. package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +5 -13
  309. package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +61 -185
  310. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  311. package/packages/omo-codex/plugin/components/ultrawork/directive.md +122 -117
  312. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.d.ts +2 -0
  313. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +48 -0
  314. package/packages/omo-codex/plugin/components/ultrawork/dist/codex-hook.d.ts +7 -0
  315. package/packages/omo-codex/plugin/components/ultrawork/dist/codex-hook.js +122 -0
  316. package/packages/omo-codex/plugin/components/ultrawork/dist/directive.d.ts +1 -0
  317. package/packages/omo-codex/plugin/components/ultrawork/dist/directive.js +2 -0
  318. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  319. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  320. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +20 -11
  321. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +17 -11
  322. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +2 -5
  323. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +0 -71
  324. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.d.ts +16 -0
  325. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +200 -0
  326. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.d.ts +17 -0
  327. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +97 -0
  328. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.d.ts +4 -0
  329. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +183 -0
  330. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +6 -0
  331. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +55 -0
  332. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +12 -0
  333. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +145 -0
  334. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.d.ts +2 -0
  335. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +39 -0
  336. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +13 -0
  337. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +100 -0
  338. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +26 -0
  339. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +97 -0
  340. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.d.ts +28 -0
  341. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +145 -0
  342. package/packages/omo-codex/plugin/components/ulw-loop/dist/command-types.d.ts +34 -0
  343. package/packages/omo-codex/plugin/components/ulw-loop/dist/command-types.js +1 -0
  344. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +16 -0
  345. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +41 -0
  346. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +95 -0
  347. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.js +1 -0
  348. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.d.ts +31 -0
  349. package/packages/omo-codex/plugin/components/ulw-loop/dist/evidence.js +119 -0
  350. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +12 -0
  351. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +69 -0
  352. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +16 -0
  353. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +59 -0
  354. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +48 -0
  355. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +119 -0
  356. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +8 -0
  357. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +89 -0
  358. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +6 -0
  359. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +123 -0
  360. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.d.ts +16 -0
  361. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +70 -0
  362. package/packages/omo-codex/plugin/components/ulw-loop/dist/runtime.d.ts +10 -0
  363. package/packages/omo-codex/plugin/components/ulw-loop/dist/runtime.js +13 -0
  364. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.d.ts +63 -0
  365. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-types.js +1 -0
  366. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.d.ts +6 -0
  367. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +292 -0
  368. package/packages/omo-codex/plugin/components/ulw-loop/dist/types.d.ts +5 -0
  369. package/packages/omo-codex/plugin/components/ulw-loop/dist/types.js +5 -0
  370. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
  371. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  372. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +14 -14
  373. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +24 -25
  374. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +17 -3
  375. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +2 -1
  376. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -1
  377. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +95 -0
  378. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +0 -96
  379. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +23 -0
  380. package/packages/omo-codex/plugin/components/ulw-loop/test/skill-contract.test.ts +46 -0
  381. package/packages/omo-codex/plugin/hooks/hooks.json +16 -16
  382. package/packages/omo-codex/plugin/package-lock.json +10 -9
  383. package/packages/omo-codex/plugin/package.json +27 -26
  384. package/packages/omo-codex/plugin/scripts/auto-update.mjs +64 -15
  385. package/packages/omo-codex/plugin/scripts/build-bundled-mcp-runtimes.mjs +16 -0
  386. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +82 -18
  387. package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +2 -2
  388. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +23 -11
  389. package/packages/omo-codex/plugin/scripts/sync-version.mjs +94 -0
  390. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +9 -9
  391. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +16 -1
  392. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +93 -0
  393. package/packages/omo-codex/plugin/skills/lcx-doctor/agents/openai.yaml +11 -0
  394. package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +17 -13
  395. package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +139 -0
  396. package/packages/omo-codex/plugin/skills/lsp-setup/references/bash/README.md +60 -0
  397. package/packages/omo-codex/plugin/skills/lsp-setup/references/c-cpp/README.md +61 -0
  398. package/packages/omo-codex/plugin/skills/lsp-setup/references/csharp/README.md +71 -0
  399. package/packages/omo-codex/plugin/skills/lsp-setup/references/dart/README.md +48 -0
  400. package/packages/omo-codex/plugin/skills/lsp-setup/references/elixir/README.md +51 -0
  401. package/packages/omo-codex/plugin/skills/lsp-setup/references/go/README.md +57 -0
  402. package/packages/omo-codex/plugin/skills/lsp-setup/references/haskell/README.md +57 -0
  403. package/packages/omo-codex/plugin/skills/lsp-setup/references/java/README.md +57 -0
  404. package/packages/omo-codex/plugin/skills/lsp-setup/references/julia/README.md +60 -0
  405. package/packages/omo-codex/plugin/skills/lsp-setup/references/kotlin/README.md +59 -0
  406. package/packages/omo-codex/plugin/skills/lsp-setup/references/lua/README.md +66 -0
  407. package/packages/omo-codex/plugin/skills/lsp-setup/references/php/README.md +62 -0
  408. package/packages/omo-codex/plugin/skills/lsp-setup/references/python/README.md +71 -0
  409. package/packages/omo-codex/plugin/skills/lsp-setup/references/ruby/README.md +53 -0
  410. package/packages/omo-codex/plugin/skills/lsp-setup/references/rust/README.md +59 -0
  411. package/packages/omo-codex/plugin/skills/lsp-setup/references/swift/README.md +51 -0
  412. package/packages/omo-codex/plugin/skills/lsp-setup/references/terraform/README.md +62 -0
  413. package/packages/omo-codex/plugin/skills/lsp-setup/references/typescript/README.md +77 -0
  414. package/packages/omo-codex/plugin/skills/lsp-setup/references/yaml/README.md +70 -0
  415. package/packages/omo-codex/plugin/skills/lsp-setup/references/zig/README.md +49 -0
  416. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/detect-lsp.ts +210 -0
  417. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/lsp-server-table.ts +177 -0
  418. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/tsconfig.json +17 -0
  419. package/packages/omo-codex/plugin/skills/lsp-setup/scripts/verify-lsp.ts +147 -0
  420. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +9 -9
  421. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +10 -10
  422. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +20 -22
  423. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +38 -61
  424. package/packages/omo-codex/plugin/skills/ultraresearch/SKILL.md +135 -677
  425. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +14 -14
  426. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +24 -25
  427. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +20 -11
  428. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +17 -11
  429. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +9 -9
  430. package/packages/omo-codex/plugin/test/aggregate-build.test.mjs +2 -1
  431. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +1 -1
  432. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +5 -5
  433. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +6 -6
  434. package/packages/omo-codex/plugin/test/auto-update-restart-notice.test.mjs +194 -0
  435. package/packages/omo-codex/plugin/test/auto-update.test.mjs +17 -0
  436. package/packages/omo-codex/plugin/test/lcx-bug-skills.test.mjs +15 -44
  437. package/packages/omo-codex/plugin/test/lsp-prebuild-layouts.test.mjs +140 -0
  438. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +189 -7
  439. package/packages/omo-codex/plugin/test/start-work-skill.test.mjs +9 -31
  440. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +68 -4
  441. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +119 -0
  442. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +11 -112
  443. package/packages/omo-codex/plugin/test/sync-version.test.mjs +68 -0
  444. package/packages/omo-codex/plugin/test/ultraresearch-skill-contract.test.mjs +126 -0
  445. package/packages/omo-codex/plugin/test/ulw-plan-skill.test.mjs +2 -2
  446. package/packages/omo-codex/scripts/install/bin-dir.mjs +20 -0
  447. package/packages/omo-codex/scripts/install/bin-links.mjs +43 -6
  448. package/packages/omo-codex/scripts/install/cache.mjs +4 -0
  449. package/packages/omo-codex/scripts/install/config.mjs +4 -4
  450. package/packages/omo-codex/scripts/install/delegated-command.mjs +5 -1
  451. package/packages/omo-codex/scripts/install/git-bash-mcp-env.mjs +28 -0
  452. package/packages/omo-codex/scripts/install/git-bash.mjs +12 -4
  453. package/packages/omo-codex/scripts/install/git-bash.test.mjs +39 -4
  454. package/packages/omo-codex/scripts/install/hook-targets.mjs +46 -0
  455. package/packages/omo-codex/scripts/install/multi-agent-v2-config.mjs +12 -2
  456. package/packages/omo-codex/scripts/install/process.mjs +1 -0
  457. package/packages/omo-codex/scripts/install-bin-links.test.mjs +131 -3
  458. package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +91 -0
  459. package/packages/omo-codex/scripts/install-config.test.mjs +50 -44
  460. package/packages/omo-codex/scripts/install-delegated-command.test.mjs +78 -0
  461. package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +93 -0
  462. package/packages/omo-codex/scripts/install-hook-targets.test.mjs +100 -0
  463. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +3 -1
  464. package/packages/omo-codex/scripts/install-local.mjs +7 -18
  465. package/packages/omo-codex/scripts/install-local.test.mjs +34 -1
  466. package/packages/shared-skills/skills/lcx-contribute-bug-fix/SKILL.md +16 -1
  467. package/packages/shared-skills/skills/lcx-doctor/SKILL.md +93 -0
  468. package/packages/shared-skills/skills/lcx-doctor/agents/openai.yaml +11 -0
  469. package/packages/shared-skills/skills/lcx-report-bug/SKILL.md +17 -13
  470. package/packages/shared-skills/skills/lsp-setup/SKILL.md +139 -0
  471. package/packages/shared-skills/skills/lsp-setup/references/bash/README.md +60 -0
  472. package/packages/shared-skills/skills/lsp-setup/references/c-cpp/README.md +61 -0
  473. package/packages/shared-skills/skills/lsp-setup/references/csharp/README.md +71 -0
  474. package/packages/shared-skills/skills/lsp-setup/references/dart/README.md +48 -0
  475. package/packages/shared-skills/skills/lsp-setup/references/elixir/README.md +51 -0
  476. package/packages/shared-skills/skills/lsp-setup/references/go/README.md +57 -0
  477. package/packages/shared-skills/skills/lsp-setup/references/haskell/README.md +57 -0
  478. package/packages/shared-skills/skills/lsp-setup/references/java/README.md +57 -0
  479. package/packages/shared-skills/skills/lsp-setup/references/julia/README.md +60 -0
  480. package/packages/shared-skills/skills/lsp-setup/references/kotlin/README.md +59 -0
  481. package/packages/shared-skills/skills/lsp-setup/references/lua/README.md +66 -0
  482. package/packages/shared-skills/skills/lsp-setup/references/php/README.md +62 -0
  483. package/packages/shared-skills/skills/lsp-setup/references/python/README.md +71 -0
  484. package/packages/shared-skills/skills/lsp-setup/references/ruby/README.md +53 -0
  485. package/packages/shared-skills/skills/lsp-setup/references/rust/README.md +59 -0
  486. package/packages/shared-skills/skills/lsp-setup/references/swift/README.md +51 -0
  487. package/packages/shared-skills/skills/lsp-setup/references/terraform/README.md +62 -0
  488. package/packages/shared-skills/skills/lsp-setup/references/typescript/README.md +77 -0
  489. package/packages/shared-skills/skills/lsp-setup/references/yaml/README.md +70 -0
  490. package/packages/shared-skills/skills/lsp-setup/references/zig/README.md +49 -0
  491. package/packages/shared-skills/skills/lsp-setup/scripts/detect-lsp.ts +210 -0
  492. package/packages/shared-skills/skills/lsp-setup/scripts/lsp-server-table.ts +177 -0
  493. package/packages/shared-skills/skills/lsp-setup/scripts/tsconfig.json +17 -0
  494. package/packages/shared-skills/skills/lsp-setup/scripts/verify-lsp.ts +147 -0
  495. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +1 -1
  496. package/packages/shared-skills/skills/review-work/SKILL.md +10 -14
  497. package/packages/shared-skills/skills/start-work/SKILL.md +30 -59
  498. package/packages/shared-skills/skills/ultraresearch/SKILL.md +126 -667
  499. package/dist/hooks/anthropic-effort/hook.d.ts +0 -26
  500. package/dist/hooks/anthropic-effort/index.d.ts +0 -1
  501. package/dist/hooks/keyword-detector/analyze/default.d.ts +0 -12
  502. package/dist/hooks/keyword-detector/analyze/index.d.ts +0 -1
  503. package/dist/hooks/keyword-detector/search/default.d.ts +0 -12
  504. package/dist/hooks/keyword-detector/search/index.d.ts +0 -1
  505. package/dist/hooks/thinking-block-validator/hook.d.ts +0 -12
  506. package/dist/hooks/thinking-block-validator/index.d.ts +0 -1
  507. package/packages/omo-codex/plugin/components/ultrawork/test/directive-contract.test.ts +0 -18
  508. package/packages/omo-codex/plugin/test/global-review-debug-gate.test.mjs +0 -29
  509. package/packages/omo-codex/plugin/test/subagent-guidance.test.mjs +0 -151
@@ -14,7 +14,7 @@ test("#given non-Windows platform #when resolving Git Bash #then no preflight is
14
14
  where: () => [],
15
15
  });
16
16
 
17
- assert.deepEqual(result, { found: true, path: null, source: "not-required" });
17
+ assert.deepEqual(result, { found: true, path: null, source: "not-required", checkedPaths: [] });
18
18
  });
19
19
 
20
20
  test("#given Windows env override to bash.exe #when the file exists #then env path wins", () => {
@@ -26,7 +26,7 @@ test("#given Windows env override to bash.exe #when the file exists #then env pa
26
26
  where: () => [programFilesGitBash],
27
27
  });
28
28
 
29
- assert.deepEqual(result, { found: true, path: overridePath, source: "env" });
29
+ assert.deepEqual(result, { found: true, path: overridePath, source: "env", checkedPaths: [overridePath] });
30
30
  });
31
31
 
32
32
  test("#given Windows standard paths are absent and PATH contains bash #when resolving #then uses where bash candidate", () => {
@@ -38,7 +38,42 @@ test("#given Windows standard paths are absent and PATH contains bash #when reso
38
38
  where: () => ["C:\\Windows\\System32\\bash.exe", pathCandidate],
39
39
  });
40
40
 
41
- assert.deepEqual(result, { found: true, path: pathCandidate, source: "path" });
41
+ assert.deepEqual(result, {
42
+ found: true,
43
+ path: pathCandidate,
44
+ source: "path",
45
+ checkedPaths: [programFilesGitBash, programFilesX86GitBash, "C:\\Windows\\System32\\bash.exe", pathCandidate],
46
+ });
47
+ });
48
+
49
+ test("#given PATH bash is only the System32 WSL launcher #when resolving #then launcher is skipped and install guidance returned", () => {
50
+ const system32Bash = "C:\\Windows\\System32\\bash.exe";
51
+ const result = resolveGitBash({
52
+ platform: "win32",
53
+ env: {},
54
+ exists: (path) => path === system32Bash,
55
+ where: () => [system32Bash],
56
+ });
57
+
58
+ assert.equal(result.found, false);
59
+ assert.deepEqual(result.checkedPaths, [programFilesGitBash, programFilesX86GitBash, system32Bash]);
60
+ assert.match(result.installHint, /winget install --id Git\.Git -e --source winget/);
61
+ });
62
+
63
+ test("#given PATH lists the WindowsApps alias before a real Git Bash #when resolving #then alias is skipped and Git Bash wins", () => {
64
+ const windowsAppsBash = "C:/Users/dev/AppData/Local/Microsoft/WindowsApps/bash.exe";
65
+ const gitBash = "D:\\Tools\\Git\\bin\\bash.exe";
66
+ const result = resolveGitBash({
67
+ platform: "win32",
68
+ env: {},
69
+ exists: (path) => path === windowsAppsBash || path === gitBash,
70
+ where: () => [windowsAppsBash, gitBash],
71
+ });
72
+
73
+ assert.equal(result.found, true);
74
+ assert.equal(result.path, gitBash);
75
+ assert.equal(result.source, "path");
76
+ assert.deepEqual(result.checkedPaths, [programFilesGitBash, programFilesX86GitBash, windowsAppsBash, gitBash]);
42
77
  });
43
78
 
44
79
  test("#given Windows invalid env override #when resolving #then returns guidance without falling through", () => {
@@ -127,7 +162,7 @@ test("#given non-Windows platform #when preparing #then winget is never called",
127
162
  });
128
163
 
129
164
  assert.deepEqual(runCalls, []);
130
- assert.deepEqual(result, { found: true, path: null, source: "not-required" });
165
+ assert.deepEqual(result, { found: true, path: null, source: "not-required", checkedPaths: [] });
131
166
  });
132
167
 
133
168
  test("#given Windows without Git Bash and winget fails #when preparing #then original install hint is preserved", async () => {
@@ -0,0 +1,46 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join, sep } from "node:path";
3
+
4
+ import { exists, isRecord } from "./utils.mjs";
5
+
6
+ const PLUGIN_ROOT_TARGET_PATTERN = /\$\{PLUGIN_ROOT\}\/([^"']+)/g;
7
+
8
+ export async function findMissingHookCommandTargets(pluginRoot) {
9
+ const manifestPath = join(pluginRoot, "hooks", "hooks.json");
10
+ if (!(await exists(manifestPath))) return [];
11
+
12
+ const commands = [];
13
+ collectCommands(JSON.parse(await readFile(manifestPath, "utf8")), commands);
14
+
15
+ const missing = [];
16
+ const seen = new Set();
17
+ for (const command of commands) {
18
+ for (const match of command.matchAll(PLUGIN_ROOT_TARGET_PATTERN)) {
19
+ const target = join(pluginRoot, ...match[1].split("/"));
20
+ if (seen.has(target)) continue;
21
+ seen.add(target);
22
+ if (!(await exists(target))) missing.push(target);
23
+ }
24
+ }
25
+ return missing;
26
+ }
27
+
28
+ export async function assertHookCommandTargets(pluginRoot) {
29
+ const missing = await findMissingHookCommandTargets(pluginRoot);
30
+ if (missing.length === 0) return;
31
+ const relativeMissing = missing.map((path) => path.split(`${pluginRoot}${sep}`).join("").split(sep).join("/"));
32
+ throw new Error(
33
+ `Plugin payload is missing ${missing.length} hook command target(s) referenced by hooks.json: ${relativeMissing.join(", ")}. ` +
34
+ "The previous plugin cache was left untouched; this payload was not activated.",
35
+ );
36
+ }
37
+
38
+ function collectCommands(value, commands) {
39
+ if (Array.isArray(value)) {
40
+ for (const entry of value) collectCommands(entry, commands);
41
+ return;
42
+ }
43
+ if (!isRecord(value)) return;
44
+ if (value.type === "command" && typeof value.command === "string") commands.push(value.command);
45
+ for (const entry of Object.values(value)) collectCommands(entry, commands);
46
+ }
@@ -20,11 +20,21 @@ export function ensureCodexMultiAgentV2Config(config) {
20
20
  if (!section) {
21
21
  return appendBlock(
22
22
  normalizedConfig,
23
- `[${CODEX_MULTI_AGENT_V2_HEADER}]\nmax_concurrent_threads_per_session = ${maxThreadsValue}\n`,
23
+ `[${CODEX_MULTI_AGENT_V2_HEADER}]\nmax_concurrent_threads_per_session = ${maxThreadsValue}\nhide_spawn_agent_metadata = false\n`,
24
24
  );
25
25
  }
26
26
 
27
- return replaceOrInsertSetting(normalizedConfig, section, "max_concurrent_threads_per_session", maxThreadsValue);
27
+ // Codex defaults hide_spawn_agent_metadata to true on V2, which strips the
28
+ // agent_type parameter from spawn_agent and makes the role TOMLs this
29
+ // installer ships unselectable.
30
+ const withMaxThreads = replaceOrInsertSetting(
31
+ normalizedConfig,
32
+ section,
33
+ "max_concurrent_threads_per_session",
34
+ maxThreadsValue,
35
+ );
36
+ const updatedSection = findTomlSection(withMaxThreads, CODEX_MULTI_AGENT_V2_HEADER);
37
+ return replaceOrInsertSetting(withMaxThreads, updatedSection, "hide_spawn_agent_metadata", "false");
28
38
  }
29
39
 
30
40
  function removeFeatureFlagSetting(config, featureName) {
@@ -7,6 +7,7 @@ export async function defaultRunCommand(command, args, options) {
7
7
  const child = spawn(invocation.command, invocation.args, {
8
8
  cwd: options.cwd,
9
9
  stdio: "inherit",
10
+ ...(options.env ? { env: options.env } : {}),
10
11
  });
11
12
  child.once("error", reject);
12
13
  child.once("exit", (code, signal) => {
@@ -1,11 +1,139 @@
1
1
  import assert from "node:assert/strict";
2
- import { lstat, mkdir, readFile, readlink, symlink, writeFile } from "node:fs/promises";
3
- import { join } from "node:path";
2
+ import { spawnSync } from "node:child_process";
3
+ import { chmod, lstat, mkdir, readFile, readlink, symlink, writeFile } from "node:fs/promises";
4
+ import { dirname, join } from "node:path";
4
5
  import test from "node:test";
5
6
 
6
- import { linkCachedPluginBins } from "./install/cache.mjs";
7
+ import { linkCachedPluginBins, linkRootRuntimeBin } from "./install/cache.mjs";
7
8
  import { makeTempDir, writeJson } from "./install-test-fixtures.mjs";
8
9
 
10
+ async function writeRuntimeWrapperFixture({ withNodeCli = false } = {}) {
11
+ const root = await makeTempDir();
12
+ const repoRoot = join(root, "repo");
13
+ const binDir = join(root, "bin");
14
+ const codexHome = join(root, "codex");
15
+ const homeDir = join(root, "home");
16
+ await mkdir(join(repoRoot, "dist", "cli"), { recursive: true });
17
+ await writeFile(join(repoRoot, "dist", "cli", "index.js"), "");
18
+ if (withNodeCli) {
19
+ await mkdir(join(repoRoot, "dist", "cli-node"), { recursive: true });
20
+ await writeFile(
21
+ join(repoRoot, "dist", "cli-node", "index.js"),
22
+ 'console.log("OMO_NODE_OK", process.argv.slice(2).join(" "));\n',
23
+ );
24
+ }
25
+ await mkdir(homeDir, { recursive: true });
26
+ const link = await linkRootRuntimeBin({ binDir, codexHome, repoRoot, platform: "linux" });
27
+ return { homeDir, link, repoRoot };
28
+ }
29
+
30
+ function runtimeWrapperEnv(homeDir) {
31
+ return { PATH: `${dirname(process.execPath)}:/usr/bin:/bin`, HOME: homeDir };
32
+ }
33
+
34
+ test("#given bun absent from PATH but present in ~/.bun/bin #when running the omo runtime wrapper #then resolves the bun fallback", async (t) => {
35
+ if (process.platform === "win32") return t.skip("posix wrapper execution");
36
+ const { homeDir, link } = await writeRuntimeWrapperFixture();
37
+ await mkdir(join(homeDir, ".bun", "bin"), { recursive: true });
38
+ await writeFile(join(homeDir, ".bun", "bin", "bun"), '#!/bin/sh\necho "fake-bun-ran $2"\n');
39
+ await chmod(join(homeDir, ".bun", "bin", "bun"), 0o755);
40
+
41
+ const result = spawnSync(link.path, ["--version"], {
42
+ encoding: "utf8",
43
+ env: { PATH: "/usr/bin:/bin", HOME: homeDir },
44
+ });
45
+
46
+ assert.equal(result.status, 0, result.stderr);
47
+ assert.match(result.stdout, /fake-bun-ran --version/);
48
+ });
49
+
50
+ test("#given bun absent everywhere #when running the omo runtime wrapper #then fails with an actionable install hint", async (t) => {
51
+ if (process.platform === "win32") return t.skip("posix wrapper execution");
52
+ const { homeDir, link } = await writeRuntimeWrapperFixture();
53
+
54
+ const result = spawnSync(link.path, ["--version"], {
55
+ encoding: "utf8",
56
+ env: { PATH: "/usr/bin:/bin", HOME: homeDir },
57
+ });
58
+
59
+ assert.equal(result.status, 127);
60
+ assert.match(result.stderr, /bun runtime not found/);
61
+ assert.match(result.stderr, /https:\/\/bun\.sh/);
62
+ });
63
+
64
+ test("#given OMO_RUNTIME=node and a node CLI bundle #when running the omo runtime wrapper #then executes the node CLI", async (t) => {
65
+ if (process.platform === "win32") return t.skip("posix wrapper execution");
66
+ const { homeDir, link } = await writeRuntimeWrapperFixture({ withNodeCli: true });
67
+
68
+ const result = spawnSync(link.path, ["--help"], {
69
+ encoding: "utf8",
70
+ env: { ...runtimeWrapperEnv(homeDir), OMO_RUNTIME: "node" },
71
+ });
72
+
73
+ assert.equal(result.status, 0, result.stderr);
74
+ assert.match(result.stdout, /OMO_NODE_OK --help/);
75
+ });
76
+
77
+ test("#given bun absent everywhere and a node CLI bundle #when running the omo runtime wrapper #then falls back to node", async (t) => {
78
+ if (process.platform === "win32") return t.skip("posix wrapper execution");
79
+ const { homeDir, link } = await writeRuntimeWrapperFixture({ withNodeCli: true });
80
+
81
+ const result = spawnSync(link.path, ["--version"], {
82
+ encoding: "utf8",
83
+ env: runtimeWrapperEnv(homeDir),
84
+ });
85
+
86
+ assert.equal(result.status, 0, result.stderr);
87
+ assert.match(result.stdout, /OMO_NODE_OK --version/);
88
+ });
89
+
90
+ test("#given bun absent and no node CLI bundle #when running the omo runtime wrapper #then the error names both runtimes", async (t) => {
91
+ if (process.platform === "win32") return t.skip("posix wrapper execution");
92
+ const { homeDir, link } = await writeRuntimeWrapperFixture();
93
+
94
+ const result = spawnSync(link.path, ["--version"], {
95
+ encoding: "utf8",
96
+ env: runtimeWrapperEnv(homeDir),
97
+ });
98
+
99
+ assert.equal(result.status, 127);
100
+ assert.match(result.stderr, /bun runtime not found/);
101
+ assert.match(result.stderr, /https:\/\/bun\.sh/);
102
+ assert.match(result.stderr, /dist\/cli-node\/index\.js/);
103
+ assert.match(result.stderr, /OMO_RUNTIME=node/);
104
+ });
105
+
106
+ test("#given Windows platform #when writing the omo runtime wrapper #then embeds the node fallback chain", async () => {
107
+ const root = await makeTempDir();
108
+ const repoRoot = join(root, "repo");
109
+ const binDir = join(root, "bin");
110
+ await mkdir(join(repoRoot, "dist", "cli"), { recursive: true });
111
+ await writeFile(join(repoRoot, "dist", "cli", "index.js"), "");
112
+
113
+ const link = await linkRootRuntimeBin({ binDir, codexHome: join(root, "codex"), repoRoot, platform: "win32" });
114
+
115
+ const wrapper = await readFile(link.path, "utf8");
116
+ assert.match(wrapper, /OMO_RUNTIME/);
117
+ assert.match(wrapper, /dist[\\/]cli-node[\\/]index\.js/);
118
+ assert.ok(wrapper.indexOf("OMO_RUNTIME") < wrapper.indexOf("where bun"), "node override must precede bun discovery");
119
+ });
120
+
121
+ test("#given Windows platform #when writing the omo runtime wrapper #then embeds the bun fallback chain", async () => {
122
+ const root = await makeTempDir();
123
+ const repoRoot = join(root, "repo");
124
+ const binDir = join(root, "bin");
125
+ await mkdir(join(repoRoot, "dist", "cli"), { recursive: true });
126
+ await writeFile(join(repoRoot, "dist", "cli", "index.js"), "");
127
+
128
+ const link = await linkRootRuntimeBin({ binDir, codexHome: join(root, "codex"), repoRoot, platform: "win32" });
129
+
130
+ const wrapper = await readFile(link.path, "utf8");
131
+ assert.match(wrapper, /where bun/);
132
+ assert.match(wrapper, /%USERPROFILE%\\\.bun\\bin\\bun\.exe/);
133
+ assert.match(wrapper, /bun runtime not found/);
134
+ assert.match(wrapper, /exit \/b 127/);
135
+ });
136
+
9
137
  test("#given Windows platform #when linking cached plugin bins #then writes command shims", async () => {
10
138
  const root = await makeTempDir();
11
139
  const pluginRoot = join(root, "plugin");
@@ -0,0 +1,91 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtemp, readFile, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+
7
+ import { updateCodexConfig } from "./install/config.mjs";
8
+
9
+ test("#given windows platform with Git Bash enabled #when updating config #then enables git_bash plugin mcp policy", async () => {
10
+ // given
11
+ const root = await mkdtemp(join(tmpdir(), "omo-codex-config-git-bash-win32-"));
12
+ const configPath = join(root, "config.toml");
13
+ await writeFile(
14
+ configPath,
15
+ [
16
+ '[plugins."omo@sisyphuslabs"]',
17
+ "enabled = true",
18
+ "",
19
+ '[plugins."omo@sisyphuslabs".mcp_servers.lsp]',
20
+ "enabled = true",
21
+ "",
22
+ '[hooks.state."omo@sisyphuslabs:hooks/hooks.json:post_tool_use:0:0"]',
23
+ 'trusted_hash = "sha256:keep"',
24
+ "",
25
+ ].join("\n"),
26
+ );
27
+
28
+ // when
29
+ await updateCodexConfig({
30
+ configPath,
31
+ repoRoot: "/repo/packages/omo-codex",
32
+ marketplaceName: "sisyphuslabs",
33
+ marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex/cache/sisyphuslabs" },
34
+ pluginNames: ["omo"],
35
+ platform: "win32",
36
+ gitBashEnabled: true,
37
+ trustedHookStates: [{ key: "omo@sisyphuslabs:hooks/hooks.json:post_tool_use:0:0", trustedHash: "sha256:keep" }],
38
+ });
39
+
40
+ // then
41
+ const content = await readFile(configPath, "utf8");
42
+ assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.lsp\]/);
43
+ assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\]/);
44
+ assert.match(content, /\[hooks\.state\."omo@sisyphuslabs:hooks\/hooks\.json:post_tool_use:0:0"\]/);
45
+ assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\][\s\S]*?enabled = true/);
46
+ });
47
+
48
+ test("#given windows platform without Git Bash enabled #when updating config #then disables git_bash plugin mcp policy", async () => {
49
+ // given
50
+ const root = await mkdtemp(join(tmpdir(), "omo-codex-config-git-bash-win32-disabled-"));
51
+ const configPath = join(root, "config.toml");
52
+
53
+ // when
54
+ await updateCodexConfig({
55
+ configPath,
56
+ repoRoot: "/repo/packages/omo-codex",
57
+ marketplaceName: "sisyphuslabs",
58
+ marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex/cache/sisyphuslabs" },
59
+ pluginNames: ["omo"],
60
+ platform: "win32",
61
+ gitBashEnabled: false,
62
+ });
63
+
64
+ // then
65
+ const content = await readFile(configPath, "utf8");
66
+ assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\]/);
67
+ assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\][\s\S]*?enabled = false/);
68
+ });
69
+
70
+ test("#given non-windows platforms #when updating config #then disables git_bash plugin mcp policy", async () => {
71
+ for (const platform of ["linux", "darwin"]) {
72
+ // given
73
+ const root = await mkdtemp(join(tmpdir(), `omo-codex-config-git-bash-${platform}-`));
74
+ const configPath = join(root, "config.toml");
75
+
76
+ // when
77
+ await updateCodexConfig({
78
+ configPath,
79
+ repoRoot: "/repo/packages/omo-codex",
80
+ marketplaceName: "sisyphuslabs",
81
+ marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex/cache/sisyphuslabs" },
82
+ pluginNames: ["omo"],
83
+ platform,
84
+ });
85
+
86
+ // then
87
+ const content = await readFile(configPath, "utf8");
88
+ assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\]/);
89
+ assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\][\s\S]*?enabled = false/);
90
+ }
91
+ });
@@ -184,6 +184,56 @@ test("#given existing MultiAgentV2 table #when script installer updates config #
184
184
  assert.doesNotMatch(config, /max_concurrent_threads_per_session = 4/);
185
185
  });
186
186
 
187
+ test("#given empty Codex config #when script installer updates config #then exposes spawn_agent agent_type for installed roles", async () => {
188
+ // given
189
+ const root = await mkdtemp(join(tmpdir(), "omo-codex-script-config-multi-agent-roles-"));
190
+ const configPath = join(root, "config.toml");
191
+
192
+ // when
193
+ await updateCodexConfig({
194
+ configPath,
195
+ repoRoot: "/repo/packages/omo-codex",
196
+ marketplaceName: "debug",
197
+ marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex" },
198
+ pluginNames: ["omo"],
199
+ });
200
+
201
+ // then
202
+ const config = await readFile(configPath, "utf8");
203
+ const v2Section = config.slice(config.indexOf("[features.multi_agent_v2]"));
204
+ assert.match(v2Section, /hide_spawn_agent_metadata = false/);
205
+ });
206
+
207
+ test("#given user config hiding spawn_agent metadata #when script installer updates config #then re-exposes agent_type so role TOMLs stay selectable", async () => {
208
+ // given
209
+ const root = await mkdtemp(join(tmpdir(), "omo-codex-script-config-multi-agent-hide-"));
210
+ const configPath = join(root, "config.toml");
211
+ await writeFile(
212
+ configPath,
213
+ [
214
+ "[features.multi_agent_v2]",
215
+ "usage_hint_enabled = false",
216
+ "hide_spawn_agent_metadata = true",
217
+ "",
218
+ ].join("\n"),
219
+ );
220
+
221
+ // when
222
+ await updateCodexConfig({
223
+ configPath,
224
+ repoRoot: "/repo/packages/omo-codex",
225
+ marketplaceName: "debug",
226
+ marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex" },
227
+ pluginNames: ["omo"],
228
+ });
229
+
230
+ // then
231
+ const config = await readFile(configPath, "utf8");
232
+ assert.match(config, /hide_spawn_agent_metadata = false/);
233
+ assert.doesNotMatch(config, /hide_spawn_agent_metadata = true/);
234
+ assert.match(config, /usage_hint_enabled = false/);
235
+ });
236
+
187
237
  test("#given legacy boolean MultiAgentV2 flag and table #when script installer updates config #then normalizes to table config", async () => {
188
238
  // given
189
239
  const root = await mkdtemp(join(tmpdir(), "omo-codex-script-config-multi-agent-legacy-"));
@@ -325,47 +375,3 @@ test("#given existing trust and lsp blocks #when updating config #then existing
325
375
  assert.match(content, /\[hooks\.state\."omo@sisyphuslabs:hooks\/hooks\.json:post_tool_use:0:0"\]/);
326
376
  assert.match(content, /trusted_hash = "sha256:keep"/);
327
377
  });
328
-
329
- test("#given windows platform #when updating config #then enables git_bash plugin mcp policy", async () => {
330
- // given
331
- const root = await mkdtemp(join(tmpdir(), "omo-codex-config-git-bash-win32-"));
332
- const configPath = join(root, "config.toml");
333
-
334
- // when
335
- await updateCodexConfig({
336
- configPath,
337
- repoRoot: "/repo/packages/omo-codex",
338
- marketplaceName: "sisyphuslabs",
339
- marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex/cache/sisyphuslabs" },
340
- pluginNames: ["omo"],
341
- platform: "win32",
342
- });
343
-
344
- // then
345
- const content = await readFile(configPath, "utf8");
346
- assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\]/);
347
- assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\][\s\S]*?enabled = true/);
348
- });
349
-
350
- test("#given non-windows platforms #when updating config #then disables git_bash plugin mcp policy", async () => {
351
- for (const platform of ["linux", "darwin"]) {
352
- // given
353
- const root = await mkdtemp(join(tmpdir(), `omo-codex-config-git-bash-${platform}-`));
354
- const configPath = join(root, "config.toml");
355
-
356
- // when
357
- await updateCodexConfig({
358
- configPath,
359
- repoRoot: "/repo/packages/omo-codex",
360
- marketplaceName: "sisyphuslabs",
361
- marketplaceSource: { sourceType: "local", source: "/repo/packages/omo-codex/cache/sisyphuslabs" },
362
- pluginNames: ["omo"],
363
- platform,
364
- });
365
-
366
- // then
367
- const content = await readFile(configPath, "utf8");
368
- assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\]/);
369
- assert.match(content, /\[plugins\."omo@sisyphuslabs"\.mcp_servers\.git_bash\][\s\S]*?enabled = false/);
370
- }
371
- });
@@ -0,0 +1,78 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { buildDelegatedOmoInvocation, runDelegatedOmoCommand } from "./install/delegated-command.mjs";
5
+
6
+ test("#given a lazycodex passthrough command #when delegating to omo #then resets OMO_INVOCATION_NAME so the delegate does not re-enter the lazycodex path", async () => {
7
+ // given
8
+ const parsed = { kind: "command", command: "doctor", args: [] };
9
+ let received;
10
+ const options = {
11
+ cwd: "/tmp/project",
12
+ log: () => {},
13
+ runCommand: async (command, args, runOptions) => {
14
+ received = { command, args, runOptions };
15
+ },
16
+ };
17
+
18
+ // when
19
+ await runDelegatedOmoCommand(parsed, { ...options });
20
+
21
+ // then
22
+ const invocation = buildDelegatedOmoInvocation(parsed);
23
+ assert.equal(received.command, invocation.command);
24
+ assert.deepEqual(received.args, invocation.args);
25
+ assert.equal(received.runOptions.cwd, "/tmp/project");
26
+ assert.equal(
27
+ received.runOptions.env?.OMO_INVOCATION_NAME,
28
+ "omo",
29
+ "delegated omo command must run with OMO_INVOCATION_NAME=omo to avoid infinite recursion",
30
+ );
31
+ });
32
+
33
+ test("#given OMO_INVOCATION_NAME=lazycodex in the parent env #when delegating a cleanup passthrough #then the child env overrides it to omo", async () => {
34
+ // given
35
+ const previous = process.env.OMO_INVOCATION_NAME;
36
+ process.env.OMO_INVOCATION_NAME = "lazycodex";
37
+ let received;
38
+ const parsed = { kind: "command", command: "cleanup", args: [] };
39
+
40
+ try {
41
+ // when
42
+ await runDelegatedOmoCommand(parsed, {
43
+ cwd: "/tmp/project",
44
+ log: () => {},
45
+ runCommand: async (_command, _args, runOptions) => {
46
+ received = runOptions;
47
+ },
48
+ });
49
+ } finally {
50
+ if (previous === undefined) delete process.env.OMO_INVOCATION_NAME;
51
+ else process.env.OMO_INVOCATION_NAME = previous;
52
+ }
53
+
54
+ // then
55
+ assert.equal(received.env.OMO_INVOCATION_NAME, "omo");
56
+ });
57
+
58
+ test("#given a dry-run passthrough #when delegating #then logs the invocation without invoking runCommand", async () => {
59
+ // given
60
+ const parsed = { kind: "command", command: "doctor", dryRun: true, args: [] };
61
+ let logged;
62
+ let ran = false;
63
+
64
+ // when
65
+ await runDelegatedOmoCommand(parsed, {
66
+ cwd: "/tmp/project",
67
+ log: (line) => {
68
+ logged = line;
69
+ },
70
+ runCommand: async () => {
71
+ ran = true;
72
+ },
73
+ });
74
+
75
+ // then
76
+ assert.equal(ran, false);
77
+ assert.match(logged, /npx --yes --package oh-my-openagent omo doctor/);
78
+ });
@@ -0,0 +1,93 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+
7
+ import { stampGitBashMcpEnv } from "./install/git-bash-mcp-env.mjs";
8
+
9
+ const MANIFEST = `${JSON.stringify(
10
+ {
11
+ mcpServers: {
12
+ ast_grep: { command: "node", args: ["../../ast-grep-mcp/dist/cli.js", "mcp"] },
13
+ git_bash: { command: "node", args: ["../../git-bash-mcp/dist/cli.js", "mcp"] },
14
+ },
15
+ },
16
+ null,
17
+ "\t",
18
+ )}\n`;
19
+
20
+ async function createPluginRoot() {
21
+ const pluginRoot = await mkdtemp(join(tmpdir(), "git-bash-mcp-env-"));
22
+ await writeFile(join(pluginRoot, ".mcp.json"), MANIFEST);
23
+ return pluginRoot;
24
+ }
25
+
26
+ test("#given win32 install with OMO_CODEX_GIT_BASH_PATH set #when stamping #then git_bash server env forwards the override", async (t) => {
27
+ const pluginRoot = await createPluginRoot();
28
+ t.after(() => rm(pluginRoot, { recursive: true, force: true }));
29
+
30
+ const changed = await stampGitBashMcpEnv({
31
+ pluginRoot,
32
+ env: { OMO_CODEX_GIT_BASH_PATH: "D:\\Git\\bin\\bash.exe" },
33
+ platform: "win32",
34
+ });
35
+
36
+ assert.equal(changed, true);
37
+ const parsed = JSON.parse(await readFile(join(pluginRoot, ".mcp.json"), "utf8"));
38
+ assert.deepEqual(parsed.mcpServers.git_bash.env, { OMO_CODEX_GIT_BASH_PATH: "D:\\Git\\bin\\bash.exe" });
39
+ assert.equal(parsed.mcpServers.ast_grep.env, undefined);
40
+ });
41
+
42
+ test("#given the override is unset #when stamping #then the manifest stays byte-identical", async (t) => {
43
+ const pluginRoot = await createPluginRoot();
44
+ t.after(() => rm(pluginRoot, { recursive: true, force: true }));
45
+
46
+ const changed = await stampGitBashMcpEnv({ pluginRoot, env: {}, platform: "win32" });
47
+
48
+ assert.equal(changed, false);
49
+ assert.equal(await readFile(join(pluginRoot, ".mcp.json"), "utf8"), MANIFEST);
50
+ });
51
+
52
+ test("#given a non-Windows install #when stamping #then the manifest stays byte-identical", async (t) => {
53
+ const pluginRoot = await createPluginRoot();
54
+ t.after(() => rm(pluginRoot, { recursive: true, force: true }));
55
+
56
+ const changed = await stampGitBashMcpEnv({
57
+ pluginRoot,
58
+ env: { OMO_CODEX_GIT_BASH_PATH: "D:\\Git\\bin\\bash.exe" },
59
+ platform: "darwin",
60
+ });
61
+
62
+ assert.equal(changed, false);
63
+ assert.equal(await readFile(join(pluginRoot, ".mcp.json"), "utf8"), MANIFEST);
64
+ });
65
+
66
+ test("#given the override already stamped #when stamping again #then nothing changes", async (t) => {
67
+ const pluginRoot = await createPluginRoot();
68
+ t.after(() => rm(pluginRoot, { recursive: true, force: true }));
69
+ const input = { pluginRoot, env: { OMO_CODEX_GIT_BASH_PATH: "D:\\Git\\bin\\bash.exe" }, platform: "win32" };
70
+
71
+ await stampGitBashMcpEnv(input);
72
+ const afterFirst = await readFile(join(pluginRoot, ".mcp.json"), "utf8");
73
+ const changedAgain = await stampGitBashMcpEnv(input);
74
+
75
+ assert.equal(changedAgain, false);
76
+ assert.equal(await readFile(join(pluginRoot, ".mcp.json"), "utf8"), afterFirst);
77
+ });
78
+
79
+ test("#given a manifest without a git_bash server #when stamping #then the manifest stays byte-identical", async (t) => {
80
+ const pluginRoot = await mkdtemp(join(tmpdir(), "git-bash-mcp-env-"));
81
+ t.after(() => rm(pluginRoot, { recursive: true, force: true }));
82
+ const manifest = `${JSON.stringify({ mcpServers: { ast_grep: { command: "node" } } }, null, "\t")}\n`;
83
+ await writeFile(join(pluginRoot, ".mcp.json"), manifest);
84
+
85
+ const changed = await stampGitBashMcpEnv({
86
+ pluginRoot,
87
+ env: { OMO_CODEX_GIT_BASH_PATH: "D:\\Git\\bin\\bash.exe" },
88
+ platform: "win32",
89
+ });
90
+
91
+ assert.equal(changed, false);
92
+ assert.equal(await readFile(join(pluginRoot, ".mcp.json"), "utf8"), manifest);
93
+ });