oh-my-opencode 5.0.0-beta.30 → 5.0.0-beta.32

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 (278) hide show
  1. package/dist/cli/index.js +178 -37
  2. package/dist/cli-node/index.js +178 -37
  3. package/dist/config/schema/background-task.d.ts +1 -0
  4. package/dist/config/schema/oh-my-opencode-config.d.ts +1 -0
  5. package/dist/features/background-agent/constants.d.ts +0 -7
  6. package/dist/features/background-agent/manager.d.ts +2 -1
  7. package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
  8. package/dist/features/background-agent/parent-wake-notifier-types.d.ts +1 -1
  9. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -1
  10. package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -1
  11. package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
  12. package/dist/features/monitor/manager-internals.d.ts +1 -1
  13. package/dist/features/monitor/output-injector-types.d.ts +1 -1
  14. package/dist/features/task-toast-manager/manager.d.ts +0 -24
  15. package/dist/features/team-mode/tools/messaging-live-delivery-recipient.d.ts +1 -0
  16. package/dist/features/team-mode/tools/messaging-runtime.d.ts +1 -0
  17. package/dist/hooks/anthropic-context-window-limit-recovery/message-storage-directory.d.ts +0 -3
  18. package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +1 -0
  19. package/dist/hooks/anthropic-context-window-limit-recovery/storage/empty-messages.d.ts +0 -1
  20. package/dist/hooks/anthropic-context-window-limit-recovery/tool-result-storage.d.ts +11 -0
  21. package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
  22. package/dist/hooks/claude-code-hooks/stop.d.ts +2 -0
  23. package/dist/hooks/claude-code-hooks/todo.d.ts +0 -1
  24. package/dist/hooks/claude-code-hooks/transcript.d.ts +2 -0
  25. package/dist/hooks/fsync-skip-warning/index.d.ts +4 -0
  26. package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +1 -0
  27. package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +13 -0
  28. package/dist/hooks/keyword-detector/hook.d.ts +7 -0
  29. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
  30. package/dist/hooks/model-fallback/hook.d.ts +1 -1
  31. package/dist/index.js +681 -273
  32. package/dist/oh-my-opencode.schema.json +5 -0
  33. package/dist/plugin-dispose.d.ts +3 -0
  34. package/dist/shared/agent-tool-restrictions.d.ts +0 -1
  35. package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  36. package/dist/tools/delegate-task/sync-session-cleanup.d.ts +3 -0
  37. package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -0
  38. package/dist/tools/delegate-task/types.d.ts +1 -0
  39. package/dist/tools/session-manager/directory-filter.d.ts +2 -0
  40. package/dist/tui.js +148 -9
  41. package/package.json +16 -15
  42. package/packages/git-bash-mcp/dist/cli.js +1 -0
  43. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +47 -19
  44. package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
  45. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +97 -0
  46. package/packages/lsp-core/src/lsp/client-wrapper.ts +21 -6
  47. package/packages/lsp-core/src/lsp/client.ts +6 -3
  48. package/packages/lsp-core/src/lsp/constants.ts +5 -0
  49. package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +61 -0
  50. package/packages/lsp-core/src/lsp/errors.ts +15 -0
  51. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +10 -3
  52. package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
  53. package/packages/lsp-core/src/lsp/manager.ts +106 -13
  54. package/packages/lsp-core/src/lsp/timer-provider.ts +13 -0
  55. package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
  56. package/packages/lsp-core/src/lsp/transport.ts +7 -2
  57. package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +84 -1
  58. package/packages/lsp-core/src/lsp/workspace-document-state.ts +30 -11
  59. package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -1
  60. package/packages/lsp-core/src/mcp.ts +3 -0
  61. package/packages/lsp-core/src/tools/parameters.test.ts +51 -0
  62. package/packages/lsp-daemon/dist/cli.js +155 -34
  63. package/packages/lsp-daemon/dist/client.js +155 -34
  64. package/packages/lsp-daemon/dist/index.js +155 -34
  65. package/packages/lsp-daemon/dist/proxy.js +3 -0
  66. package/packages/lsp-tools-mcp/dist/cli.js +155 -34
  67. package/packages/lsp-tools-mcp/dist/lsp/manager.js +134 -28
  68. package/packages/lsp-tools-mcp/dist/mcp.js +155 -34
  69. package/packages/lsp-tools-mcp/dist/tools.js +154 -34
  70. package/packages/lsp-tools-mcp/package.json +1 -1
  71. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  72. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  73. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  74. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +17 -2
  75. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +17 -2
  76. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  77. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +12 -0
  78. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +47 -0
  79. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  80. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  81. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  82. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  83. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  84. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  85. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  86. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +152 -34
  87. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  88. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  89. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  90. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  91. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  92. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  93. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  94. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  95. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -4
  96. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +489 -4
  97. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  98. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -2
  99. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
  100. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
  101. package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
  102. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
  103. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
  104. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  105. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  106. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +5 -2
  107. package/packages/omo-codex/plugin/components/ulw-loop/README.md +1 -0
  108. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +9 -0
  109. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +14 -0
  110. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +10 -1
  111. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +8 -0
  112. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +113 -0
  113. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +9 -5
  114. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  115. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  116. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +1 -0
  117. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +2 -0
  118. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +856 -347
  119. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
  120. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +27 -6
  121. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +13 -0
  122. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +14 -0
  123. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
  124. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +17 -2
  125. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +13 -0
  126. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +19 -0
  127. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +2 -0
  128. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +53 -0
  129. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +9 -0
  130. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +85 -0
  131. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +1 -1
  132. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
  133. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +41 -102
  134. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +4 -2
  135. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +185 -14
  136. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
  137. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
  138. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +18 -0
  139. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +65 -0
  140. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  141. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  142. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +17 -0
  143. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +7 -0
  144. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +25 -1
  145. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +127 -0
  146. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +10 -12
  147. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +2 -1
  148. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +1 -0
  149. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +2 -0
  150. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +34 -5
  151. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +23 -0
  152. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
  153. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +18 -3
  154. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +27 -0
  155. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +57 -0
  156. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +103 -0
  157. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +1 -1
  158. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +54 -123
  159. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +4 -2
  160. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +187 -12
  161. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
  162. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +95 -0
  163. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +107 -1
  164. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +92 -0
  165. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +183 -0
  166. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +35 -0
  167. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
  168. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +105 -0
  169. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate.test.ts +101 -0
  170. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +46 -2
  171. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
  172. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +5 -0
  173. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +318 -1
  174. package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
  175. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +9 -3
  176. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  177. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  178. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  179. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  180. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  181. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  182. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  183. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  184. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  185. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  186. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  187. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  188. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  189. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  190. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  191. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  192. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  193. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  194. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  195. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  196. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  197. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  198. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  199. package/packages/omo-codex/plugin/package-lock.json +13 -13
  200. package/packages/omo-codex/plugin/package.json +1 -1
  201. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +31 -2
  202. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  203. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +17 -0
  204. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +11 -1
  205. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +13 -0
  206. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -2
  207. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
  208. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  209. package/dist/features/builtin-skills/index.d.ts +0 -1
  210. package/dist/features/builtin-skills/skill-file-loader.d.ts +0 -1
  211. package/dist/features/builtin-skills/skills/agent-browser-skill.d.ts +0 -1
  212. package/dist/features/builtin-skills/skills/agent-browser-template.d.ts +0 -1
  213. package/dist/features/builtin-skills/skills/debugging.d.ts +0 -1
  214. package/dist/features/builtin-skills/skills/dev-browser.d.ts +0 -1
  215. package/dist/features/builtin-skills/skills/frontend.d.ts +0 -1
  216. package/dist/features/builtin-skills/skills/git-master-sections/commit-atomic-planning.d.ts +0 -1
  217. package/dist/features/builtin-skills/skills/git-master-sections/commit-context-analysis.d.ts +0 -1
  218. package/dist/features/builtin-skills/skills/git-master-sections/commit-execution-verification.d.ts +0 -1
  219. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +0 -1
  220. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +0 -1
  221. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +0 -1
  222. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +0 -1
  223. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +0 -1
  224. package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +0 -1
  225. package/dist/features/builtin-skills/skills/git-master.d.ts +0 -1
  226. package/dist/features/builtin-skills/skills/index.d.ts +0 -1
  227. package/dist/features/builtin-skills/skills/init-deep.d.ts +0 -1
  228. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +0 -1
  229. package/dist/features/builtin-skills/skills/playwright-mcp-skill.d.ts +0 -1
  230. package/dist/features/builtin-skills/skills/playwright.d.ts +0 -1
  231. package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +0 -1
  232. package/dist/features/builtin-skills/skills/review-work.d.ts +0 -1
  233. package/dist/features/builtin-skills/skills/security-research.d.ts +0 -1
  234. package/dist/features/builtin-skills/skills/security-review.d.ts +0 -1
  235. package/dist/features/builtin-skills/skills/team-mode.d.ts +0 -1
  236. package/dist/features/builtin-skills/skills/visual-qa.d.ts +0 -1
  237. package/dist/features/builtin-skills/skills.d.ts +0 -1
  238. package/dist/features/builtin-skills/types.d.ts +0 -1
  239. package/dist/features/claude-code-plugin-loader/agent-loader.d.ts +0 -1
  240. package/dist/features/claude-code-plugin-loader/command-loader.d.ts +0 -1
  241. package/dist/features/claude-code-plugin-loader/discovery-core.d.ts +0 -1
  242. package/dist/features/claude-code-plugin-loader/discovery-paths.d.ts +0 -1
  243. package/dist/features/claude-code-plugin-loader/discovery.d.ts +0 -1
  244. package/dist/features/claude-code-plugin-loader/hook-loader.d.ts +0 -1
  245. package/dist/features/claude-code-plugin-loader/index.d.ts +0 -1
  246. package/dist/features/claude-code-plugin-loader/install-path-resolver.d.ts +0 -1
  247. package/dist/features/claude-code-plugin-loader/installed-plugin-database.d.ts +0 -1
  248. package/dist/features/claude-code-plugin-loader/loaded-plugin.d.ts +0 -1
  249. package/dist/features/claude-code-plugin-loader/loader.d.ts +0 -1
  250. package/dist/features/claude-code-plugin-loader/mcp-server-loader.d.ts +0 -1
  251. package/dist/features/claude-code-plugin-loader/plugin-key.d.ts +0 -1
  252. package/dist/features/claude-code-plugin-loader/plugin-manifest.d.ts +0 -1
  253. package/dist/features/claude-code-plugin-loader/plugin-path-resolver.d.ts +0 -1
  254. package/dist/features/claude-code-plugin-loader/plugin-settings.d.ts +0 -1
  255. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +0 -1
  256. package/dist/features/claude-code-plugin-loader/skill-loader.d.ts +0 -1
  257. package/dist/features/claude-code-plugin-loader/types.d.ts +0 -1
  258. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
  259. package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
  260. package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +0 -1
  261. package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +0 -1
  262. package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +0 -1
  263. package/dist/shared/prompt-async-gate/queue.d.ts +0 -1
  264. package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +0 -1
  265. package/dist/shared/prompt-async-gate/reservations.d.ts +0 -1
  266. package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +0 -1
  267. package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +0 -1
  268. package/dist/shared/prompt-async-gate/timing.d.ts +0 -1
  269. package/dist/shared/prompt-async-gate/types.d.ts +0 -1
  270. package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
  271. package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
  272. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  273. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  274. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  275. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  276. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  277. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -483
  278. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +0 -490
