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
@@ -0,0 +1,51 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import {
4
+ clientOptions,
5
+ optionalBoolean,
6
+ optionalNumber,
7
+ optionalString,
8
+ requireNumber,
9
+ requireString,
10
+ severityFilter,
11
+ } from "./parameters.js";
12
+
13
+ describe("LSP tool parameter helpers", () => {
14
+ test("#given required string parameter #when value is missing or empty #then throws clear error", () => {
15
+ expect(requireString({ filePath: "index.ts" }, "filePath")).toBe("index.ts");
16
+ expect(() => requireString({}, "filePath")).toThrow("Missing required string parameter 'filePath'");
17
+ expect(() => requireString({ filePath: "" }, "filePath")).toThrow("Missing required string parameter 'filePath'");
18
+ expect(() => requireString({ filePath: 42 }, "filePath")).toThrow("Missing required string parameter 'filePath'");
19
+ });
20
+
21
+ test("#given required number parameter #when value is non-finite #then throws clear error", () => {
22
+ expect(requireNumber({ line: 3 }, "line")).toBe(3);
23
+ expect(() => requireNumber({}, "line")).toThrow("Missing required number parameter 'line'");
24
+ expect(() => requireNumber({ line: Number.NaN }, "line")).toThrow("Missing required number parameter 'line'");
25
+ expect(() => requireNumber({ line: Number.POSITIVE_INFINITY }, "line")).toThrow(
26
+ "Missing required number parameter 'line'",
27
+ );
28
+ });
29
+
30
+ test("#given optional parameters #when values have wrong type #then ignores them", () => {
31
+ expect(optionalString({ query: "symbol" }, "query")).toBe("symbol");
32
+ expect(optionalString({ query: 7 }, "query")).toBeUndefined();
33
+ expect(optionalNumber({ limit: 10 }, "limit")).toBe(10);
34
+ expect(optionalNumber({ limit: Number.NaN }, "limit")).toBeUndefined();
35
+ expect(optionalBoolean({ includeDeclaration: false }, "includeDeclaration")).toBe(false);
36
+ expect(optionalBoolean({ includeDeclaration: "false" }, "includeDeclaration")).toBeUndefined();
37
+ });
38
+
39
+ test("#given severity parameter #when value is unknown #then defaults to all", () => {
40
+ expect(severityFilter({ severity: "warning" })).toBe("warning");
41
+ expect(severityFilter({ severity: "fatal" })).toBe("all");
42
+ expect(severityFilter({})).toBe("all");
43
+ });
44
+
45
+ test("#given optional abort signal #when building client options #then includes only defined signal", () => {
46
+ const controller = new AbortController();
47
+
48
+ expect(clientOptions(undefined)).toEqual({});
49
+ expect(clientOptions(controller.signal)).toEqual({ signal: controller.signal });
50
+ });
51
+ });
@@ -184,6 +184,7 @@ async function runJsonRpcStdioServer(config) {
184
184
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
185
185
  isClosed = true;
186
186
  config.onIdleTimeout?.();
187
+ config.input.destroy();
187
188
  });
188
189
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
189
190
  isClosed = true;
@@ -563,6 +564,16 @@ class LspProcessSpawnError extends Error {
563
564
  this.name = "LspProcessSpawnError";
564
565
  }
565
566
  }
567
+
568
+ class LspClientRespawnBudgetExceededError extends Error {
569
+ constructor(serverId, root, retryLimit) {
570
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
571
+ this.serverId = serverId;
572
+ this.root = root;
573
+ this.retryLimit = retryLimit;
574
+ this.name = "LspClientRespawnBudgetExceededError";
575
+ }
576
+ }
566
577
  function isLspDeadConnectionError(err) {
567
578
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
568
579
  }
@@ -584,6 +595,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
584
595
  // ../lsp-core/src/lsp/connection.ts
585
596
  import { pathToFileURL } from "node:url";
586
597
 
598
+ // ../lsp-core/src/lsp/timer-provider.ts
599
+ var realTimerProvider = {
600
+ now: () => Date.now(),
601
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
602
+ clearTimeout: (handle) => clearTimeout(handle)
603
+ };
604
+
587
605
  // ../lsp-core/src/lsp/constants.ts
588
606
  var DEFAULT_MAX_REFERENCES = 200;
589
607
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -596,6 +614,8 @@ var MAX_RESIDENT_CLIENTS = 6;
596
614
  var REAPER_INTERVAL_MS = 60000;
597
615
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
598
616
  var STOP_SIGKILL_GRACE_MS = 1000;
