oh-my-opencode 4.19.4 → 5.0.0-beta.2

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 (268) hide show
  1. package/README.ja.md +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +6 -5
  4. package/README.ru.md +1 -1
  5. package/README.zh-cn.md +1 -1
  6. package/bin/oh-my-opencode.js +14 -1
  7. package/bin/oh-my-opencode.test.ts +21 -0
  8. package/dist/cli/index.js +1452 -703
  9. package/dist/cli-node/index.js +1452 -703
  10. package/dist/config/schema/agent-overrides.d.ts +528 -0
  11. package/dist/config/schema/oh-my-opencode-config.d.ts +495 -0
  12. package/dist/features/monitor/batcher.d.ts +3 -1
  13. package/dist/features/monitor/manager-internals.d.ts +1 -0
  14. package/dist/features/monitor/output-injector-types.d.ts +2 -0
  15. package/dist/features/monitor/output-injector.d.ts +6 -0
  16. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  17. package/dist/hooks/todo-continuation-enforcer/unrecoverable-request-error.d.ts +9 -0
  18. package/dist/hooks/tool-pair-validator/hook.test-support.d.ts +29 -0
  19. package/dist/hooks/tool-pair-validator/tool-part-ids.d.ts +14 -5
  20. package/dist/hooks/tool-pair-validator/tool-result-repair.d.ts +4 -3
  21. package/dist/hooks/tool-pair-validator/types.d.ts +5 -22
  22. package/dist/index.js +2776 -2240
  23. package/dist/mcp/lsp.d.ts +1 -0
  24. package/dist/oh-my-opencode.schema.json +1466 -131
  25. package/dist/shared/tmux/constants.d.ts +1 -1
  26. package/dist/skills/ast-grep/SOURCE +1 -1
  27. package/dist/skills/ast-grep/install.ps1 +2 -2
  28. package/dist/skills/ast-grep/install.sh +1 -1
  29. package/dist/skills/ast-grep/references/install.md +2 -2
  30. package/dist/skills/ast-grep/tests/smoke.sh +1 -1
  31. package/dist/skills/start-work/SKILL.md +54 -9
  32. package/dist/skills/ultimate-browsing/SKILL.md +2 -2
  33. package/dist/skills/ultimate-browsing/engine/__main__.py +8 -1
  34. package/dist/skills/ultimate-browsing/engine/bias_check.py +11 -0
  35. package/dist/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
  36. package/dist/skills/ultimate-browsing/engine/result_schema.py +10 -1
  37. package/dist/skills/ultimate-browsing/engine/surrogate.py +214 -0
  38. package/dist/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
  39. package/dist/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
  40. package/dist/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
  41. package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
  42. package/dist/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
  43. package/dist/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
  44. package/dist/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
  45. package/dist/skills/ultimate-browsing/engine/validators.py +46 -0
  46. package/dist/skills/ultimate-browsing/engine/waf_detector.py +1 -1
  47. package/dist/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
  48. package/dist/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  49. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  50. package/dist/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  51. package/dist/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
  52. package/dist/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
  53. package/dist/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
  54. package/dist/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
  55. package/dist/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
  56. package/dist/skills/ulw-plan/SKILL.md +1 -1
  57. package/dist/skills/ulw-plan/references/full-workflow.md +3 -3
  58. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  59. package/dist/skills/ulw-research/SKILL.md +15 -10
  60. package/dist/tui.js +307 -28
  61. package/docs/reference/web-terminal-visual-qa.md +1 -1
  62. package/package.json +27 -19
  63. package/packages/lsp-core/src/lsp/connection.ts +1 -1
  64. package/packages/lsp-daemon/dist/cli.js +27 -13
  65. package/packages/lsp-daemon/dist/client.js +49 -35
  66. package/packages/lsp-daemon/dist/ensure-daemon.d.ts +1 -0
  67. package/packages/lsp-daemon/dist/ensure-daemon.js +18 -5
  68. package/packages/lsp-daemon/dist/index.js +34 -20
  69. package/packages/lsp-tools-mcp/dist/cli.js +1 -1
  70. package/packages/lsp-tools-mcp/dist/lsp/manager.js +1 -1
  71. package/packages/lsp-tools-mcp/dist/mcp.js +1 -1
  72. package/packages/lsp-tools-mcp/dist/tools.js +1 -1
  73. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  74. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +268 -92
  75. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  76. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  77. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +7 -7
  78. package/packages/omo-codex/plugin/components/bootstrap/src/worker.ts +3 -0
  79. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +106 -6
  80. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +106 -6
  81. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  82. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  83. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  84. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  85. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  86. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  87. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  88. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  89. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +56 -42
  90. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  91. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  92. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  93. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  94. package/packages/omo-codex/plugin/components/start-work-continuation/AGENTS.md +1 -0
  95. package/packages/omo-codex/plugin/components/start-work-continuation/README.md +5 -1
  96. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +2 -1
  97. package/packages/omo-codex/plugin/components/start-work-continuation/dist/cli.js +18 -0
  98. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  99. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  100. package/packages/omo-codex/plugin/components/start-work-continuation/src/codex-hook.ts +21 -0
  101. package/packages/omo-codex/plugin/components/start-work-continuation/test/codex-hook.test.ts +105 -0
  102. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  103. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  104. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  105. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  106. package/packages/omo-codex/plugin/components/ultrawork/CHANGELOG.md +2 -0
  107. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
  108. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  109. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
  110. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  111. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-low.toml +1 -1
  112. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
  113. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +2 -2
  114. package/packages/omo-codex/plugin/components/ultrawork/directive.md +3 -2
  115. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  116. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  117. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +3 -2
  118. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +1 -1
  119. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +3 -3
  120. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  121. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +1 -1
  122. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +2 -0
  123. package/packages/omo-codex/plugin/components/ulw-loop/README.md +11 -11
  124. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +3 -2
  125. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +1 -1
  126. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  127. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +9 -9
  128. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +1 -1
  129. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +66 -66
  130. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +4 -4
  131. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +1 -1
  132. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +1 -1
  133. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +1 -1
  134. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +1 -1
  135. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +2 -2
  136. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  137. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  138. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -3
  139. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +22 -25
  140. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +1 -1
  141. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +9 -9
  142. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +1 -1
  143. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +1 -1
  144. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +4 -4
  145. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +1 -1
  146. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +1 -1
  147. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +1 -1
  148. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +1 -1
  149. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +2 -2
  150. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -2
  151. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +1 -1
  152. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-helpers.test.ts +2 -2
  153. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-kind-guidance.test.ts +1 -1
  154. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +2 -2
  155. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +1 -1
  156. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -5
  157. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +1 -1
  158. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +1 -1
  159. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +1 -1
  160. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  161. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  162. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  163. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  164. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  165. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  166. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  167. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  168. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  169. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  170. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  171. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  172. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  173. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  174. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  175. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  176. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  177. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  178. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  179. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  180. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  181. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  182. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  183. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  184. package/packages/omo-codex/plugin/package-lock.json +13 -13
  185. package/packages/omo-codex/plugin/package.json +1 -1
  186. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +4 -4
  187. package/packages/omo-codex/plugin/skills/ast-grep/SOURCE +1 -1
  188. package/packages/omo-codex/plugin/skills/ast-grep/install.ps1 +2 -2
  189. package/packages/omo-codex/plugin/skills/ast-grep/install.sh +1 -1
  190. package/packages/omo-codex/plugin/skills/ast-grep/references/install.md +2 -2
  191. package/packages/omo-codex/plugin/skills/ast-grep/tests/smoke.sh +1 -1
  192. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +54 -9
  193. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -2
  194. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +8 -1
  195. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/bias_check.py +11 -0
  196. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
  197. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/result_schema.py +10 -1
  198. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogate.py +214 -0
  199. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
  200. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
  201. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
  202. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
  203. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
  204. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
  205. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
  206. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/validators.py +46 -0
  207. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_detector.py +1 -1
  208. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
  209. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  210. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  211. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  212. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
  213. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
  214. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
  215. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
  216. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
  217. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +3 -2
  218. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -3
  219. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +22 -25
  220. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +1 -1
  221. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +3 -3
  222. package/packages/omo-codex/plugin/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  223. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +15 -10
  224. package/packages/omo-codex/plugin/test/bootstrap-binlinks.test.mjs +12 -12
  225. package/packages/omo-codex/plugin/test/bootstrap-orchestration.test.mjs +36 -4
  226. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +1 -1
  227. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +4 -4
  228. package/packages/omo-codex/scripts/install-bin-links.test.mjs +56 -2
  229. package/packages/omo-codex/scripts/install-delegated-command.test.mjs +6 -6
  230. package/packages/omo-codex/scripts/install-dist/install-local.mjs +115 -61
  231. package/packages/omo-codex/scripts/install-local-entrypoint.test.mjs +4 -4
  232. package/packages/omo-codex/scripts/install-local.test.mjs +5 -2
  233. package/packages/shared-skills/index.mjs +19 -1
  234. package/packages/shared-skills/skills/ast-grep/SOURCE +1 -1
  235. package/packages/shared-skills/skills/ast-grep/install.ps1 +2 -2
  236. package/packages/shared-skills/skills/ast-grep/install.sh +1 -1
  237. package/packages/shared-skills/skills/ast-grep/references/install.md +2 -2
  238. package/packages/shared-skills/skills/ast-grep/tests/smoke.sh +1 -1
  239. package/packages/shared-skills/skills/start-work/SKILL.md +54 -9
  240. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -2
  241. package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +8 -1
  242. package/packages/shared-skills/skills/ultimate-browsing/engine/bias_check.py +11 -0
  243. package/packages/shared-skills/skills/ultimate-browsing/engine/fetch_chain.py +90 -52
  244. package/packages/shared-skills/skills/ultimate-browsing/engine/result_schema.py +10 -1
  245. package/packages/shared-skills/skills/ultimate-browsing/engine/surrogate.py +214 -0
  246. package/packages/shared-skills/skills/ultimate-browsing/engine/surrogates.yaml +60 -0
  247. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +7 -0
  248. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +19 -0
  249. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +1 -0
  250. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +1128 -0
  251. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate.py +252 -0
  252. package/packages/shared-skills/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +78 -0
  253. package/packages/shared-skills/skills/ultimate-browsing/engine/validators.py +46 -0
  254. package/packages/shared-skills/skills/ultimate-browsing/engine/waf_detector.py +1 -1
  255. package/packages/shared-skills/skills/ultimate-browsing/engine/waf_profiles.yaml +10 -5
  256. package/packages/shared-skills/skills/ultimate-browsing/references/agent-reach/social.md +1 -1
  257. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  258. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  259. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/cache-archive.md +51 -50
  260. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/fallback.md +1 -1
  261. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/jina.md +8 -2
  262. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/naver.md +1 -1
  263. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/twitter.md +3 -3
  264. package/packages/shared-skills/skills/ulw-plan/SKILL.md +1 -1
  265. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +3 -3
  266. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  267. package/packages/shared-skills/skills/ulw-research/SKILL.md +15 -10
  268. package/postinstall.mjs +6 -0