@@ -7,6 +7,7 @@ import {
7
7
  runJsonRpcStdioServer,
8
8
  successResponse,
9
9
  type JsonRpcResponse,
10
+ type McpLifecycleLog,
10
11
  type ParentWatchdogConfig,
11
12
  } from "../../../../../mcp-stdio-core/src/index.ts";
12
13
 
@@ -18,6 +19,9 @@ export interface UnavailableCodegraphMcpOptions {
18
19
  // Test seam: production callers leave this unset so the watchdog uses its
19
20
  // defaults (parentPid = process.ppid, 30s poll).
20
21
  readonly parentWatchdog?: ParentWatchdogConfig;
22
+ // Test seam: surfaces the mcp-stdio-core lifecycle log so tests can pin the
23
+ // resolved idle timeout without waiting a real timeout out.
24
+ readonly lifecycleLog?: McpLifecycleLog;
21
25
  }
22
26
 
23
27
  interface UnavailableCodegraphMcpHandlerOptions {
@@ -36,7 +40,15 @@ export async function runUnavailableCodegraphMcpServer(
36
40
  },
37
41
  input: options.input,
38
42
  output: options.output,
43
+ // Idle stays disabled: the codex host never respawns an exited stdio
44
+ // MCP server (codex-rs auto-reconnects only its own codex_apps server),
45
+ // and since #6548 the default idle timer actually destroys stdin — so an
46
+ // inherited 10-minute default would silently kill this stub mid-session
47
+ // and turn later codegraph tool calls into dead-connection errors.
48
+ idleTimeoutMs: 0,
39
49
  parentWatchdog: options.parentWatchdog ?? {},
50
+ // Conditional spread keeps this assignable under exactOptionalPropertyTypes.
51
+ ...(options.lifecycleLog === undefined ? {} : { log: options.lifecycleLog }),
40
52
  });