617
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
618
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
599
619
 
600
620
  // ../lsp-core/src/lsp/json-rpc-connection.ts
601
621
  var HEADER_SEPARATOR2 = `\r
@@ -1121,6 +1141,7 @@ class LspClientTransport {
1121
1141
  this.documentFormattingSupported = false;
1122
1142
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
1123
1143
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
1144
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
1124
1145
  }
1125
1146
  pid() {
1126
1147
  return this.proc?.pid;
@@ -1221,7 +1242,7 @@ class LspClientTransport {
1221
1242
  const options = args[1];
1222
1243
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
1223
1244
  const timeoutController = new AbortController;
1224
- const timeoutHandle = setTimeout(() => {
1245
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
1225
1246
  const stderrTail = this.stderrBuffer.slice(-5).join(`
1226
1247
  `);
1227
1248
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -1240,7 +1261,7 @@ class LspClientTransport {
1240
1261
  }
1241
1262
  throw error;
1242
1263
  } finally {
1243
- clearTimeout(timeoutHandle);
1264
+ this.timerProvider.clearTimeout(timeoutHandle);
1244
1265
  combinedSignal.dispose();
1245
1266
  }
1246
1267
  }
@@ -1621,6 +1642,17 @@ function canonicalPath(filePath) {
1621
1642
  return absolute;
1622
1643
  }
1623
1644
  }
1645
+ function normalizeDocumentUri(uri) {
1646
+ let decoded = uri;
1647
+ try {
1648
+ decoded = decodeURIComponent(uri);
1649
+ } catch {
1650
+ decoded = uri;
1651
+ }
1652
+ if (process.platform !== "win32")
1653
+ return decoded;
1654
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1655
+ }
1624
1656
  function isSameOrDescendant(candidate, parent) {
1625
1657
  const suffix = relative2(parent, candidate);
1626
1658
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1637,7 +1669,12 @@ class WorkspaceDocumentState {
1637
1669
  this.openDocuments = new Map;
1638
1670
  this.openByUri = new Map;
1639
1671
  this.openPromises = new Map;
1640
- this.now = options.now ?? (() => Date.now());
1672
+ this.timerProvider = options.timerProvider ?? {
1673
+ now: options.now ?? (() => Date.now()),
1674
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1675
+ clearTimeout: (handle) => clearTimeout(handle)
1676
+ };
1677
+ this.now = () => this.timerProvider.now();
1641
1678
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1642
1679
  }
1643
1680
  async openFile(filePath) {
@@ -1659,7 +1696,7 @@ class WorkspaceDocumentState {
1659
1696
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1660
1697
  }
1661
1698
  getStoredDiagnostics(uri) {
1662
- const state = this.openByUri.get(uri);
1699
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1663
1700
  if (!state)
1664
1701
  return [];
1665
1702
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1681,13 +1718,13 @@ class WorkspaceDocumentState {
1681
1718
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1682
1719
  }
1683
1720
  getPullCache(snapshot) {
1684
- const state = this.openByUri.get(snapshot.uri);
1721
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1685
1722
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1686
1723
  return null;
1687
1724
  return state.pullCache;
1688
1725
  }
1689
1726
  recordPullDiagnostics(snapshot, report) {
1690
- const state = this.openByUri.get(snapshot.uri);
1727
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1691
1728
  if (!state)
1692
1729
  return;
1693
1730
  state.pullCache = {
@@ -1697,7 +1734,7 @@ class WorkspaceDocumentState {
1697
1734
  };
1698
1735
  }
1699
1736
  recordPublishedDiagnostics(params) {
1700
- const state = this.openByUri.get(params.uri);
1737
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1701
1738
  if (!state)
1702
1739
  return;
1703
1740
  state.publishGeneration += 1;
@@ -1711,7 +1748,7 @@ class WorkspaceDocumentState {
1711
1748
  this.notifyWaiters(state);
1712
1749
  }
1713
1750
  resolvePushDiagnostics(snapshot) {
1714
- const state = this.openByUri.get(snapshot.uri);
1751
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1715
1752
  if (!state?.lastPublish)
1716
1753
  return { status: "missing" };
1717
1754
  const publish = state.lastPublish;
@@ -1725,7 +1762,7 @@ class WorkspaceDocumentState {
1725
1762
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1726
1763
  }
1727
1764
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1728
- const state = this.openByUri.get(snapshot.uri);
1765
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1729
1766
  if (!state || timeoutMs <= 0)
1730
1767
  return Promise.resolve();
1731
1768
  return new Promise((resolveActivity) => {
@@ -1734,11 +1771,11 @@ class WorkspaceDocumentState {
1734
1771
  if (settled)
1735
1772
  return;
1736
1773
  settled = true;
1737
- clearTimeout(timer);
1774
+ this.timerProvider.clearTimeout(timer);
1738
1775
  state.waiters.delete(finish);
1739
1776
  resolveActivity();
1740
1777
  };
1741
- const timer = setTimeout(finish, timeoutMs);
1778
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1742
1779
  if (typeof timer.unref === "function")
1743
1780
  timer.unref();
1744
1781
  state.waiters.add(finish);
@@ -1846,7 +1883,7 @@ class WorkspaceDocumentState {
1846
1883
  waiters: new Set
1847
1884
  };
1848
1885
  this.openDocuments.set(path, state);
1849
- this.openByUri.set(state.uri, state);
1886
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
1850
1887
  this.notifyWaiters(state);
1851
1888
  await this.sendNotification("textDocument/didOpen", {
1852
1889
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -1871,7 +1908,7 @@ class WorkspaceDocumentState {
1871
1908
  }
1872
1909
  async closeDocument(state) {
1873
1910
  this.openDocuments.delete(state.path);
1874
- this.openByUri.delete(state.uri);
1911
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
1875
1912
  this.clearDiagnostics(state.uri);
1876
1913
  this.notifyWaiters(state);
1877
1914
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -2958,6 +2995,7 @@ class LspClient extends LspClientConnection {
2958
2995
  this.diagnosticPullErrors = [];
2959
2996
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2960
2997
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2998
+ timerProvider: this.timerProvider,
2961
2999
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
2962
3000
  });
2963
3001
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -3061,7 +3099,7 @@ class LspClient extends LspClientConnection {
3061
3099
  const absPath = this.resolveWorkspacePath(filePath);
3062
3100
  const uri = pathToFileURL3(absPath).href;
3063
3101
  await this.openFile(absPath);
3064
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
3102
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
3065
3103
  for (;; ) {
3066
3104
  signal?.throwIfAborted();
3067
3105
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -3074,7 +3112,7 @@ class LspClient extends LspClientConnection {
3074
3112
  if (!pushFallbackOnly) {
3075
3113
  const cached = this.documents.getPullCache(snapshot);
3076
3114
  try {
3077
- const remainingMs2 = deadlineAt - Date.now();
3115
+ const remainingMs2 = deadlineAt - this.timerProvider.now();
3078
3116
  if (remainingMs2 <= 0)
3079
3117
  return this.freshnessTimeout(absPath);
3080
3118
  const result = await this.sendRequest("textDocument/diagnostic", {
@@ -3109,7 +3147,7 @@ class LspClient extends LspClientConnection {
3109
3147
  }
3110
3148
  if (!pushFallbackOnly)
3111
3149
  continue;
3112
- const remainingMs = deadlineAt - Date.now();
3150
+ const remainingMs = deadlineAt - this.timerProvider.now();
3113
3151
  if (remainingMs <= 0) {
3114
3152
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
3115
3153
  const cached = this.documents.getPullCache(snapshot);
@@ -3269,6 +3307,8 @@ function awaitWithSignal(promise, signal) {
3269
3307
  class LspManager {
3270
3308
  constructor(options = {}) {
3271
3309
  this.clients = new Map;
3310
+ this.pendingStops = new Map;
3311
+ this.respawnBudgets = new Map;
3272
3312
  this.reaperHandle = null;
3273
3313
  this.signalDisposer = null;
3274
3314
  this.disposed = false;
@@ -3294,17 +3334,52 @@ class LspManager {
3294
3334
  getKey(root, serverId) {
3295
3335
  return `${root}::${serverId}`;
3296
3336
  }
3337
+ tombstoneStop(key, client) {
3338
+ const stop = stopClientBestEffort(client);
3339
+ this.pendingStops.set(key, stop);
3340
+ stop.finally(() => {
3341
+ if (this.pendingStops.get(key) === stop) {
3342
+ this.pendingStops.delete(key);
3343
+ }
3344
+ });
3345
+ return stop;
3346
+ }
3347
+ recordDeadGeneration(key) {
3348
+ let budget = this.respawnBudgets.get(key);
3349
+ if (budget === undefined) {
3350
+ budget = { deadGenerations: 0, exhaustedAt: null };
3351
+ this.respawnBudgets.set(key, budget);
3352
+ }
3353
+ budget.deadGenerations += 1;
3354
+ }
3355
+ markHealthyGeneration(key) {
3356
+ this.respawnBudgets.delete(key);
3357
+ }
3358
+ ensureRespawnAllowed(key, root, serverId) {
3359
+ const budget = this.respawnBudgets.get(key);
3360
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
3361
+ return;
3362
+ if (budget.exhaustedAt === null) {
3363
+ budget.exhaustedAt = this.now();
3364
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3365
+ }
3366
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
3367
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
3368
+ }
3369
+ budget.deadGenerations = 0;
3370
+ budget.exhaustedAt = null;
3371
+ }
3297
3372
  reapStale() {
3298
3373
  const t = this.now();
3299
3374
  for (const [key, managed] of this.clients) {
3300
3375
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3301
- stopClientBestEffort(managed.client);
3302
3376
  this.clients.delete(key);
3377
+ this.tombstoneStop(key, managed.client);
3303
3378
  continue;
3304
3379
  }
3305
3380
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
3306
- stopClientBestEffort(managed.client);
3307
3381
  this.clients.delete(key);
3382
+ this.tombstoneStop(key, managed.client);
3308
3383
  }
3309
3384
  }
3310
3385
  }
@@ -3314,7 +3389,7 @@ class LspManager {
3314
3389
  if (!victim)
3315
3390
  return;
3316
3391
  this.clients.delete(victim.key);
3317
- stopClientBestEffort(victim.managed.client);
3392
+ this.tombstoneStop(victim.key, victim.managed.client);
3318
3393
  }
3319
3394
  }
3320
3395
  leastRecentlyUsedIdleClient() {
@@ -3331,7 +3406,7 @@ class LspManager {
3331
3406
  async tryDeleteIfOrphaned(key, managed) {
3332
3407
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
3333
3408
  this.clients.delete(key);
3334
- await stopClientBestEffort(managed.client);
3409
+ await this.tombstoneStop(key, managed.client);
3335
3410
  }
3336
3411
  }
3337
3412
  async getClient(root, server2, signal) {
@@ -3340,12 +3415,22 @@ class LspManager {
3340
3415
  }
3341
3416
  signal?.throwIfAborted();
3342
3417
  const key = this.getKey(root, server2.id);
3418
+ for (;; ) {
3419
+ const pendingStop = this.pendingStops.get(key);
3420
+ if (pendingStop === undefined)
3421
+ break;
3422
+ await awaitWithSignal(pendingStop, signal);
3423
+ signal?.throwIfAborted();
3424
+ }
3425
+ if (this.disposed) {
3426
+ throw new Error("LspManager has been disposed");
3427
+ }
3343
3428
  let managed = this.clients.get(key);
3344
3429
  if (managed) {
3345
3430
  const t = this.now();
3346
3431
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
3347
- await stopClientBestEffort(managed.client);
3348
3432
  this.clients.delete(key);
3433
+ await this.tombstoneStop(key, managed.client);
3349
3434
  managed = undefined;
3350
3435
  }
3351
3436
  }
@@ -3366,15 +3451,20 @@ class LspManager {
3366
3451
  signal.throwIfAborted();
3367
3452
  }
3368
3453
  if (!managed.client.isAlive()) {
3369
- await stopClientBestEffort(managed.client);
3370
- this.clients.delete(key);
3454
+ this.recordDeadGeneration(key);
3455
+ if (this.clients.get(key) === managed) {
3456
+ this.clients.delete(key);
3457
+ }
3458
+ await this.tombstoneStop(key, managed.client);
3371
3459
  return this.getClient(root, server2, signal);
3372
3460
  }
3461
+ this.markHealthyGeneration(key);
3373
3462
  managed.refCount++;
3374
3463
  managed.lastUsedAt = this.now();
3375
3464
  return managed.client;
3376
3465
  }
3377
3466
  this.evictForAdmission();
3467
+ this.ensureRespawnAllowed(key, root, server2.id);
3378
3468
  const client = this.clientFactory(root, server2);
3379
3469
  const initStartedAt = this.now();
3380
3470
  const initPromise = (async () => {
@@ -3398,7 +3488,7 @@ class LspManager {
3398
3488
  if (this.clients.get(key) === newManaged) {
3399
3489
  this.clients.delete(key);
3400
3490
  }
3401
- await stopClientBestEffort(client);
3491
+ await this.tombstoneStop(key, client);
3402
3492
  throw err;
3403
3493
  }
3404
3494
  newManaged.pendingWaiters--;
@@ -3409,6 +3499,15 @@ class LspManager {
3409
3499
  await this.tryDeleteIfOrphaned(key, newManaged);
3410
3500
  signal.throwIfAborted();
3411
3501
  }
3502
+ if (!client.isAlive()) {
3503
+ this.recordDeadGeneration(key);
3504
+ if (this.clients.get(key) === newManaged) {
3505
+ this.clients.delete(key);
3506
+ }
3507
+ await this.tombstoneStop(key, client);
3508
+ return this.getClient(root, server2, signal);
3509
+ }
3510
+ this.markHealthyGeneration(key);
3412
3511
  newManaged.refCount++;
3413
3512
  newManaged.lastUsedAt = this.now();
3414
3513
  return client;
@@ -3429,15 +3528,20 @@ class LspManager {
3429
3528
  if (client && managed.client !== client)
3430
3529
  return;
3431
3530
  this.clients.delete(key);
3432
- stopClientBestEffort(managed.client);
3531
+ this.tombstoneStop(key, managed.client);
3433
3532
  }
3434
3533
  warmupClient(root, server2) {
3435
3534
  if (this.disposed)
3436
3535
  return;
3437
3536
  const key = this.getKey(root, server2.id);
3438
- if (this.clients.has(key))
3537
+ if (this.clients.has(key) || this.pendingStops.has(key))
3439
3538
  return;
3440
3539
  this.evictForAdmission();
3540
+ try {
3541
+ this.ensureRespawnAllowed(key, root, server2.id);
3542
+ } catch {
3543
+ return;
3544
+ }
3441
3545
  const client = this.clientFactory(root, server2);
3442
3546
  const initStartedAt = this.now();
3443
3547
  const initPromise = (async () => {
@@ -3463,7 +3567,7 @@ class LspManager {
3463
3567
  if (this.clients.get(key) === managed) {
3464
3568
  this.clients.delete(key);
3465
3569
  }
3466
- stopClientBestEffort(client);
3570
+ this.tombstoneStop(key, client);
3467
3571
  });
3468
3572
  }
3469
3573
  isServerInitializing(root, serverId) {
@@ -3507,8 +3611,11 @@ class LspManager {
3507
3611
  for (const managed of this.clients.values()) {
3508
3612
  stopPromises.push(stopClientBestEffort(managed.client));
3509
3613
  }
3614
+ const tombstonedStops = [...this.pendingStops.values()];
3510
3615
  this.clients.clear();
3511
- await Promise.allSettled(stopPromises);
3616
+ this.respawnBudgets.clear();
3617
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3618
+ this.pendingStops.clear();
3512
3619
  }
3513
3620
  }
3514
3621
  var _defaultInstance = null;
@@ -3531,7 +3638,16 @@ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:f
3531
3638
  import { dirname as dirname5, join as join3 } from "node:path";
3532
3639
 
3533
3640
  // ../lsp-core/src/lsp/workspace-markers.ts
3534
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
3641
+ var GIT_WORKSPACE_MARKER = ".git";
3642
+ var PROJECT_WORKSPACE_MARKERS = [
3643
+ "package.json",
3644
+ "pyproject.toml",
3645
+ "Cargo.toml",
3646
+ "go.mod",
3647
+ "pom.xml",
3648
+ "build.gradle"
3649
+ ];
3650
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
3535
3651
 
3536
3652
  // ../lsp-core/src/lsp/outside-context-workspace.ts
3537
3653
  function findWorkspaceRootOutsideContext(directory) {
@@ -4220,20 +4336,25 @@ function findWorkspaceRoot(filePath) {
4220
4336
  if (!isPathInside(cwd, abs))
4221
4337
  return findWorkspaceRootOutsideContext(dir);
4222
4338
  const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4339
+ let nearestPackageRoot;
4223
4340
  while (isPathInside(cwd, dir)) {
4224
4341
  const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4225
4342
  if (canonicalDir !== undefined) {
4226
- for (const marker of WORKSPACE_MARKERS) {
4227
- if (existsSync10(join5(dir, marker))) {
4228
- return canonicalDir;
4229
- }
4343
+ if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
4344
+ return canonicalDir;
4345
+ }
4346
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4347
+ nearestPackageRoot = canonicalDir;
4230
4348
  }
4231
4349
  }
4232
4350
  if (dir === cwd)
4233
4351
  break;
4234
4352
  dir = dirname8(dir);
4235
4353
  }
4236
- return fallbackRoot;
4354
+ return nearestPackageRoot ?? fallbackRoot;
4355
+ }
4356
+ function hasProjectWorkspaceMarker(directory) {
4357
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
4237
4358
  }
4238
4359
  function resolveReadablePathInsideContext(filePath) {
4239
4360
  const cwd = contextCwd();