@@ -18,10 +18,10 @@ import { AsyncLocalStorage } from "node:async_hooks";
18
18
  import { existsSync, realpathSync, statSync } from "node:fs";
19
19
  import { basename, delimiter, dirname, isAbsolute, join, relative, resolve } from "node:path";
20
20
  import { spawn } from "node:child_process";
21
- import { closeSync as closeSync2, mkdirSync as mkdirSync2, openSync as openSync2 } from "node:fs";
21
+ import { closeSync as closeSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
22
22
  import { Socket } from "node:net";
23
- import { dirname as dirname3 } from "node:path";
24
- import { execPath } from "node:process";
23
+ import { dirname as dirname3, isAbsolute as isAbsolute3 } from "node:path";
24
+ import { argv0, execPath } from "node:process";
25
25
  import {
26
26
  chmodSync,
27
27
  closeSync,
@@ -42,38 +42,38 @@ import * as path from "node:path";
42
42
  import { fileURLToPath } from "node:url";
43
43
  import { statSync as statSync2 } from "node:fs";
44
44
  import { isAbsolute as isAbsolute2 } from "node:path";
45
- import { existsSync as existsSync9, statSync as statSync4 } from "node:fs";
45
+ import { existsSync as existsSync10, statSync as statSync4 } from "node:fs";
46
46
  import { dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
47
47
  import { basename as basename2, extname } from "node:path";
48
48
  import { resolve as resolve6 } from "node:path";
49
49
  import { pathToFileURL as pathToFileURL3 } from "node:url";
50
50
  import { pathToFileURL } from "node:url";
51
51
  import { spawn as spawn2, spawnSync } from "node:child_process";
52
- import { existsSync as existsSync2, statSync as statSync3 } from "node:fs";
52
+ import { existsSync as existsSync3, statSync as statSync3 } from "node:fs";
53
53
  import { delimiter as delimiter2, join as join2 } from "node:path";
54
54
  import { readFileSync as readFileSync2, realpathSync as realpathSync2 } from "node:fs";
55
55
  import { relative as relative2, resolve as resolve2 } from "node:path";
56
56
  import { pathToFileURL as pathToFileURL2 } from "node:url";
57
- import { existsSync as existsSync4, lstatSync as lstatSync3, renameSync, rmSync, writeFileSync } from "node:fs";
58
- import { existsSync as existsSync3, lstatSync as lstatSync2, readFileSync as readFileSync3, readdirSync, realpathSync as realpathSync3 } from "node:fs";
59
- import { dirname as dirname4, isAbsolute as isAbsolute3, relative as relative3, resolve as resolve3 } from "node:path";
57
+ import { existsSync as existsSync5, lstatSync as lstatSync3, renameSync, rmSync, writeFileSync } from "node:fs";
58
+ import { existsSync as existsSync4, lstatSync as lstatSync2, readFileSync as readFileSync3, readdirSync, realpathSync as realpathSync3 } from "node:fs";
59
+ import { dirname as dirname4, isAbsolute as isAbsolute4, relative as relative3, resolve as resolve3 } from "node:path";
60
60
  import { fileURLToPath as fileURLToPath2 } from "node:url";
61
61
  import { createHash as createHash2 } from "node:crypto";
62
62
  import { dirname as dirname5, relative as relative4, resolve as resolve4 } from "node:path";
63
- import { existsSync as existsSync5, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
63
+ import { existsSync as existsSync6, lstatSync as lstatSync4, readdirSync as readdirSync2 } from "node:fs";
64
64
  import { dirname as dirname6, resolve as resolve5 } from "node:path";
65
- import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
65
+ import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
66
66
  import { dirname as dirname7 } from "node:path";
67
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
68
- import { existsSync as existsSync8 } from "node:fs";
67
+ import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
68
+ import { existsSync as existsSync9 } from "node:fs";
69
69
  import { delimiter as delimiter3, join as join3 } from "node:path";
70
- import { existsSync as existsSync10, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
70
+ import { existsSync as existsSync11, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
71
71
  import { join as join5, resolve as resolve8 } from "node:path";
72
72
  import { fileURLToPath as fileURLToPath3 } from "node:url";
73
73
  import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
74
74
  import { join as join6 } from "node:path";
75
75
  import { statSync as statSync5 } from "node:fs";
76
- import { isAbsolute as isAbsolute4 } from "node:path";
76
+ import { isAbsolute as isAbsolute5 } from "node:path";
77
77
 
78
78
  class LspRequestContextParseError extends Error {
79
79
  code;
@@ -563,15 +563,29 @@ function spawnDaemonProcess(paths) {
563
563
  mkdirSync2(dirname3(paths.log), { recursive: true });
564
564
  const logFd = openSync2(paths.log, "a");
565
565
  try {
566
- const child = spawn(execPath, [paths.cliPath, "daemon"], {
566
+ const child = spawn(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
567
567
  detached: true,
568
568
  stdio: ["ignore", logFd, logFd]
569
569
  });
570
+ child.once("spawn", () => closeSync2(logFd));
571
+ child.once("error", (error) => {
572
+ writeSync2(logFd, `[lsp-daemon] failed to spawn daemon: ${error.message}
573
+ `);
574
+ closeSync2(logFd);
575
+ });
570
576
  child.unref();
571
- } finally {
577
+ } catch (error) {
572
578
  closeSync2(logFd);
579
+ throw error;
573
580
  }
574
581
  }
582
+ function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync2) {
583
+ if (pathExists(cachedExecPath))
584
+ return cachedExecPath;
585
+ if (isAbsolute3(originalArgv0) && pathExists(originalArgv0))
586
+ return originalArgv0;
587
+ return "node";
588
+ }
575
589
  function defaultEnsureDaemonDeps() {
576
590
  return {
577
591
  probe: (paths, signal) => probeDaemon(paths, PROBE_TIMEOUT_MS, signal),
@@ -1085,7 +1099,7 @@ function reportKillError(context, error) {
1085
1099
  }
1086
1100
  function validateCwd(cwd) {
1087
1101
  try {
1088
- if (!existsSync2(cwd)) {
1102
+ if (!existsSync3(cwd)) {
1089
1103
  return { valid: false, error: `Working directory does not exist: ${cwd}` };
1090
1104
  }
1091
1105
  const stats = statSync3(cwd);
@@ -1173,7 +1187,7 @@ function resolveWindowsCommand(command, env) {
1173
1187
  for (const baseDirectory of baseDirectories) {
1174
1188
  for (const extension of extensions) {
1175
1189
  const candidate = baseDirectory ? join2(baseDirectory, `${command}${extension}`) : `${command}${extension}`;
1176
- if (existsSync2(candidate))
1190
+ if (existsSync3(candidate))
1177
1191
  return candidate;
1178
1192
  }
1179
1193
  }
@@ -1567,7 +1581,7 @@ class LspClientConnection extends LspClientTransport {
1567
1581
  initializationOptions: this.server.initialization
1568
1582
  }, { timeoutMs: this.initializeTimeoutMs });
1569
1583
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
1570
- await this.sendNotification("initialized");
1584
+ await this.sendNotification("initialized", {});
1571
1585
  await this.sendNotification("workspace/didChangeConfiguration", {
1572
1586
  settings: { json: { validate: { enable: true } } }
1573
1587
  });
@@ -2037,11 +2051,11 @@ class WorkspaceEditPathError extends Error {
2037
2051
  }
2038
2052
  function isPathInsideWorkspace(filePath, workspaceRoot) {
2039
2053
  const relativePath = relative3(workspaceRoot, filePath);
2040
- return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute3(relativePath);
2054
+ return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute4(relativePath);
2041
2055
  }
2042
2056
  function canonicalizeMissingPath(filePath) {
2043
2057
  let ancestor = filePath;
2044
- while (!existsSync3(ancestor)) {
2058
+ while (!existsSync4(ancestor)) {
2045
2059
  const parent = dirname4(ancestor);
2046
2060
  if (parent === ancestor)
2047
2061
  throw new WorkspaceEditPathError(filePath, "no existing ancestor");
@@ -2059,7 +2073,7 @@ function canonicalWorkspaceRoot(workspaceRoot) {
2059
2073
  success: true,
2060
2074
  path: canonical,
2061
2075
  requestedPath: resolve3(workspaceRoot),
2062
- followedSymbolicLink: existsSync3(resolve3(workspaceRoot)) && lstatSync2(resolve3(workspaceRoot)).isSymbolicLink()
2076
+ followedSymbolicLink: existsSync4(resolve3(workspaceRoot)) && lstatSync2(resolve3(workspaceRoot)).isSymbolicLink()
2063
2077
  };
2064
2078
  } catch (error) {
2065
2079
  const detail = error instanceof Error ? error.message : String(error);
@@ -2079,7 +2093,7 @@ function uriToCanonicalWorkspacePath(uri, workspaceRoot) {
2079
2093
  return { success: false, error: `non-file URI ${uri}: ${detail}` };
2080
2094
  }
2081
2095
  try {
2082
- const canonical = existsSync3(requestedPath) ? realpathSync3(requestedPath) : canonicalizeMissingPath(requestedPath);
2096
+ const canonical = existsSync4(requestedPath) ? realpathSync3(requestedPath) : canonicalizeMissingPath(requestedPath);
2083
2097
  if (!isPathInsideWorkspace(canonical, workspaceRoot)) {
2084
2098
  return { success: false, error: `${requestedPath}: outside workspace ${workspaceRoot}` };
2085
2099
  }
@@ -2087,7 +2101,7 @@ function uriToCanonicalWorkspacePath(uri, workspaceRoot) {
2087
2101
  success: true,
2088
2102
  path: canonical,
2089
2103
  requestedPath,
2090
- followedSymbolicLink: existsSync3(requestedPath) && lstatSync2(requestedPath).isSymbolicLink()
2104
+ followedSymbolicLink: existsSync4(requestedPath) && lstatSync2(requestedPath).isSymbolicLink()
2091
2105
  };
2092
2106
  } catch (error) {
2093
2107
  const detail = error instanceof Error ? error.message : String(error);
@@ -2095,7 +2109,7 @@ function uriToCanonicalWorkspacePath(uri, workspaceRoot) {
2095
2109
  }
2096
2110
  }
2097
2111
  function snapshotPath(path2, includeChildren) {
2098
- if (!existsSync3(path2))
2112
+ if (!existsSync4(path2))
2099
2113
  return { kind: "missing" };
2100
2114
  const stats = lstatSync2(path2);
2101
2115
  if (stats.isFile())
@@ -2213,7 +2227,7 @@ function commitOperation(context, operation) {
2213
2227
  }
2214
2228
  if (operation.kind === "rename") {
2215
2229
  if (operation.replaceDestination) {
2216
- const targetKind = existsSync4(operation.newPath) && lstatSync3(operation.newPath).isDirectory() ? "directory" : "file";
2230
+ const targetKind = existsSync5(operation.newPath) && lstatSync3(operation.newPath).isDirectory() ? "directory" : "file";
2217
2231
  io.remove(operation.newPath, targetKind === "directory");
2218
2232
  accumulator.mutations.push({ kind: "delete", path: operation.newPath, targetKind });
2219
2233
  addModifiedPath(accumulator.filesModified, reportedPath(plan, operation.newPath));
@@ -2841,7 +2855,7 @@ class WorkspaceSnapshotBuilder {
2841
2855
  break;
2842
2856
  candidate = dirname6(candidate);
2843
2857
  }
2844
- if (!includeChildren || !existsSync5(path2) || !lstatSync4(path2).isDirectory())
2858
+ if (!includeChildren || !existsSync6(path2) || !lstatSync4(path2).isDirectory())
2845
2859
  return;
2846
2860
  for (const child of readdirSync2(path2))
2847
2861
  this.add(resolve5(path2, child), true);
@@ -3597,7 +3611,7 @@ function getInstallDecisionsPath() {
3597
3611
  }
3598
3612
  function loadInstallDecisions() {
3599
3613
  const path2 = getInstallDecisionsPath();
3600
- if (!existsSync6(path2))
3614
+ if (!existsSync7(path2))
3601
3615
  return {};
3602
3616
  try {
3603
3617
  const parsed = JSON.parse(readFileSync4(path2, "utf8"));
@@ -3788,7 +3802,7 @@ function getUserConfigPath() {
3788
3802
  return lspRequestContext().userConfigPath;
3789
3803
  }
3790
3804
  function loadJsonFile(path2) {
3791
- if (!existsSync7(path2))
3805
+ if (!existsSync8(path2))
3792
3806
  return null;
3793
3807
  try {
3794
3808
  const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
@@ -3981,7 +3995,7 @@ function isServerInstalled(command, _workingDirectory) {
3981
3995
  if (!cmd)
3982
3996
  return false;
3983
3997
  if (cmd.includes("/") || cmd.includes("\\")) {
3984
- if (existsSync8(cmd))
3998
+ if (existsSync9(cmd))
3985
3999
  return true;
3986
4000
  }
3987
4001
  const isWindows = process.platform === "win32";
@@ -4002,7 +4016,7 @@ function isServerInstalled(command, _workingDirectory) {
4002
4016
  const paths = pathEnv.split(delimiter3);
4003
4017
  for (const p of paths) {
4004
4018
  for (const suffix of exts) {
4005
- if (existsSync8(join3(p, cmd + suffix))) {
4019
+ if (existsSync9(join3(p, cmd + suffix))) {
4006
4020
  return true;
4007
4021
  }
4008
4022
  }
@@ -4111,7 +4125,7 @@ function findWorkspaceRoot(filePath) {
4111
4125
  let prevDir = "";
4112
4126
  while (dir !== prevDir) {
4113
4127
  for (const marker of WORKSPACE_MARKERS) {
4114
- if (existsSync9(join4(dir, marker))) {
4128
+ if (existsSync10(join4(dir, marker))) {
4115
4129
  return dir;
4116
4130
  }
4117
4131
  }
@@ -4391,7 +4405,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4391
4405
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4392
4406
  }
4393
4407
  const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4394
- if (!existsSync10(absDir)) {
4408
+ if (!existsSync11(absDir)) {
4395
4409
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4396
4410
  }
4397
4411
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -5260,12 +5274,12 @@ function resolveDaemonRuntime2(env, defaults) {
5260
5274
  throw new InvalidRuntimeOverrideError2("paired_values_required", `${OMO_LSP_DAEMON_CLI2} and ${OMO_LSP_DAEMON_VERSION2} must be set together`);
5261
5275
  }
5262
5276
  if (!hasCliOverride || !hasVersionOverride) {
5263
- if (!isAbsolute4(defaults.cliPath)) {
5277
+ if (!isAbsolute5(defaults.cliPath)) {
5264
5278
  throw new InvalidRuntimeOverrideError2("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
5265
5279
  }
5266
5280
  return { cliPath: defaults.cliPath, version: validateDaemonVersion2(defaults.version) };
5267
5281
  }
5268
- if (!isAbsolute4(cliOverride)) {
5282
+ if (!isAbsolute5(cliOverride)) {
5269
5283
  throw new InvalidRuntimeOverrideError2("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI2} must be an absolute path to an existing regular file`);
5270
5284
  }
5271
5285
  const stat = statSync5(cliOverride, { throwIfNoEntry: false });
@@ -5386,8 +5400,8 @@ function extensionKey(filePath) {
5386
5400
  }
5387
5401
  // ../../../../lsp-core/src/request-context.ts
5388
5402
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
5389
- import { existsSync as existsSync11, realpathSync as realpathSync4, statSync as statSync6 } from "node:fs";
5390
- import { basename as basename3, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute5, join as join7, relative as relative5, resolve as resolve9 } from "node:path";
5403
+ import { existsSync as existsSync12, realpathSync as realpathSync4, statSync as statSync6 } from "node:fs";
5404
+ import { basename as basename3, delimiter as delimiter4, dirname as dirname2, isAbsolute as isAbsolute6, join as join7, relative as relative5, resolve as resolve9 } from "node:path";
5391
5405
 
5392
5406
  class LspRequestContextParseError2 extends Error {
5393
5407
  code;
@@ -5430,7 +5444,7 @@ function parseLspRequestContext2(value) {
5430
5444
  }
5431
5445
  function canonicalCwd2(cwd) {
5432
5446
  const resolved = resolve9(cwd);
5433
- if (!existsSync11(resolved) || !statSync6(resolved).isDirectory()) {
5447
+ if (!existsSync12(resolved) || !statSync6(resolved).isDirectory()) {
5434
5448
  throw new LspRequestContextParseError2("invalid_cwd", `LSP request cwd must be an existing directory: ${cwd}`);
5435
5449
  }
5436
5450
  return realpathSync4(resolved);
@@ -5479,14 +5493,14 @@ function stringArrayField2(value, field) {
5479
5493
  return fieldValue;
5480
5494
  }
5481
5495
  function requireAbsolutePath2(path2, field) {
5482
- if (!isAbsolute5(path2)) {
5496
+ if (!isAbsolute6(path2)) {
5483
5497
  throw new LspRequestContextParseError2("relative_path", `LSP request context.${field} must be absolute: ${path2}`);
5484
5498
  }
5485
5499
  }
5486
5500
  function isPathInside2(parent, child) {
5487
5501
  const childPath = resolve9(child);
5488
5502
  const relativePath = relative5(parent, childPath);
5489
- return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute5(relativePath);
5503
+ return relativePath === "" || !relativePath.startsWith("..") && !isAbsolute6(relativePath);
5490
5504
  }
5491
5505
  function isMissingPathError2(error) {
5492
5506
  const code = errorCode2(error);
@@ -5509,7 +5523,7 @@ function errorCode2(error) {
5509
5523
  }
5510
5524
 
5511
5525
  // src/daemon-cli-path.ts
5512
- import { existsSync as existsSync13, readFileSync as readFileSync6 } from "node:fs";
5526
+ import { existsSync as existsSync14, readFileSync as readFileSync6 } from "node:fs";
5513
5527
  import { createRequire as createRequire2 } from "node:module";
5514
5528
  import { dirname as dirname9, join as join9 } from "node:path";
5515
5529
  import { fileURLToPath as fileURLToPath4 } from "node:url";
@@ -5533,7 +5547,7 @@ function resolveLspDaemonCli() {
5533
5547
  if (packageCli !== null)
5534
5548
  return resolveConfiguredLspDaemonCli(packageCli);
5535
5549
  const bundledCli = fileURLToPath4(new URL("../../lsp-daemon/dist/cli.js", import.meta.url));
5536
- if (existsSync13(bundledCli))
5550
+ if (existsSync14(bundledCli))
5537
5551
  return resolveConfiguredLspDaemonCli(bundledCli);
5538
5552
  return resolveConfiguredLspDaemonCli(bundledCli);
5539
5553
  }
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
10
10
  "timeout": 60,
11
- "statusMessage": "(OmO 4.19.4) Checking LSP Diagnostics"
11
+ "statusMessage": "(OmO 5.0.0-beta.2) Checking LSP Diagnostics"
12
12
  }
13
13
  ]
14
14
  }
@@ -21,7 +21,7 @@
21
21
  "type": "command",
22
22
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
23
23
  "timeout": 5,
24
- "statusMessage": "(OmO 4.19.4) Resetting LSP Diagnostics Cache"
24
+ "statusMessage": "(OmO 5.0.0-beta.2) Resetting LSP Diagnostics Cache"
25
25
  }
26
26
  ]
27
27
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-lsp",
3
- "version": "4.19.4",
3
+ "version": "5.0.0-beta.2",
4
4
  "description": "Codex plugin that exposes Language Server Protocol tools and post-edit diagnostics.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook session-start",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 4.19.4) Loading Project Rules"
10
+ "statusMessage": "(OmO 5.0.0-beta.2) Loading Project Rules"
11
11
  }
12
12
  ]
13
13
  }
@@ -19,7 +19,7 @@
19
19
  "type": "command",
20
20
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
21
21
  "timeout": 10,
22
- "statusMessage": "(OmO 4.19.4) Loading Project Rules"
22
+ "statusMessage": "(OmO 5.0.0-beta.2) Loading Project Rules"
23
23
  }
24
24
  ]
25
25
  }
@@ -32,7 +32,7 @@
32
32
  "type": "command",
33
33
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
34
34
  "timeout": 10,
35
- "statusMessage": "(OmO 4.19.4) Matching Project Rules"
35
+ "statusMessage": "(OmO 5.0.0-beta.2) Matching Project Rules"
36
36
  }
37
37
  ]
38
38
  }
@@ -45,7 +45,7 @@
45
45
  "type": "command",
46
46
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
47
47
  "timeout": 10,
48
- "statusMessage": "(OmO 4.19.4) Resetting Project Rule Cache"
48
+ "statusMessage": "(OmO 5.0.0-beta.2) Resetting Project Rule Cache"
49
49
  }
50
50
  ]
51
51
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-rules",
3
- "version": "4.19.4",
3
+ "version": "5.0.0-beta.2",
4
4
  "description": "Codex plugin that injects project rule files into model context through lifecycle hooks.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -48,4 +48,5 @@ Conventions for human contributors and AI agents working on this repository.
48
48
  - Never make a network call from the hook.
49
49
  - Keep the directive in `directive.md`. Do not inline it into TypeScript files.
50
50
  - The hook only continues sessions listed in `.omo/boulder.json` as `codex:<session_id>`.
51
+ - The hook yields no output when `last_assistant_message` starts with `<start-work-blocked-external>`, or when that marker is the second line immediately after the mandatory `ULTRAWORK MODE ENABLED!` opener, so a conclusive external blocker can end the turn. Reject the marker everywhere else.
51
52
  - The hook continues while the plan has a readable top-level checklist (`total > 0`). A fully-checked plan still blocks Stop until the final gate runs and the Boulder work is marked completed; an unreadable or empty checklist yields no output.
@@ -8,7 +8,11 @@ It reads `.omo/boulder.json` in the hook payload `cwd`, resolves the active work
8
8
  {"decision":"block","reason":"<directive>"}
9
9
  ```
10
10
 
11
- The `reason` is loaded from `directive.md` on every invocation and filled with current plan state. The hook returns no output when `stop_hook_active` is `true`, when no active Boulder work exists, when the work is completed, when the active work is not tied to `codex:<session_id>`, or when the plan has no readable top-level checklist. An active plan whose checklist is fully checked still blocks Stop until the final gate runs and Boulder is marked completed.
11
+ The `reason` is loaded from `directive.md` on every invocation and filled with current plan state. The hook returns no output when `stop_hook_active` is `true`, when `last_assistant_message` starts with `<start-work-blocked-external>` (or places it immediately after the mandatory `ULTRAWORK MODE ENABLED!` opener), when no active Boulder work exists, when the work is completed, when the active work is not tied to `codex:<session_id>`, or when the plan has no readable top-level checklist. An active plan whose checklist is fully checked still blocks Stop until the final gate runs and Boulder is marked completed.
12
+
13
+ ## External blocker escape hatch
14
+
15
+ A plan can stall on something no amount of retrying fixes: a missing credential, missing hardware, a revoked authorization, an unavailable third-party service. `directive.md` instructs the agent to write `<start-work-blocked-external>` as the entire first line of its answer in that case, or as the entire second line when ultrawork's mandatory opener occupies the first. The hook recognizes those structural forms and lets the turn end so the user can act, instead of continuing the same unchanged external-state check forever. Merely discussing the marker later in an answer still continues the plan.
12
16
 
13
17
  This pairs with the `start-work` skill at `plugin/skills/start-work/SKILL.md`. That skill writes `.omo/boulder.json` with Codex session ids prefixed as `codex:` so the hook can continue only its own active Codex session.
14
18
 
@@ -45,7 +45,8 @@ Before completion, satisfy all five `review-work` lanes and a `debugging` runtim
45
45
  # Stop conditions for THIS turn
46
46
 
47
47
  - A top-level checkbox flipped to `- [x]` after the 5-phase QA gate (Phase 1 read, Phase 2 automated, Phase 3 channel scenario, Phase 4 adversarial-class probing, Phase 5 gate decision). Then the Stop hook will re-evaluate; if more checkboxes remain you will be continued again.
48
- - 3 same-failure cycles on one sub-task escalate via `multi_agent_v1.spawn_agent({"message":"TASK: act as a rigorous reviewer. DELIVERABLE: diagnose the repeated sub-task failure and recommend the next safe action. VERIFY: cite the failing evidence.","fork_context":false})` and stop dispatch.
48
+ - A conclusive external blocker only the user or external state can clear (missing hardware, credential, authorization, or an unavailable service) → after ONE authoritative check, stop retrying and stop reviewer dispatch. Write `<start-work-blocked-external>` as the entire first line of your answer, then state the exact blocker and the observable condition that resumes the work. If ultrawork requires `ULTRAWORK MODE ENABLED!` as the first line, put the blocker marker alone on the second line instead. The Stop hook recognizes both forms and lets this turn end.
49
+ - 3 same-failure cycles on one agent-controllable sub-task → escalate via `multi_agent_v1.spawn_agent({"message":"TASK: act as a rigorous reviewer. DELIVERABLE: diagnose the repeated sub-task failure and recommend the next safe action. VERIFY: cite the failing evidence.","fork_context":false})` and stop dispatch.
49
50
  - Safety boundary (destructive command, secret exfiltration, production write) → stop and surface a safe substitute.
50
51
  - All top-level checkboxes `- [x]` AND the Global Review and Debugging Gate passed → print the ORCHESTRATION COMPLETE block and end.
51
52
 
@@ -307,6 +307,8 @@ function runStopHook(input, fs) {
307
307
  return "";
308
308
  if (input.stop_hook_active)
309
309
  return "";
310
+ if (hasAllowedExternalBlockerMarker(input.last_assistant_message))
311
+ return "";
310
312
  if (transcriptHasContextPressureMarker(input.transcript_path, fs))
311
313
  return "";
312
314
  const state = readContinuationState(input.cwd, input.session_id);
@@ -337,6 +339,22 @@ function renderDirective(state, sessionId) {
337
339
  }
338
340
  return rendered;
339
341
  }
342
+ var EXTERNAL_BLOCKER_MARKER = "<start-work-blocked-external>";
343
+ var ULTRAWORK_OPENER = "ULTRAWORK MODE ENABLED!";
344
+ function hasAllowedExternalBlockerMarker(lastAssistantMessage) {
345
+ if (lastAssistantMessage === undefined)
346
+ return false;
347
+ const lines = lastAssistantMessage.split(String.fromCharCode(10));
348
+ const [firstLine = "", secondLine = ""] = lines;
349
+ let markerLineIndex = -1;
350
+ if (firstLine.trim() === EXTERNAL_BLOCKER_MARKER)
351
+ markerLineIndex = 0;
352
+ else if (firstLine.trim() === ULTRAWORK_OPENER && secondLine.trim() === EXTERNAL_BLOCKER_MARKER)
353
+ markerLineIndex = 1;
354
+ if (markerLineIndex === -1)
355
+ return false;
356
+ return lines.slice(markerLineIndex + 1).some((line) => line.trim() !== "");
357
+ }
340
358
  var CONTEXT_PRESSURE_MARKERS = [
341
359
  "context compacted",
342
360
  "context_length_exceeded",
@@ -7,7 +7,7 @@
7
7
  "type": "command",
8
8
  "command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook stop",
9
9
  "timeout": 10,
10
- "statusMessage": "(OmO 4.19.4) Checking Start-Work Continuation"
10
+ "statusMessage": "(OmO 5.0.0-beta.2) Checking Start-Work Continuation"
11
11
  }
12
12
  ]
13
13
  }
@@ -19,7 +19,7 @@
19
19
  "type": "command",
20
20
  "command": "node \"${PLUGIN_ROOT}/components/start-work-continuation/dist/cli.js\" hook subagent-stop",
21
21
  "timeout": 10,
22
- "statusMessage": "(OmO 4.19.4) Checking Start-Work Continuation"
22
+ "statusMessage": "(OmO 5.0.0-beta.2) Checking Start-Work Continuation"
23
23
  }
24
24
  ]
25
25
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-start-work-continuation",
3
- "version": "4.19.4",
3
+ "version": "5.0.0-beta.2",
4
4
  "description": "Codex Stop hook continuation injector for omo-codex start-work plans.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -6,6 +6,7 @@ import type { ReadonlyFileSystem, StopHookEventName, StopHookOutput, StopInput }
6
6
  export function runStopHook(input: unknown, fs: ReadonlyFileSystem): string {
7
7
  if (!isStopInput(input)) return "";
8
8
  if (input.stop_hook_active) return "";
9
+ if (hasAllowedExternalBlockerMarker(input.last_assistant_message)) return "";
9
10
  if (transcriptHasContextPressureMarker(input.transcript_path, fs)) return "";
10
11
  const state = readContinuationState(input.cwd, input.session_id);
11
12
  if (state === null) return "";
@@ -39,6 +40,26 @@ function renderDirective(state: ContinuationState, sessionId: string): string {
39
40
  return rendered;
40
41
  }
41
42
 
43
+ const EXTERNAL_BLOCKER_MARKER = "<start-work-blocked-external>";
44
+ const ULTRAWORK_OPENER = "ULTRAWORK MODE ENABLED!";
45
+
46
+ // The marker alone is not enough to end the turn. `directive.md` requires the exact blocker and
47
+ // the condition that resumes the work on the following lines, so at least one is required here
48
+ // too. That keeps a bare echo of the marker, whether quoted back from a prompt or produced by
49
+ // untrusted text the agent read, from skipping the continuation guard.
50
+ function hasAllowedExternalBlockerMarker(lastAssistantMessage: string | undefined): boolean {
51
+ if (lastAssistantMessage === undefined) return false;
52
+ const lines = lastAssistantMessage.split(String.fromCharCode(10));
53
+ const [firstLine = "", secondLine = ""] = lines;
54
+
55
+ let markerLineIndex = -1;
56
+ if (firstLine.trim() === EXTERNAL_BLOCKER_MARKER) markerLineIndex = 0;
57
+ else if (firstLine.trim() === ULTRAWORK_OPENER && secondLine.trim() === EXTERNAL_BLOCKER_MARKER) markerLineIndex = 1;
58
+ if (markerLineIndex === -1) return false;
59
+
60
+ return lines.slice(markerLineIndex + 1).some((line) => line.trim() !== "");
61
+ }
62
+
42
63
  const CONTEXT_PRESSURE_MARKERS = [
43
64
  "context compacted",
44
65
  "context_length_exceeded",
@@ -70,6 +70,111 @@ describe("start-work Stop hook", () => {
70
70
  expect(parsed.reason).toContain("- Your session id in boulder.json: `codex:sess_abc`");
71
71
  });
72
72
 
73
+ it("#given active codex work and an external-blocker marker #when hook runs #then returns empty output", () => {
74
+ // given
75
+ const workspace = createWorkspace({
76
+ boulderJson: createBoulderJson({ sessionIds: ["codex:sess_abc"], status: "active" }),
77
+ planMarkdown: SCAFFOLD_PLAN_MARKDOWN,
78
+ });
79
+ const fs = createMemoryFs();
80
+ const input = {
81
+ ...createStopInput(workspace),
82
+ last_assistant_message: [
83
+ "<start-work-blocked-external>",
84
+ "Blocker: the staging deploy credential is missing.",
85
+ "Resume when a valid credential is provisioned.",
86
+ ].join("\n"),
87
+ };
88
+
89
+ // when
90
+ const output = runStopHook(input, fs);
91
+
92
+ // then
93
+ expect(output).toBe("");
94
+ });
95
+
96
+ it("#given ultrawork opener then external-blocker marker #when hook runs #then returns empty output", () => {
97
+ // given
98
+ const workspace = createWorkspace({
99
+ boulderJson: createBoulderJson({ sessionIds: ["codex:sess_abc"], status: "active" }),
100
+ planMarkdown: SCAFFOLD_PLAN_MARKDOWN,
101
+ });
102
+ const fs = createMemoryFs();
103
+ const input = {
104
+ ...createStopInput(workspace),
105
+ last_assistant_message: [
106
+ "ULTRAWORK MODE ENABLED!",
107
+ "<start-work-blocked-external>",
108
+ "Blocker: the staging deploy credential is missing.",
109
+ ].join("\n"),
110
+ };
111
+
112
+ // when
113
+ const output = runStopHook(input, fs);
114
+
115
+ // then
116
+ expect(output).toBe("");
117
+ });
118
+
119
+ it("#given the external-blocker marker with no stated blocker #when hook runs #then still returns block JSON", () => {
120
+ // given: a bare marker, which is what a quoted echo or untrusted text would produce.
121
+ // directive.md requires the blocker and the resume condition, so the marker alone must not
122
+ // skip the continuation guard.
123
+ const workspace = createWorkspace({
124
+ boulderJson: createBoulderJson({ sessionIds: ["codex:sess_abc"], status: "active" }),
125
+ planMarkdown: SCAFFOLD_PLAN_MARKDOWN,
126
+ });
127
+ const fs = createMemoryFs();
128
+ const input = {
129
+ ...createStopInput(workspace),
130
+ last_assistant_message: "<start-work-blocked-external>",
131
+ };
132
+
133
+ // when
134
+ const output = runStopHook(input, fs);
135
+
136
+ // then
137
+ expect(output).not.toBe("");
138
+ });
139
+
140
+ it("#given the ultrawork opener and a bare marker #when hook runs #then still returns block JSON", () => {
141
+ // given
142
+ const workspace = createWorkspace({
143
+ boulderJson: createBoulderJson({ sessionIds: ["codex:sess_abc"], status: "active" }),
144
+ planMarkdown: SCAFFOLD_PLAN_MARKDOWN,
145
+ });
146
+ const fs = createMemoryFs();
147
+ const input = {
148
+ ...createStopInput(workspace),
149
+ last_assistant_message: ["ULTRAWORK MODE ENABLED!", "<start-work-blocked-external>", " "].join("\n"),
150
+ };
151
+
152
+ // when
153
+ const output = runStopHook(input, fs);
154
+
155
+ // then
156
+ expect(output).not.toBe("");
157
+ });
158
+
159
+ it("#given the external-blocker marker below the first line #when hook runs #then still returns block JSON", () => {
160
+ // given
161
+ const workspace = createWorkspace({
162
+ boulderJson: createBoulderJson({ sessionIds: ["codex:sess_abc"], status: "active" }),
163
+ planMarkdown: SCAFFOLD_PLAN_MARKDOWN,
164
+ });
165
+ const fs = createMemoryFs();
166
+ const input = {
167
+ ...createStopInput(workspace),
168
+ last_assistant_message: ["Next turn I may need to emit", "<start-work-blocked-external>"].join("\n"),
169
+ };
170
+
171
+ // when
172
+ const output = runStopHook(input, fs);
173
+
174
+ // then
175
+ expect(parseBlockOutput(output).decision).toBe("block");
176
+ });
177
+
73
178
  it("#given active codex work with zero remaining tasks #when hook runs #then blocks for the final gate", () => {
74
179
  // given
75
180
  const workspace = createWorkspace({
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
10
10
  "timeout": 10,
11
- "statusMessage": "(OmO 4.19.4) Checking Thread Title Hygiene"
11
+ "statusMessage": "(OmO 5.0.0-beta.2) Checking Thread Title Hygiene"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-teammode",
3
- "version": "4.19.4",
3
+ "version": "5.0.0-beta.2",
4
4
  "description": "Codex team-mode hook component that keeps background thread titles descriptive after create_thread.",
5
5
  "type": "module",
6
6
  "private": true,