41
53
  }
42
54
 
@@ -0,0 +1,47 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { PassThrough } from "node:stream";
3
+
4
+ import { runUnavailableCodegraphMcpServer } from "../src/mcp-unavailable.ts";
5
+
6
+ describe("unavailable codegraph MCP idle teardown", () => {
7
+ it("#given the codex host (no respawn for exited stdio servers) #when the unavailable stub starts #then the idle timeout is disabled", async () => {
8
+ // given — codex never respawns a user-configured stdio MCP server
9
+ // (codex-rs reconnects only its own codex_apps server), so if the stub
10
+ // inherited the mcp-stdio-core default idle timeout it would destroy its
11
+ // own stdin after 10 idle minutes and every later codegraph tool call in
12
+ // a long-lived session would fail on a dead connection instead of
13
+ // answering with the skip reason.
14
+ const stdin = new PassThrough();
15
+ const stdout = new PassThrough();
16
+ stdout.resume();
17
+ const lifecycle: Array<{ readonly event: string; readonly data?: unknown }> = [];
18
+
19
+ try {
20
+ // when
21
+ const served = runUnavailableCodegraphMcpServer({
22
+ input: stdin,
23
+ output: stdout,
24
+ reason: "CodeGraph MCP skipped: test reason",
25
+ serverVersion: "0.0.0-test",
26
+ lifecycleLog: (event, data) => {
27
+ lifecycle.push({ event, data });
28
+ },
29
+ });
30
+ const outcome = await Promise.race([
31
+ served.then(() => "settled" as const),
32
+ Bun.sleep(500).then(() => "parked" as const),
33
+ ]);
34
+
35
+ // then — the server must park on the held-open pipe (no idle timer
36
+ // tore it down) and must have started with the timeout disabled.
37
+ expect(outcome).toBe("parked");
38
+ expect(lifecycle).toContainEqual({
39
+ event: "stdio_started",
40
+ data: expect.objectContaining({ idle_timeout_ms: 0 }),
41
+ });
42
+ } finally {
43
+ stdin.destroy();
44
+ stdout.destroy();
45
+ }
46
+ });
47
+ });
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
10
10
  "timeout": 30,
11
- "statusMessage": "(OmO 5.0.0-beta.30) Checking Comments"
11
+ "statusMessage": "(OmO 5.0.0-beta.32) Checking Comments"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-comment-checker",
3
- "version": "5.0.0-beta.30",
3
+ "version": "5.0.0-beta.32",
4
4
  "description": "Codex plugin that runs comment-checker after edit-like PostToolUse hooks.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
10
10
  "timeout": 5,
11
- "statusMessage": "(OmO 5.0.0-beta.30) Recommending Git Bash MCP"
11
+ "statusMessage": "(OmO 5.0.0-beta.32) Recommending Git Bash MCP"
12
12
  }
13
13
  ]
14
14
  }
@@ -20,7 +20,7 @@
20
20
  "type": "command",
21
21
  "command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
22
22
  "timeout": 5,
23
- "statusMessage": "(OmO 5.0.0-beta.30) Resetting Git Bash MCP Reminder"
23
+ "statusMessage": "(OmO 5.0.0-beta.32) Resetting Git Bash MCP Reminder"
24
24
  }
25
25
  ]
26
26
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-git-bash-hook",
3
- "version": "5.0.0-beta.30",
3
+ "version": "5.0.0-beta.32",
4
4
  "description": "Codex hook component that reminds Windows sessions to prefer the OMO git_bash MCP.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -8,7 +8,7 @@
8
8
  "type": "command",
9
9
  "command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
10
10
  "timeout": 10,
11
- "statusMessage": "(OmO 5.0.0-beta.30) Verifying LazyCodex Executor Evidence"
11
+ "statusMessage": "(OmO 5.0.0-beta.32) Verifying LazyCodex Executor Evidence"
12
12
  }
13
13
  ]
14
14
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/codex-lazycodex-executor-verify",
3
- "version": "5.0.0-beta.30",
3
+ "version": "5.0.0-beta.32",
4
4
  "description": "Codex SubagentStop evidence verifier for LazyCodex executor completions.",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.12.1",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "5.0.0-beta.30",
4
- "inputDigest": "sha256:e51c462bed771b67810446ab27ee35a6009800cb9e3869f41234c80ca6818caa",
3
+ "version": "5.0.0-beta.32",
4
+ "inputDigest": "sha256:7ebeb55787bcfcf32f5cdd2782c145f22c9aa8c595b7dedde0228036267ccfee",
5
5
  "outputs": [
6
6
  {
7
7
  "path": "cli.d.ts",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  {
11
11
  "path": "cli.js",
12
- "sha256": "5e3645a0299f523876c758e645e70f7a122a46da6ec7d3994473ec19f9048430"
12
+ "sha256": "89f0a2360dc1977cc00f2cdb661ff6929a7b90131728488502834a372840db3c"
13
13
  },
14
14
  {
15
15
  "path": "codex-hook-cli.d.ts",
@@ -745,6 +745,16 @@ class LspProcessSpawnError extends Error {
745
745
  this.name = "LspProcessSpawnError";
746
746
  }
747
747
  }
748
+
749
+ class LspClientRespawnBudgetExceededError extends Error {
750
+ constructor(serverId, root, retryLimit) {
751
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
752
+ this.serverId = serverId;
753
+ this.root = root;
754
+ this.retryLimit = retryLimit;
755
+ this.name = "LspClientRespawnBudgetExceededError";
756
+ }
757
+ }
748
758
  function isLspDeadConnectionError(err) {
749
759
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
750
760
  }
@@ -756,6 +766,11 @@ function reportBestEffortCleanupError(operation, error, logger = writeCleanupErr
756
766
  const message = error instanceof Error ? error.message : String(error);
757
767
  logger(`[lsp] ignored ${operation} failure during cleanup: ${message}`);
758
768
  }
769
+ var realTimerProvider = {
770
+ now: () => Date.now(),
771
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
772
+ clearTimeout: (handle) => clearTimeout(handle)
773
+ };
759
774
  var DEFAULT_MAX_REFERENCES = 200;
760
775
  var DEFAULT_MAX_SYMBOLS = 200;
761
776
  var DEFAULT_MAX_DIAGNOSTICS = 200;
@@ -767,6 +782,8 @@ var MAX_RESIDENT_CLIENTS = 6;
767
782
  var REAPER_INTERVAL_MS = 60000;
768
783
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
769
784
  var STOP_SIGKILL_GRACE_MS = 1000;
785
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
786
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
770
787
  var HEADER_SEPARATOR2 = `\r
771
788
  \r
772
789
  `;
@@ -1282,6 +1299,7 @@ class LspClientTransport {
1282
1299
  this.documentFormattingSupported = false;
1283
1300
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1284
1301
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1302
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
1285
1303
  }
1286
1304
  pid() {
1287
1305
  return this.proc?.pid;
@@ -1382,7 +1400,7 @@ class LspClientTransport {
1382
1400
  const options = args[1];
1383
1401
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
1384
1402
  const timeoutController = new AbortController;
1385
- const timeoutHandle = setTimeout(() => {
1403
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
1386
1404
  const stderrTail = this.stderrBuffer.slice(-5).join(`
1387
1405
  `);
1388
1406
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -1401,7 +1419,7 @@ class LspClientTransport {
1401
1419
  }
1402
1420
  throw error;
1403
1421
  } finally {
1404
- clearTimeout(timeoutHandle);
1422
+ this.timerProvider.clearTimeout(timeoutHandle);
1405
1423
  combinedSignal.dispose();
1406
1424
  }
1407
1425
  }
@@ -1771,6 +1789,17 @@ function canonicalPath(filePath) {
1771
1789
  return absolute;
1772
1790
  }
1773
1791
  }
1792
+ function normalizeDocumentUri(uri) {
1793
+ let decoded = uri;
1794
+ try {
1795
+ decoded = decodeURIComponent(uri);
1796
+ } catch {
1797
+ decoded = uri;
1798
+ }
1799
+ if (process.platform !== "win32")
1800
+ return decoded;
1801
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1802
+ }
1774
1803
  function isSameOrDescendant(candidate, parent) {
1775
1804
  const suffix = relative2(parent, candidate);
1776
1805
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1787,7 +1816,12 @@ class WorkspaceDocumentState {
1787
1816
  this.openDocuments = new Map;
1788
1817
  this.openByUri = new Map;
1789
1818
  this.openPromises = new Map;
1790
- this.now = options.now ?? (() => Date.now());
1819
+ this.timerProvider = options.timerProvider ?? {
1820
+ now: options.now ?? (() => Date.now()),
1821
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1822
+ clearTimeout: (handle) => clearTimeout(handle)
1823
+ };
1824
+ this.now = () => this.timerProvider.now();
1791
1825
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1792
1826
  }
1793
1827
  async openFile(filePath) {
@@ -1809,7 +1843,7 @@ class WorkspaceDocumentState {
1809
1843
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1810
1844
  }
1811
1845
  getStoredDiagnostics(uri) {
1812
- const state = this.openByUri.get(uri);
1846
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1813
1847
  if (!state)
1814
1848
  return [];
1815
1849
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1831,13 +1865,13 @@ class WorkspaceDocumentState {
1831
1865
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1832
1866
  }
1833
1867
  getPullCache(snapshot) {
1834
- const state = this.openByUri.get(snapshot.uri);
1868
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1835
1869
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1836
1870
  return null;
1837
1871
  return state.pullCache;
1838
1872
  }
1839
1873
  recordPullDiagnostics(snapshot, report) {
1840
- const state = this.openByUri.get(snapshot.uri);
1874
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1841
1875
  if (!state)
1842
1876
  return;
1843
1877
  state.pullCache = {
@@ -1847,7 +1881,7 @@ class WorkspaceDocumentState {
1847
1881
  };
1848
1882
  }
1849
1883
  recordPublishedDiagnostics(params) {
1850
- const state = this.openByUri.get(params.uri);
1884
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1851
1885
  if (!state)
1852
1886
  return;
1853
1887
  state.publishGeneration += 1;
@@ -1861,7 +1895,7 @@ class WorkspaceDocumentState {
1861
1895
  this.notifyWaiters(state);
1862
1896
  }
1863
1897
  resolvePushDiagnostics(snapshot) {
1864
- const state = this.openByUri.get(snapshot.uri);
1898
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1865
1899
  if (!state?.lastPublish)
1866
1900
  return { status: "missing" };
1867
1901
  const publish = state.lastPublish;
@@ -1875,7 +1909,7 @@ class WorkspaceDocumentState {
1875
1909
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1876
1910
  }
1877
1911
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1878
- const state = this.openByUri.get(snapshot.uri);
1912
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1879
1913
  if (!state || timeoutMs <= 0)
1880
1914
  return Promise.resolve();
1881
1915
  return new Promise((resolveActivity) => {
@@ -1884,11 +1918,11 @@ class WorkspaceDocumentState {
1884
1918
  if (settled)
1885
1919
  return;
1886
1920
  settled = true;
1887
- clearTimeout(timer);
1921
+ this.timerProvider.clearTimeout(timer);
1888
1922
  state.waiters.delete(finish);
1889
1923
  resolveActivity();
1890
1924
  };
1891
- const timer = setTimeout(finish, timeoutMs);
1925
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1892
1926
  if (typeof timer.unref === "function")
1893
1927
  timer.unref();
1894
1928
  state.waiters.add(finish);
@@ -1996,7 +2030,7 @@ class WorkspaceDocumentState {
1996
2030
  waiters: new Set
1997
2031
  };
1998
2032
  this.openDocuments.set(path2, state);
1999
- this.openByUri.set(state.uri, state);
2033
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
2000
2034
  this.notifyWaiters(state);
2001
2035
  await this.sendNotification("textDocument/didOpen", {
2002
2036
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -2021,7 +2055,7 @@ class WorkspaceDocumentState {
2021
2055
  }
2022
2056
  async closeDocument(state) {
2023
2057
  this.openDocuments.delete(state.path);
2024
- this.openByUri.delete(state.uri);
2058
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
2025
2059
  this.clearDiagnostics(state.uri);
2026
2060
  this.notifyWaiters(state);
2027
2061
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -3071,6 +3105,7 @@ class LspClient extends LspClientConnection {
3071
3105
  this.diagnosticPullErrors = [];
3072
3106
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
3073
3107
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
3108
+ timerProvider: this.timerProvider,
3074
3109
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
3075
3110
  });
3076
3111
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -3174,7 +3209,7 @@ class LspClient extends LspClientConnection {
3174
3209
  const absPath = this.resolveWorkspacePath(filePath);
3175
3210
  const uri = pathToFileURL3(absPath).href;
3176
3211
  await this.openFile(absPath);
3177
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
3212
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
3178
3213
  for (;; ) {
3179
3214
  signal?.throwIfAborted();
3180
3215
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -3187,7 +3222,7 @@ class LspClient extends LspClientConnection {
3187
3222
  if (!pushFallbackOnly) {
3188
3223
  const cached = this.documents.getPullCache(snapshot);
3189
3224
  try {
3190
- const remainingMs2 = deadlineAt - Date.now();
3225
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
3191
3226
  if (remainingMs2 <= 0)
3192
3227
  return this.freshnessTimeout(absPath);
3193
3228
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -3222,7 +3257,7 @@ class LspClient extends LspClientConnection {
3222
3257
  }
3223
3258
  if (!pushFallbackOnly)
3224
3259
  continue;
3225
- const remainingMs = deadlineAt - Date.now();
3260
+ const remainingMs = deadlineAt - this.timerProvider.now();
3226
3261
  if (remainingMs <= 0) {
3227
3262
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
3228
3263
  const cached = this.documents.getPullCache(snapshot);
@@ -3378,6 +3413,8 @@ function awaitWithSignal2(promise, signal) {
3378
3413
  class LspManager {
3379
3414
  constructor(options = {}) {
3380
3415
  this.clients = new Map;
3416
+ this.pendingStops = new Map;
3417
+ this.respawnBudgets = new Map;
3381
3418
  this.reaperHandle = null;
3382
3419
  this.signalDisposer = null;
3383
3420
  this.disposed = false;
@@ -3403,17 +3440,52 @@ class LspManager {
3403
3440
  getKey(root, serverId) {
3404
3441
  return `${root}::${serverId}`;
3405
3442
  }
3443
+ tombstoneStop(key, client) {
3444
+ const stop = stopClientBestEffort(client);
3445
+ this.pendingStops.set(key, stop);
3446
+ stop.finally(() => {
3447
+ if (this.pendingStops.get(key) === stop) {
3448
+ this.pendingStops.delete(key);
3449
+ }
3450
+ });
3451
+ return stop;
3452
+ }
3453
+ recordDeadGeneration(key) {
3454
+ let budget = this.respawnBudgets.get(key);
3455
+ if (budget === undefined) {
3456
+ budget = { deadGenerations: 0, exhaustedAt: null };
3457
+ this.respawnBudgets.set(key, budget);
3458
+ }
3459
+ budget.deadGenerations += 1;
3460
+ }
3461
+ markHealthyGeneration(key) {
3462
+ this.respawnBudgets.delete(key);
3463
+ }
3464
+ ensureRespawnAllowed(key, root, serverId) {
3465
+ const budget = this.respawnBudgets.get(key);
3466
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
3467
+ return;
3468
+ if (budget.exhaustedAt === null) {
3469
+ budget.exhaustedAt = this.now();
3470
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3471
+ }
3472
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
3473
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3474
+ }
3475
+ budget.deadGenerations = 0;
3476
+ budget.exhaustedAt = null;
3477
+ }
3406
3478
  reapStale() {
3407
3479
  const t = this.now();
3408
3480
  for (const [key, managed] of this.clients) {
3409
3481
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3410
- stopClientBestEffort(managed.client);
3411
3482
  this.clients.delete(key);
3483
+ this.tombstoneStop(key, managed.client);
3412
3484
  continue;
3413
3485
  }
3414
3486
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
3415
- stopClientBestEffort(managed.client);
3416
3487
  this.clients.delete(key);
3488
+ this.tombstoneStop(key, managed.client);
3417
3489
  }
3418
3490
  }
3419
3491
  }
@@ -3423,7 +3495,7 @@ class LspManager {
3423
3495
  if (!victim)
3424
3496
  return;
3425
3497
  this.clients.delete(victim.key);
3426
- stopClientBestEffort(victim.managed.client);
3498
+ this.tombstoneStop(victim.key, victim.managed.client);
3427
3499
  }
3428
3500
  }
3429
3501
  leastRecentlyUsedIdleClient() {
@@ -3440,7 +3512,7 @@ class LspManager {
3440
3512
  async tryDeleteIfOrphaned(key, managed) {
3441
3513
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3442
3514
  this.clients.delete(key);
3443
- await stopClientBestEffort(managed.client);
3515
+ await this.tombstoneStop(key, managed.client);
3444
3516
  }
3445
3517
  }
3446
3518
  async getClient(root, server2, signal) {
@@ -3449,12 +3521,22 @@ class LspManager {
3449
3521
  }
3450
3522
  signal?.throwIfAborted();
3451
3523
  const key = this.getKey(root, server2.id);
3524
+ for (;; ) {
3525
+ const pendingStop = this.pendingStops.get(key);
3526
+ if (pendingStop === undefined)
3527
+ break;
3528
+ await awaitWithSignal2(pendingStop, signal);
3529
+ signal?.throwIfAborted();
3530
+ }
3531
+ if (this.disposed) {
3532
+ throw new Error("LspManager has been disposed");
3533
+ }
3452
3534
  let managed = this.clients.get(key);
3453
3535
  if (managed) {
3454
3536
  const t = this.now();
3455
3537
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3456
- await stopClientBestEffort(managed.client);
3457
3538
  this.clients.delete(key);
3539
+ await this.tombstoneStop(key, managed.client);
3458
3540
  managed = undefined;
3459
3541
  }
3460
3542
  }
@@ -3475,15 +3557,20 @@ class LspManager {
3475
3557
  signal.throwIfAborted();
3476
3558
  }
3477
3559
  if (!managed.client.isAlive()) {
3478
- await stopClientBestEffort(managed.client);
3479
- this.clients.delete(key);
3560
+ this.recordDeadGeneration(key);
3561
+ if (this.clients.get(key) === managed) {
3562
+ this.clients.delete(key);
3563
+ }
3564
+ await this.tombstoneStop(key, managed.client);
3480
3565
  return this.getClient(root, server2, signal);
3481
3566
  }
3567
+ this.markHealthyGeneration(key);
3482
3568
  managed.refCount++;
3483
3569
  managed.lastUsedAt = this.now();
3484
3570
  return managed.client;
3485
3571
  }
3486
3572
  this.evictForAdmission();
3573
+ this.ensureRespawnAllowed(key, root, server2.id);
3487
3574
  const client = this.clientFactory(root, server2);
3488
3575
  const initStartedAt = this.now();
3489
3576
  const initPromise = (async () => {
@@ -3507,7 +3594,7 @@ class LspManager {
3507
3594
  if (this.clients.get(key) === newManaged) {
3508
3595
  this.clients.delete(key);
3509
3596
  }
3510
- await stopClientBestEffort(client);
3597
+ await this.tombstoneStop(key, client);
3511
3598
  throw err;
3512
3599
  }
3513
3600
  newManaged.pendingWaiters--;
@@ -3518,6 +3605,15 @@ class LspManager {
3518
3605
  await this.tryDeleteIfOrphaned(key, newManaged);
3519
3606
  signal.throwIfAborted();
3520
3607
  }
3608
+ if (!client.isAlive()) {
3609
+ this.recordDeadGeneration(key);
3610
+ if (this.clients.get(key) === newManaged) {
3611
+ this.clients.delete(key);
3612
+ }
3613
+ await this.tombstoneStop(key, client);
3614
+ return this.getClient(root, server2, signal);
3615
+ }
3616
+ this.markHealthyGeneration(key);
3521
3617
  newManaged.refCount++;
3522
3618
  newManaged.lastUsedAt = this.now();
3523
3619
  return client;
@@ -3538,15 +3634,20 @@ class LspManager {
3538
3634
  if (client && managed.client !== client)
3539
3635
  return;
3540
3636
  this.clients.delete(key);
3541
- stopClientBestEffort(managed.client);
3637
+ this.tombstoneStop(key, managed.client);
3542
3638
  }
3543
3639
  warmupClient(root, server2) {
3544
3640
  if (this.disposed)
3545
3641
  return;
3546
3642
  const key = this.getKey(root, server2.id);
3547
- if (this.clients.has(key))
3643
+ if (this.clients.has(key) || this.pendingStops.has(key))
3548
3644
  return;
3549
3645
  this.evictForAdmission();
3646
+ try {
3647
+ this.ensureRespawnAllowed(key, root, server2.id);
3648
+ } catch {
3649
+ return;
3650
+ }
3550
3651
  const client = this.clientFactory(root, server2);
3551
3652
  const initStartedAt = this.now();
3552
3653
  const initPromise = (async () => {
@@ -3572,7 +3673,7 @@ class LspManager {
3572
3673
  if (this.clients.get(key) === managed) {
3573
3674
  this.clients.delete(key);
3574
3675
  }
3575
- stopClientBestEffort(client);
3676
+ this.tombstoneStop(key, client);
3576
3677
  });
3577
3678
  }
3578
3679
  isServerInitializing(root, serverId) {
@@ -3616,8 +3717,11 @@ class LspManager {
3616
3717
  for (const managed of this.clients.values()) {
3617
3718
  stopPromises.push(stopClientBestEffort(managed.client));
3618
3719
  }
3720
+ const tombstonedStops = [...this.pendingStops.values()];
3619
3721
  this.clients.clear();
3620
- await Promise.allSettled(stopPromises);
3722
+ this.respawnBudgets.clear();
3723
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3724
+ this.pendingStops.clear();
3621
3725
  }
3622
3726
  }
3623
3727
  var _defaultInstance = null;
@@ -3627,7 +3731,16 @@ function getLspManager() {
3627
3731
  }
3628
3732
  return _defaultInstance;
3629
3733
  }
3630
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3734
+ var GIT_WORKSPACE_MARKER = ".git";
3735
+ var PROJECT_WORKSPACE_MARKERS = [
3736
+ "package.json",
3737
+ "pyproject.toml",
3738
+ "Cargo.toml",
3739
+ "go.mod",
3740
+ "pom.xml",
3741
+ "build.gradle"
3742
+ ];
3743
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
3631
3744
  function findWorkspaceRootOutsideContext(directory) {
3632
3745
  const marked = nearestMarkedAncestor(directory);
3633
3746
  if (marked !== undefined)
@@ -4297,20 +4410,25 @@ function findWorkspaceRoot(filePath) {
4297
4410
  if (!isPathInside(cwd, abs))
4298
4411
  return findWorkspaceRootOutsideContext(dir);
4299
4412
  const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4413
+ let nearestPackageRoot;
4300
4414
  while (isPathInside(cwd, dir)) {
4301
4415
  const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4302
4416
  if (canonicalDir !== undefined) {
4303
- for (const marker of WORKSPACE_MARKERS) {
4304
- if (existsSync11(join5(dir, marker))) {
4305
- return canonicalDir;
4306
- }
4417
+ if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
4418
+ return canonicalDir;
4419
+ }
4420
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4421
+ nearestPackageRoot = canonicalDir;
4307
4422
  }
4308
4423
  }
4309
4424
  if (dir === cwd)
4310
4425
  break;
4311
4426
  dir = dirname10(dir);
4312
4427
  }
4313
- return fallbackRoot;
4428
+ return nearestPackageRoot ?? fallbackRoot;
4429
+ }
4430
+ function hasProjectWorkspaceMarker(directory) {
4431
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
4314
4432
  }
4315
4433
  function resolveReadablePathInsideContext(filePath) {
4316
4434
  const cwd = contextCwd();
@@ -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 5.0.0-beta.30) Checking LSP Diagnostics"
11
+ "statusMessage": "(OmO 5.0.0-beta.32) 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 5.0.0-beta.30) Resetting LSP Diagnostics Cache"
24
+ "statusMessage": "(OmO 5.0.0-beta.32) 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": "5.0.0-beta.30",
3
+ "version": "5.0.0-beta.32",
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",