oh-my-opencode 5.0.0-beta.6 → 5.0.0-beta.60

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 (990) hide show
  1. package/.agents/command/publish.md +59 -23
  2. package/.agents/skills/codex-qa/scripts/lsp-e2e.sh +1 -3
  3. package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +1 -1
  4. package/.agents/skills/pre-publish-review/SKILL.md +9 -12
  5. package/.agents/skills/publish/SKILL.md +59 -23
  6. package/.agents/skills/senpi-qa/SKILL.md +80 -0
  7. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
  8. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
  9. package/.agents/skills/tech-debt-audit/SKILL.md +6 -76
  10. package/.agents/skills/work-with-pr/SKILL.md +37 -23
  11. package/.opencode/command/publish.md +59 -23
  12. package/.opencode/skills/pre-publish-review/SKILL.md +9 -12
  13. package/.opencode/skills/work-with-pr/SKILL.md +37 -23
  14. package/README.ja.md +65 -60
  15. package/README.ko.md +66 -61
  16. package/README.md +65 -72
  17. package/README.ru.md +62 -60
  18. package/README.zh-cn.md +61 -60
  19. package/THIRD-PARTY-NOTICES.md +27 -99
  20. package/dist/agents/atlas/agent.d.ts +0 -1
  21. package/dist/agents/gpt-prompt-identity.d.ts +1 -1
  22. package/dist/agents/sisyphus/grok-4.d.ts +20 -0
  23. package/dist/agents/sisyphus/index.d.ts +2 -0
  24. package/dist/agents/sisyphus-agent-config.d.ts +6 -0
  25. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  26. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
  27. package/dist/agents/types.d.ts +4 -2
  28. package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
  29. package/dist/cli/doctor/checks/index.d.ts +2 -0
  30. package/dist/cli/doctor/checks/latest-version.d.ts +11 -0
  31. package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
  32. package/dist/cli/doctor/framework/constants.d.ts +5 -0
  33. package/dist/cli/doctor/framework/types.d.ts +2 -0
  34. package/dist/cli/fallback-lane-policy.d.ts +1 -0
  35. package/dist/cli/index.js +51738 -59690
  36. package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
  37. package/dist/cli/run/on-complete-hook.d.ts +2 -0
  38. package/dist/cli/runtime-commands.d.ts +1 -1
  39. package/dist/cli/worktree-sweep/classify.d.ts +16 -0
  40. package/dist/cli/worktree-sweep/format.d.ts +8 -0
  41. package/dist/cli/worktree-sweep/git.d.ts +19 -0
  42. package/dist/cli/worktree-sweep/index.d.ts +7 -0
  43. package/dist/cli/worktree-sweep/options.d.ts +2 -0
  44. package/dist/cli/worktree-sweep/parse-worktree-list.d.ts +8 -0
  45. package/dist/cli/worktree-sweep/sweep.d.ts +2 -0
  46. package/dist/cli/worktree-sweep/types.d.ts +65 -0
  47. package/dist/cli/worktree-sweep/worktree-sweep.d.ts +2 -0
  48. package/dist/cli-node/index.js +50900 -58829
  49. package/dist/config/index.d.ts +1 -1
  50. package/dist/config/schema/background-task.d.ts +1 -0
  51. package/dist/config/schema/commands.d.ts +1 -1
  52. package/dist/config/schema/hooks.d.ts +1 -2
  53. package/dist/config/schema/oh-my-opencode-config.d.ts +5 -11
  54. package/dist/config/schema/ulw-execute.d.ts +5 -0
  55. package/dist/config/schema.d.ts +0 -1
  56. package/dist/config/validate.d.ts +2 -0
  57. package/dist/create-hooks.d.ts +3 -2
  58. package/dist/features/background-agent/compaction-aware-message-resolver.d.ts +1 -0
  59. package/dist/features/background-agent/constants.d.ts +0 -7
  60. package/dist/features/background-agent/error-classifier.d.ts +1 -0
  61. package/dist/features/background-agent/manager.d.ts +9 -1
  62. package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
  63. package/dist/features/background-agent/parent-wake-notifier-types.d.ts +1 -1
  64. package/dist/features/background-agent/parent-wake-prompt-dispatch.d.ts +1 -1
  65. package/dist/features/background-agent/parent-wake-session-inspector.d.ts +1 -1
  66. package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
  67. package/dist/features/background-agent/types.d.ts +4 -0
  68. package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
  69. package/dist/features/btw-side/context-injector.d.ts +15 -0
  70. package/dist/features/btw-side/index.d.ts +8 -0
  71. package/dist/features/btw-side/metadata.d.ts +15 -0
  72. package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
  73. package/dist/features/btw-side/server-session-registry.d.ts +8 -0
  74. package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
  75. package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
  76. package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
  77. package/dist/features/btw-side/tui-controller.d.ts +19 -0
  78. package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
  79. package/dist/features/btw-side/tui-keymap.d.ts +17 -0
  80. package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
  81. package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
  82. package/dist/features/btw-side/tui-picker.d.ts +9 -0
  83. package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
  84. package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
  85. package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
  86. package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
  87. package/dist/features/btw-side/tui-side-start.d.ts +9 -0
  88. package/dist/features/btw-side/tui-wiring.d.ts +8 -0
  89. package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
  90. package/dist/features/builtin-commands/types.d.ts +1 -1
  91. package/dist/features/claude-tasks/storage.d.ts +7 -2
  92. package/dist/features/hook-message-injector/index.d.ts +1 -0
  93. package/dist/features/hook-message-injector/sdk-message-lookup.d.ts +1 -0
  94. package/dist/features/monitor/manager-internals.d.ts +1 -1
  95. package/dist/features/monitor/output-injector-types.d.ts +1 -1
  96. package/dist/features/opengateway-provider/index.d.ts +13 -0
  97. package/dist/features/task-toast-manager/manager.d.ts +0 -24
  98. package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +17 -0
  99. package/dist/features/team-mode/tools/messaging-live-delivery-recipient.d.ts +3 -0
  100. package/dist/features/team-mode/tools/messaging-runtime.d.ts +7 -0
  101. package/dist/hooks/anthropic-context-window-limit-recovery/message-storage-directory.d.ts +0 -3
  102. package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +1 -0
  103. package/dist/hooks/anthropic-context-window-limit-recovery/storage/empty-messages.d.ts +0 -1
  104. package/dist/hooks/anthropic-context-window-limit-recovery/tool-result-storage.d.ts +11 -0
  105. package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
  106. package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
  107. package/dist/hooks/atlas/event-handler.d.ts +1 -0
  108. package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
  109. package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
  110. package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
  111. package/dist/hooks/atlas/types.d.ts +1 -0
  112. package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
  113. package/dist/hooks/claude-code-hooks/stop.d.ts +2 -0
  114. package/dist/hooks/claude-code-hooks/todo.d.ts +0 -1
  115. package/dist/hooks/claude-code-hooks/transcript.d.ts +2 -0
  116. package/dist/hooks/compaction-context-injector/validated-model.d.ts +2 -0
  117. package/dist/hooks/fsync-skip-warning/index.d.ts +4 -0
  118. package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +1 -0
  119. package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +13 -0
  120. package/dist/hooks/index.d.ts +1 -2
  121. package/dist/hooks/keyword-detector/hook.d.ts +9 -0
  122. package/dist/hooks/keyword-detector/ultrawork/index.d.ts +2 -0
  123. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
  124. package/dist/hooks/model-fallback/hook.d.ts +1 -1
  125. package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
  126. package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
  127. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
  128. package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
  129. package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
  130. package/dist/hooks/runtime-fallback/types.d.ts +3 -1
  131. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  132. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  133. package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
  134. package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
  135. package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
  136. package/dist/hooks/unstable-agent-babysitter/task-message-analyzer.d.ts +1 -0
  137. package/dist/index.js +29256 -25391
  138. package/dist/mcp/index.d.ts +0 -4
  139. package/dist/mcp/types.d.ts +0 -1
  140. package/dist/oh-my-opencode.schema.json +21 -47
  141. package/dist/plugin/chat-message/types.d.ts +6 -4
  142. package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
  143. package/dist/plugin/event-session-lifecycle.d.ts +1 -0
  144. package/dist/plugin/hooks/create-core-hooks.d.ts +2 -2
  145. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -3
  146. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  147. package/dist/plugin/messages-transform.d.ts +1 -0
  148. package/dist/plugin/stop-continuation.d.ts +3 -0
  149. package/dist/plugin/system-transform.d.ts +5 -1
  150. package/dist/plugin-dispose.d.ts +3 -0
  151. package/dist/shared/agent-tool-restrictions.d.ts +0 -1
  152. package/dist/shared/compaction-agent-config-checkpoint.d.ts +1 -0
  153. package/dist/shared/index.d.ts +2 -0
  154. package/dist/shared/legacy-plugin-warning.d.ts +2 -1
  155. package/dist/shared/normalize-sdk-response.d.ts +1 -0
  156. package/dist/shared/omo-process-sweep.d.ts +2 -4
  157. package/dist/shared/plugin-entry-migrator.d.ts +4 -3
  158. package/dist/shared/plugin-entry-shape.d.ts +6 -0
  159. package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
  160. package/dist/shared/shell-env.d.ts +1 -1
  161. package/dist/skills/ast-grep/AGENTS.md +51 -0
  162. package/dist/skills/ast-grep/SKILL.md +1 -1
  163. package/dist/skills/coding-agent-sessions/AGENTS.md +62 -0
  164. package/dist/skills/coding-agent-sessions/SKILL.md +1 -1
  165. package/dist/skills/data-scientist/SKILL.md +99 -239
  166. package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
  167. package/dist/skills/data-scientist/references/placement.md +74 -0
  168. package/dist/skills/data-scientist/references/polars-lane.md +95 -0
  169. package/dist/skills/data-scientist/references/uv-setup.md +1 -1
  170. package/dist/skills/data-scientist/references/visualization.md +64 -0
  171. package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  172. package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  173. package/dist/skills/debugging/SKILL.md +3 -1
  174. package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
  175. package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
  176. package/dist/skills/debugging/references/runtimes/go.md +15 -1
  177. package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
  178. package/dist/skills/debugging/references/runtimes/node.md +25 -0
  179. package/dist/skills/debugging/references/runtimes/python.md +13 -0
  180. package/dist/skills/debugging/references/runtimes/rust.md +41 -0
  181. package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
  182. package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
  183. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  184. package/dist/skills/debugging/references/tools/dap.md +103 -0
  185. package/dist/skills/debugging/references/tools/frida.md +193 -0
  186. package/dist/skills/frontend/ATTRIBUTION.md +10 -0
  187. package/dist/skills/frontend/SKILL.md +15 -8
  188. package/dist/skills/frontend/references/design/README.md +10 -2
  189. package/dist/skills/frontend/references/design/_INDEX.md +2 -0
  190. package/dist/skills/frontend/references/design/ambience-skill.md +145 -0
  191. package/dist/skills/frontend/references/design/interaction-skill.md +2 -0
  192. package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
  193. package/dist/skills/frontend/references/design/stylegallery.md +80 -0
  194. package/dist/skills/frontend/references/designpowers/README.md +1 -1
  195. package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  196. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  197. package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  198. package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
  199. package/dist/skills/frontend/references/designpowers/routing.md +5 -5
  200. package/dist/skills/git-master/SKILL.md +1 -1
  201. package/dist/skills/init-deep/SKILL.md +14 -14
  202. package/dist/skills/lsp-setup/SKILL.md +1 -1
  203. package/dist/skills/programming/SKILL.md +1 -1
  204. package/dist/skills/refactor/SKILL.md +4 -4
  205. package/dist/skills/remove-ai-slops/SKILL.md +1 -1
  206. package/dist/skills/review-work/SKILL.md +101 -419
  207. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  208. package/dist/skills/ultimate-browsing/SKILL.md +26 -9
  209. package/dist/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  210. package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
  211. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  212. package/dist/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  213. package/dist/skills/{start-work → ulw-execute}/SKILL.md +20 -19
  214. package/dist/skills/ulw-plan/SKILL.md +7 -8
  215. package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
  216. package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
  217. package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
  218. package/dist/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  219. package/dist/skills/ulw-research/SKILL.md +8 -3
  220. package/dist/skills/visual-qa/AGENTS.md +58 -0
  221. package/dist/skills/visual-qa/SKILL.md +4 -3
  222. package/dist/tools/delegate-task/builtin-categories.d.ts +3 -1
  223. package/dist/tools/delegate-task/builtin-category-definition.d.ts +2 -1
  224. package/dist/tools/delegate-task/constants.d.ts +2 -2
  225. package/dist/tools/delegate-task/openai-categories.d.ts +7 -2
  226. package/dist/tools/delegate-task/sync-session-cleanup.d.ts +3 -0
  227. package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -0
  228. package/dist/tools/delegate-task/tool-description.d.ts +3 -1
  229. package/dist/tools/delegate-task/types.d.ts +4 -0
  230. package/dist/tools/session-manager/directory-filter.d.ts +2 -0
  231. package/dist/tui.d.ts +12 -0
  232. package/dist/tui.js +37048 -46599
  233. package/package.json +47 -41
  234. package/packages/git-bash-mcp/dist/cli.js +6 -1
  235. package/packages/git-bash-mcp/package.json +1 -1
  236. package/packages/lsp-core/src/index.ts +1 -0
  237. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
  238. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +57 -48
  239. package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
  240. package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
  241. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +103 -6
  242. package/packages/lsp-core/src/lsp/client-wrapper.ts +50 -16
  243. package/packages/lsp-core/src/lsp/client.ts +32 -3
  244. package/packages/lsp-core/src/lsp/connection.ts +16 -0
  245. package/packages/lsp-core/src/lsp/constants.ts +6 -0
  246. package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +61 -0
  247. package/packages/lsp-core/src/lsp/errors.ts +15 -0
  248. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +10 -3
  249. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  250. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  251. package/packages/lsp-core/src/lsp/json-rpc-connection.ts +11 -6
  252. package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
  253. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  254. package/packages/lsp-core/src/lsp/manager.ts +138 -12
  255. package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
  256. package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
  257. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  258. package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
  259. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  260. package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
  261. package/packages/lsp-core/src/lsp/timer-provider.ts +13 -0
  262. package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
  263. package/packages/lsp-core/src/lsp/transport.ts +16 -2
  264. package/packages/lsp-core/src/lsp/types.ts +8 -0
  265. package/packages/lsp-core/src/lsp/workspace-apply-edit-test-support.ts +29 -1
  266. package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +84 -1
  267. package/packages/lsp-core/src/lsp/workspace-document-state.ts +30 -11
  268. package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
  269. package/packages/lsp-core/src/mcp.ts +3 -0
  270. package/packages/lsp-core/src/request-context.test.ts +29 -0
  271. package/packages/lsp-core/src/request-context.ts +1 -1
  272. package/packages/lsp-core/src/tool-surface.test.ts +13 -1
  273. package/packages/lsp-core/src/tools/definitions.ts +14 -0
  274. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  275. package/packages/lsp-core/src/tools/format.ts +56 -0
  276. package/packages/lsp-core/src/tools/index.ts +1 -0
  277. package/packages/lsp-core/src/tools/parameters.test.ts +51 -0
  278. package/packages/lsp-core/src/tools/types.ts +10 -0
  279. package/packages/lsp-daemon/dist/cli.js +902 -479
  280. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  281. package/packages/lsp-daemon/dist/client.js +920 -493
  282. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  283. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  284. package/packages/lsp-daemon/dist/ensure-daemon.d.ts +6 -1
  285. package/packages/lsp-daemon/dist/ensure-daemon.js +10 -2
  286. package/packages/lsp-daemon/dist/index.js +824 -402
  287. package/packages/lsp-daemon/dist/ownership.js +2 -2
  288. package/packages/lsp-daemon/dist/proxy.js +3 -0
  289. package/packages/lsp-daemon/dist/version-reap.js +1 -1
  290. package/packages/lsp-daemon/package.json +1 -1
  291. package/packages/lsp-tools-mcp/dist/cli.js +762 -341
  292. package/packages/lsp-tools-mcp/dist/lsp/manager.js +272 -138
  293. package/packages/lsp-tools-mcp/dist/mcp.js +787 -368
  294. package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
  295. package/packages/lsp-tools-mcp/dist/tools.js +717 -302
  296. package/packages/lsp-tools-mcp/package.json +1 -1
  297. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -21
  298. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -6
  299. package/packages/omo-codex/plugin/.mcp.json +0 -6
  300. package/packages/omo-codex/plugin/AGENTS.md +47 -0
  301. package/packages/omo-codex/plugin/README.md +6 -2
  302. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +197 -148
  303. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  304. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  305. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
  306. package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
  307. package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
  308. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
  309. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  310. package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
  311. package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
  312. package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
  313. package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
  314. package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
  315. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
  316. package/packages/omo-codex/plugin/components/git-bash/dist/cli.js +1 -1
  317. package/packages/omo-codex/plugin/components/git-bash/dist/codex-hook.js +2 -1
  318. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  319. package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
  320. package/packages/omo-codex/plugin/components/git-bash/src/codex-hook.ts +2 -1
  321. package/packages/omo-codex/plugin/components/git-bash/test/codex-hook.test.ts +6 -7
  322. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/AGENTS.md +2 -2
  323. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
  324. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/directive.md +2 -0
  325. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +36 -29
  326. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +32 -26
  327. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/types.d.ts +3 -0
  328. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  329. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
  330. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +32 -28
  331. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/types.ts +3 -0
  332. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/cli.test.ts +1 -1
  333. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +137 -28
  334. package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +4 -2
  335. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
  336. package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
  337. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
  338. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +941 -540
  339. package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
  340. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  341. package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
  342. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  343. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
  344. package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
  345. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
  346. package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
  347. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
  348. package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
  349. package/packages/omo-codex/plugin/components/rules/README.md +2 -0
  350. package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
  351. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +123 -0
  352. package/packages/omo-codex/plugin/components/rules/dist/cli.js +91 -68
  353. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  354. package/packages/omo-codex/plugin/components/rules/package.json +7 -7
  355. package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
  356. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
  357. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +15 -5
  358. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
  359. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
  360. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  361. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
  362. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  363. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  364. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  365. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  366. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  367. package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
  368. package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
  369. package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
  370. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
  371. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +38 -3
  372. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  373. package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
  374. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
  375. package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
  376. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +29 -6
  377. package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
  378. package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
  379. package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
  380. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
  381. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  382. package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
  383. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +4 -10
  384. package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
  385. package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
  386. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2407 -684
  387. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2411 -689
  388. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  389. package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
  390. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
  391. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
  392. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
  393. package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
  394. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +10 -4
  395. package/packages/omo-codex/plugin/components/ultrawork/README.md +2 -0
  396. package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +1 -1
  397. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +1 -1
  398. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
  399. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  400. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
  401. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  402. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-low.toml +1 -1
  403. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +1 -1
  404. package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +1 -1
  405. package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +1 -1
  406. package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +1 -1
  407. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  408. package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
  409. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +490 -4
  410. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  411. package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -6
  412. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +30 -14
  413. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -7
  414. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
  415. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  416. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
  417. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +4 -0
  418. package/packages/omo-codex/plugin/components/ultrawork/src/directive.ts +5 -2
  419. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
  420. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  421. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +14 -8
  422. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +12 -1
  423. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  424. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +4 -4
  425. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  426. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +6 -6
  427. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
  428. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +10 -10
  429. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +16 -16
  430. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +16 -0
  431. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
  432. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  433. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  434. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +4 -4
  435. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  436. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  437. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +1 -1
  438. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  439. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +4 -11
  440. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +24 -22
  441. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +19 -0
  442. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
  443. package/packages/omo-codex/plugin/components/ulw-loop/README.md +12 -1
  444. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
  445. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +26 -13
  446. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +16 -0
  447. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +25 -0
  448. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +10 -4
  449. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +2 -5
  450. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +5 -78
  451. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.d.ts +12 -0
  452. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +114 -0
  453. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.d.ts +7 -1
  454. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +50 -42
  455. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +2 -2
  456. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +21 -8
  457. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  458. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +12 -1
  459. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +1 -1
  460. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +40 -37
  461. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +1396 -516
  462. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
  463. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +28 -8
  464. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.d.ts +2 -5
  465. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +24 -20
  466. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -0
  467. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +1 -0
  468. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +17 -9
  469. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.d.ts +1 -0
  470. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +13 -4
  471. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  472. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +34 -4
  473. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.d.ts +14 -0
  474. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-missing-recovery.js +29 -0
  475. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +7 -0
  476. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +9 -0
  477. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.d.ts +12 -0
  478. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +104 -0
  479. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
  480. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +65 -9
  481. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -1
  482. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
  483. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +72 -117
  484. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.d.ts +2 -0
  485. package/packages/omo-codex/plugin/components/ulw-loop/dist/review-blockers.js +16 -7
  486. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.d.ts +2 -0
  487. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/factory.js +125 -0
  488. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.d.ts +46 -0
  489. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/manifest.js +28 -0
  490. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.d.ts +127 -0
  491. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk/types.js +1 -0
  492. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk.d.ts +3 -0
  493. package/packages/omo-codex/plugin/components/ulw-loop/dist/sdk.js +3 -0
  494. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.d.ts +6 -1
  495. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +195 -29
  496. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.d.ts +9 -0
  497. package/packages/omo-codex/plugin/components/ulw-loop/dist/state-lock.js +227 -0
  498. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.d.ts +6 -0
  499. package/packages/omo-codex/plugin/components/ulw-loop/dist/status-next-actions.js +33 -0
  500. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +20 -6
  501. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +19 -0
  502. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +75 -0
  503. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +17 -4
  504. package/packages/omo-codex/plugin/components/ulw-loop/package.json +6 -6
  505. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +10 -4
  506. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  507. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +32 -8
  508. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +40 -0
  509. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +8 -6
  510. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +5 -98
  511. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +134 -0
  512. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +52 -73
  513. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +10 -4
  514. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +24 -8
  515. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +14 -1
  516. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +52 -46
  517. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +8 -6
  518. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +35 -7
  519. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +34 -28
  520. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
  521. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +1 -0
  522. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +19 -9
  523. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +25 -4
  524. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +39 -4
  525. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-missing-recovery.ts +38 -0
  526. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +11 -0
  527. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +123 -0
  528. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +71 -15
  529. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
  530. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +92 -136
  531. package/packages/omo-codex/plugin/components/ulw-loop/src/review-blockers.ts +29 -8
  532. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/factory.ts +159 -0
  533. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/manifest.ts +42 -0
  534. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk/types.ts +140 -0
  535. package/packages/omo-codex/plugin/components/ulw-loop/src/sdk.ts +3 -0
  536. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +205 -28
  537. package/packages/omo-codex/plugin/components/ulw-loop/src/state-lock.ts +239 -0
  538. package/packages/omo-codex/plugin/components/ulw-loop/src/status-next-actions.ts +36 -0
  539. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +19 -6
  540. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +107 -0
  541. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  542. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +131 -82
  543. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +147 -0
  544. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint.test.ts +16 -22
  545. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +4 -2
  546. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint.test.ts +31 -2
  547. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-commands.test.ts +2 -0
  548. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-complete-goals.test.ts +3 -1
  549. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +35 -8
  550. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +38 -4
  551. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-json-errors.test.ts +27 -0
  552. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-scope-required.test.ts +144 -0
  553. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-status-next-actions.test.ts +185 -0
  554. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +8 -3
  555. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +6 -0
  556. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +37 -2
  557. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +52 -11
  558. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  559. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/cli-session.ts +4 -0
  560. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +9 -4
  561. package/packages/omo-codex/plugin/components/ulw-loop/test/guided-recovery.test.ts +67 -0
  562. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
  563. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
  564. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io-cross-process.test.ts +106 -0
  565. package/packages/omo-codex/plugin/components/ulw-loop/test/plan-io.test.ts +36 -2
  566. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
  567. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
  568. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-fields-messages.test.ts +98 -0
  569. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-lazycodex-surface.test.ts +93 -0
  570. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
  571. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +51 -2
  572. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-senpi-surface.test.ts +131 -0
  573. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -0
  574. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate.test.ts +58 -3
  575. package/packages/omo-codex/plugin/components/ulw-loop/test/review-blockers.test.ts +9 -7
  576. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-contract.test.ts +137 -0
  577. package/packages/omo-codex/plugin/components/ulw-loop/test/sdk-session-context.test.ts +148 -0
  578. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +444 -7
  579. package/packages/omo-codex/plugin/components/ulw-loop/test/state-lock.test.ts +218 -0
  580. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
  581. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  582. package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
  583. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +13 -8
  584. package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
  585. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  586. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  587. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  588. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  589. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  590. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  591. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  592. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +18 -0
  593. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  594. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  595. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  596. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  597. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  598. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  599. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  600. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  601. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  602. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  603. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  604. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  605. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  606. package/packages/omo-codex/plugin/model-catalog.json +16 -7
  607. package/packages/omo-codex/plugin/package-lock.json +676 -524
  608. package/packages/omo-codex/plugin/package.json +2 -3
  609. package/packages/omo-codex/plugin/scripts/AGENTS.md +39 -0
  610. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -2
  611. package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
  612. package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
  613. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
  614. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +16 -7
  615. package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +8 -4
  616. package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +19 -90
  617. package/packages/omo-codex/plugin/scripts/migrate-codex-config/toml-section-editor.mjs +1 -1
  618. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +94 -55
  619. package/packages/omo-codex/plugin/shared/package.json +3 -4
  620. package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
  621. package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
  622. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
  623. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
  624. package/packages/omo-codex/plugin/skills/ast-grep/SKILL.md +1 -1
  625. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
  626. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +1 -1
  627. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  628. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  629. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  630. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  631. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  632. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  633. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  634. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  635. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +3 -1
  636. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  637. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  638. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  639. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  640. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  641. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  642. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  643. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  644. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  645. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  646. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  647. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +10 -0
  648. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +15 -8
  649. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +10 -2
  650. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +2 -0
  651. package/packages/omo-codex/plugin/skills/frontend/references/design/ambience-skill.md +145 -0
  652. package/packages/omo-codex/plugin/skills/frontend/references/design/interaction-skill.md +2 -0
  653. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  654. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  655. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  656. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  657. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  658. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  659. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  660. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  661. package/packages/omo-codex/plugin/skills/git-master/SKILL.md +1 -1
  662. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +18 -16
  663. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +4 -2
  664. package/packages/omo-codex/plugin/skills/lsp-setup/SKILL.md +1 -1
  665. package/packages/omo-codex/plugin/skills/programming/SKILL.md +1 -1
  666. package/packages/omo-codex/plugin/skills/refactor/SKILL.md +8 -6
  667. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +5 -3
  668. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +114 -422
  669. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  670. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +26 -9
  671. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  672. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  673. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  674. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  675. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +26 -13
  676. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +29 -31
  677. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  678. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +34 -4
  679. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  680. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +32 -8
  681. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -7
  682. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  683. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  684. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  685. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +12 -5
  686. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  687. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +8 -5
  688. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  689. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  690. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +16 -51
  691. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +2 -3
  692. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
  693. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +14 -4
  694. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  695. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  696. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  697. package/packages/omo-codex/plugin/test/auto-update.test.mjs +4 -29
  698. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
  699. package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
  700. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  701. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -51
  702. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +88 -2
  703. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +5 -6
  704. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  705. package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
  706. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +35 -35
  707. package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +1 -1
  708. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  709. package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +107 -15
  710. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +168 -0
  711. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +54 -24
  712. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +18 -119
  713. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  714. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  715. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  716. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  717. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  718. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +5 -5
  719. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  720. package/packages/omo-codex/scripts/AGENTS.md +36 -0
  721. package/packages/omo-codex/scripts/check-model-catalog-parity.mjs +42 -0
  722. package/packages/omo-codex/scripts/install-cache-copy.test.mjs +27 -1
  723. package/packages/omo-codex/scripts/install-config-autonomous-features.test.mjs +1 -1
  724. package/packages/omo-codex/scripts/install-config-autonomous.test.mjs +2 -1
  725. package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +0 -23
  726. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +5 -5
  727. package/packages/omo-codex/scripts/install-config.test.mjs +15 -17
  728. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2987 -1370
  729. package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +3 -4
  730. package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +1 -25
  731. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  732. package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +0 -36
  733. package/packages/omo-codex/scripts/install-packaged-local.test.mjs +1 -6
  734. package/packages/{omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md → prompts-core/prompts/ultrawork/codex.md} +26 -20
  735. package/packages/shared-skills/package.json +7 -1
  736. package/packages/shared-skills/skill-source-filter.d.ts +16 -0
  737. package/packages/shared-skills/skill-source-filter.mjs +44 -0
  738. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  739. package/packages/shared-skills/skills/ast-grep/SKILL.md +1 -1
  740. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  741. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +1 -1
  742. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  743. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  744. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  745. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  746. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  747. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  748. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  749. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  750. package/packages/shared-skills/skills/debugging/SKILL.md +3 -1
  751. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  752. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  753. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  754. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  755. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  756. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  757. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  758. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  759. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  760. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  761. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  762. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  763. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +10 -0
  764. package/packages/shared-skills/skills/frontend/SKILL.md +15 -8
  765. package/packages/shared-skills/skills/frontend/references/design/README.md +10 -2
  766. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +2 -0
  767. package/packages/shared-skills/skills/frontend/references/design/ambience-skill.md +145 -0
  768. package/packages/shared-skills/skills/frontend/references/design/interaction-skill.md +2 -0
  769. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  770. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  771. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  772. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  773. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  774. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  775. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  776. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  777. package/packages/shared-skills/skills/git-master/SKILL.md +1 -1
  778. package/packages/shared-skills/skills/init-deep/SKILL.md +14 -14
  779. package/packages/shared-skills/skills/lsp-setup/SKILL.md +1 -1
  780. package/packages/shared-skills/skills/programming/SKILL.md +1 -1
  781. package/packages/shared-skills/skills/refactor/SKILL.md +4 -4
  782. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +1 -1
  783. package/packages/shared-skills/skills/review-work/SKILL.md +101 -419
  784. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +38 -11
  785. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +26 -9
  786. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +110 -0
  787. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  788. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +23 -18
  789. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +9 -2
  790. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +20 -19
  791. package/packages/shared-skills/skills/ulw-plan/SKILL.md +7 -8
  792. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  793. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  794. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  795. package/packages/shared-skills/skills/ulw-plan/scripts/scaffold-plan.mjs +1 -1
  796. package/packages/shared-skills/skills/ulw-research/SKILL.md +8 -3
  797. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  798. package/packages/shared-skills/skills/visual-qa/SKILL.md +4 -3
  799. package/postinstall.mjs +2 -0
  800. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  801. package/script/qa/xterm-live-terminal.mjs +18 -2
  802. package/dist/config/schema/codegraph.d.ts +0 -12
  803. package/dist/config/schema/start-work.d.ts +0 -5
  804. package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
  805. package/dist/features/builtin-skills/index.d.ts +0 -1
  806. package/dist/features/builtin-skills/skill-file-loader.d.ts +0 -1
  807. package/dist/features/builtin-skills/skills/agent-browser-skill.d.ts +0 -1
  808. package/dist/features/builtin-skills/skills/agent-browser-template.d.ts +0 -1
  809. package/dist/features/builtin-skills/skills/debugging.d.ts +0 -1
  810. package/dist/features/builtin-skills/skills/dev-browser.d.ts +0 -1
  811. package/dist/features/builtin-skills/skills/frontend.d.ts +0 -1
  812. package/dist/features/builtin-skills/skills/git-master-sections/commit-atomic-planning.d.ts +0 -1
  813. package/dist/features/builtin-skills/skills/git-master-sections/commit-context-analysis.d.ts +0 -1
  814. package/dist/features/builtin-skills/skills/git-master-sections/commit-execution-verification.d.ts +0 -1
  815. package/dist/features/builtin-skills/skills/git-master-sections/commit-workflow.d.ts +0 -1
  816. package/dist/features/builtin-skills/skills/git-master-sections/history-search-workflow.d.ts +0 -1
  817. package/dist/features/builtin-skills/skills/git-master-sections/overview.d.ts +0 -1
  818. package/dist/features/builtin-skills/skills/git-master-sections/quick-reference.d.ts +0 -1
  819. package/dist/features/builtin-skills/skills/git-master-sections/rebase-workflow.d.ts +0 -1
  820. package/dist/features/builtin-skills/skills/git-master-skill-metadata.d.ts +0 -1
  821. package/dist/features/builtin-skills/skills/git-master.d.ts +0 -1
  822. package/dist/features/builtin-skills/skills/index.d.ts +0 -1
  823. package/dist/features/builtin-skills/skills/init-deep.d.ts +0 -1
  824. package/dist/features/builtin-skills/skills/playwright-cli.d.ts +0 -1
  825. package/dist/features/builtin-skills/skills/playwright-mcp-skill.d.ts +0 -1
  826. package/dist/features/builtin-skills/skills/playwright.d.ts +0 -1
  827. package/dist/features/builtin-skills/skills/remove-ai-slops.d.ts +0 -1
  828. package/dist/features/builtin-skills/skills/review-work.d.ts +0 -1
  829. package/dist/features/builtin-skills/skills/security-research.d.ts +0 -1
  830. package/dist/features/builtin-skills/skills/security-review.d.ts +0 -1
  831. package/dist/features/builtin-skills/skills/team-mode.d.ts +0 -1
  832. package/dist/features/builtin-skills/skills/visual-qa.d.ts +0 -1
  833. package/dist/features/builtin-skills/skills.d.ts +0 -1
  834. package/dist/features/builtin-skills/types.d.ts +0 -1
  835. package/dist/features/claude-code-plugin-loader/agent-loader.d.ts +0 -1
  836. package/dist/features/claude-code-plugin-loader/command-loader.d.ts +0 -1
  837. package/dist/features/claude-code-plugin-loader/discovery-core.d.ts +0 -1
  838. package/dist/features/claude-code-plugin-loader/discovery-paths.d.ts +0 -1
  839. package/dist/features/claude-code-plugin-loader/discovery.d.ts +0 -1
  840. package/dist/features/claude-code-plugin-loader/hook-loader.d.ts +0 -1
  841. package/dist/features/claude-code-plugin-loader/index.d.ts +0 -1
  842. package/dist/features/claude-code-plugin-loader/install-path-resolver.d.ts +0 -1
  843. package/dist/features/claude-code-plugin-loader/installed-plugin-database.d.ts +0 -1
  844. package/dist/features/claude-code-plugin-loader/loaded-plugin.d.ts +0 -1
  845. package/dist/features/claude-code-plugin-loader/loader.d.ts +0 -1
  846. package/dist/features/claude-code-plugin-loader/mcp-server-loader.d.ts +0 -1
  847. package/dist/features/claude-code-plugin-loader/plugin-key.d.ts +0 -1
  848. package/dist/features/claude-code-plugin-loader/plugin-manifest.d.ts +0 -1
  849. package/dist/features/claude-code-plugin-loader/plugin-path-resolver.d.ts +0 -1
  850. package/dist/features/claude-code-plugin-loader/plugin-settings.d.ts +0 -1
  851. package/dist/features/claude-code-plugin-loader/scope-filter.d.ts +0 -1
  852. package/dist/features/claude-code-plugin-loader/skill-loader.d.ts +0 -1
  853. package/dist/features/claude-code-plugin-loader/types.d.ts +0 -1
  854. package/dist/hooks/codegraph-bootstrap/command-runner.d.ts +0 -17
  855. package/dist/hooks/codegraph-bootstrap/hook.d.ts +0 -35
  856. package/dist/hooks/codegraph-bootstrap/index.d.ts +0 -1
  857. package/dist/hooks/codegraph-bootstrap/project-root.d.ts +0 -1
  858. package/dist/hooks/codegraph-bootstrap/status.d.ts +0 -11
  859. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
  860. package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
  861. package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
  862. package/dist/mcp/codegraph.d.ts +0 -16
  863. package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
  864. package/dist/shared/prompt-async-gate/message-inspection-error.d.ts +0 -1
  865. package/dist/shared/prompt-async-gate/pending-tool-turn.d.ts +0 -1
  866. package/dist/shared/prompt-async-gate/prompt-message-state.d.ts +0 -1
  867. package/dist/shared/prompt-async-gate/queue.d.ts +0 -1
  868. package/dist/shared/prompt-async-gate/recent-dispatches.d.ts +0 -1
  869. package/dist/shared/prompt-async-gate/reservations.d.ts +0 -1
  870. package/dist/shared/prompt-async-gate/semantic-dedupe.d.ts +0 -1
  871. package/dist/shared/prompt-async-gate/session-idle-dispatch.d.ts +0 -1
  872. package/dist/shared/prompt-async-gate/timing.d.ts +0 -1
  873. package/dist/shared/prompt-async-gate/types.d.ts +0 -1
  874. package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
  875. package/dist/skills/data-scientist/references/execution-templates.md +0 -197
  876. package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
  877. package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
  878. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  879. package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
  880. package/dist/tools/delegate-task/anthropic-categories.d.ts +0 -2
  881. package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
  882. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  883. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  884. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  885. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  886. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  887. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
  888. package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
  889. package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
  890. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12149
  891. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9747
  892. package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
  893. package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
  894. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
  895. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
  896. package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
  897. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
  898. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
  899. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -309
  900. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -80
  901. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
  902. package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
  903. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
  904. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
  905. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
  906. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -21
  907. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
  908. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
  909. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
  910. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
  911. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
  912. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
  913. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
  914. package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
  915. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
  916. package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
  917. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
  918. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
  919. package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
  920. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
  921. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
  922. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
  923. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
  924. package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
  925. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
  926. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
  927. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
  928. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
  929. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
  930. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
  931. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
  932. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
  933. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
  934. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
  935. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
  936. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
  937. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
  938. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
  939. package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
  940. package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
  941. package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
  942. package/packages/omo-codex/plugin/components/start-work-continuation/LICENSE +0 -21
  943. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  944. package/packages/omo-codex/plugin/components/ultrawork/directive.md +0 -471
  945. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
  946. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
  947. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  948. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  949. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
  950. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
  951. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
  952. package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
  953. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  954. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  955. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  956. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  957. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  958. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  959. package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
  960. package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
  961. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  962. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  963. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  964. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  965. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  966. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  967. /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
  968. /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
  969. /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
  970. /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
  971. /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
  972. /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
  973. /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
  974. /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
  975. /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
  976. /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
  977. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  978. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  979. /package/packages/omo-codex/plugin/components/{codegraph → ulw-execute-continuation}/LICENSE +0 -0
  980. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  981. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  982. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  983. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  984. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  985. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  986. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  987. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  988. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  989. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  990. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/cli.ts
4
+ import { argv, stderr } from "node:process";
5
+
3
6
  // ../lsp-core/src/lsp/cleanup-errors.ts
4
7
  function writeCleanupError(message) {
5
8
  process.stderr.write(`${message}
@@ -17,6 +20,13 @@ import { pathToFileURL as pathToFileURL3 } from "node:url";
17
20
  // ../lsp-core/src/lsp/connection.ts
18
21
  import { pathToFileURL } from "node:url";
19
22
 
23
+ // ../lsp-core/src/lsp/timer-provider.ts
24
+ var realTimerProvider = {
25
+ now: () => Date.now(),
26
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
27
+ clearTimeout: (handle) => clearTimeout(handle)
28
+ };
29
+
20
30
  // ../lsp-core/src/lsp/constants.ts
21
31
  var DEFAULT_MAX_REFERENCES = 200;
22
32
  var DEFAULT_MAX_SYMBOLS = 200;
@@ -25,28 +35,24 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
25
35
  var REQUEST_TIMEOUT_MS = 15000;
26
36
  var INIT_TIMEOUT_MS = 60000;
27
37
  var IDLE_TIMEOUT_MS = 5 * 60000;
38
+ var MAX_RESIDENT_CLIENTS = 6;
28
39
  var REAPER_INTERVAL_MS = 60000;
29
40
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
30
41
  var STOP_SIGKILL_GRACE_MS = 1000;
42
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
43
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
31
44
 
32
45
  // ../lsp-core/src/lsp/errors.ts
33
46
  class LspConnectionClosedError extends Error {
34
- serverId;
35
- root;
36
- name = "LspConnectionClosedError";
37
47
  constructor(serverId, root, message) {
38
48
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
39
49
  this.serverId = serverId;
40
50
  this.root = root;
51
+ this.name = "LspConnectionClosedError";
41
52
  }
42
53
  }
43
54
 
44
55
  class LspProcessExitedError extends Error {
45
- serverId;
46
- root;
47
- exitCode;
48
- stderrTail;
49
- name = "LspProcessExitedError";
50
56
  constructor(serverId, root, exitCode, stderrTail) {
51
57
  const stderrSuffix = stderrTail ? `
52
58
  stderr tail: ${stderrTail}` : "";
@@ -55,46 +61,59 @@ stderr tail: ${stderrTail}` : "";
55
61
  this.root = root;
56
62
  this.exitCode = exitCode;
57
63
  this.stderrTail = stderrTail;
64
+ this.name = "LspProcessExitedError";
58
65
  }
59
66
  }
60
67
 
61
68
  class LspRequestTimeoutError extends Error {
62
- method;
63
- stderrTail;
64
- name = "LspRequestTimeoutError";
65
69
  constructor(method, stderrTail) {
66
70
  const stderrSuffix = stderrTail ? `
67
71
  recent stderr: ${stderrTail}` : "";
68
72
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
69
73
  this.method = method;
70
74
  this.stderrTail = stderrTail;
75
+ this.name = "LspRequestTimeoutError";
71
76
  }
72
77
  }
73
78
 
74
79
  class LspInvalidPathError extends Error {
75
- name = "LspInvalidPathError";
80
+ constructor() {
81
+ super(...arguments);
82
+ this.name = "LspInvalidPathError";
83
+ }
76
84
  }
77
85
 
78
86
  class LspServerLookupError extends Error {
79
- lookup;
80
- name = "LspServerLookupError";
81
87
  constructor(message, lookup) {
82
88
  super(message);
83
89
  this.lookup = lookup;
90
+ this.name = "LspServerLookupError";
84
91
  }
85
92
  }
86
93
 
87
94
  class LspServerInitializingError extends Error {
88
- originalError;
89
- name = "LspServerInitializingError";
90
95
  constructor(originalError) {
91
96
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
92
97
  this.originalError = originalError;
98
+ this.name = "LspServerInitializingError";
93
99
  }
94
100
  }
95
101
 
96
102
  class LspProcessSpawnError extends Error {
97
- name = "LspProcessSpawnError";
103
+ constructor() {
104
+ super(...arguments);
105
+ this.name = "LspProcessSpawnError";
106
+ }
107
+ }
108
+
109
+ class LspClientRespawnBudgetExceededError extends Error {
110
+ constructor(serverId, root, retryLimit) {
111
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
112
+ this.serverId = serverId;
113
+ this.root = root;
114
+ this.retryLimit = retryLimit;
115
+ this.name = "LspClientRespawnBudgetExceededError";
116
+ }
98
117
  }
99
118
  function isLspDeadConnectionError(err) {
100
119
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -110,20 +129,31 @@ var METHOD_NOT_FOUND = -32601;
110
129
  var INTERNAL_ERROR = -32603;
111
130
 
112
131
  class JsonRpcConnection {
113
- reader;
114
- writer;
115
- pendingRequests = new Map;
116
- notificationHandlers = new Map;
117
- requestHandlers = new Map;
118
- closeHandlers = [];
119
- errorHandlers = [];
120
- inputBuffer = Buffer.alloc(0);
121
- nextRequestId = 1;
122
- listening = false;
123
- disposed = false;
124
132
  constructor(reader, writer) {
125
133
  this.reader = reader;
126
134
  this.writer = writer;
135
+ this.pendingRequests = new Map;
136
+ this.notificationHandlers = new Map;
137
+ this.requestHandlers = new Map;
138
+ this.closeHandlers = [];
139
+ this.errorHandlers = [];
140
+ this.inputBuffer = Buffer.alloc(0);
141
+ this.nextRequestId = 1;
142
+ this.listening = false;
143
+ this.disposed = false;
144
+ this.handleData = (chunk) => {
145
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
146
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
147
+ this.drainInputBuffer();
148
+ };
149
+ this.handleClose = () => {
150
+ for (const handler of this.closeHandlers) {
151
+ handler();
152
+ }
153
+ };
154
+ this.handleStreamError = (error) => {
155
+ this.emitError(error);
156
+ };
127
157
  }
128
158
  listen() {
129
159
  if (this.listening)
@@ -158,6 +188,7 @@ class JsonRpcConnection {
158
188
  let cancelAfterWrite = false;
159
189
  let settled = false;
160
190
  const writeCancel = () => this.writeMessage({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id } });
191
+ let rejectAfterCancelWrite;
161
192
  const responsePromise = new Promise((resolve, reject) => {
162
193
  const cleanup = () => {
163
194
  options.signal?.removeEventListener("abort", onAbort);
@@ -169,15 +200,19 @@ class JsonRpcConnection {
169
200
  this.pendingRequests.delete(key);
170
201
  cleanup();
171
202
  const rejectCancelled = () => reject(abortError(options.signal));
203
+ rejectAfterCancelWrite = async () => {
204
+ try {
205
+ await writeCancel();
206
+ } catch (error) {
207
+ this.emitError(toError(error));
208
+ }
209
+ rejectCancelled();
210
+ };
172
211
  if (!requestWritten) {
173
212
  cancelAfterWrite = true;
174
- rejectCancelled();
175
213
  return;
176
214
  }
177
- writeCancel().then(rejectCancelled, (error) => {
178
- this.emitError(toError(error));
179
- rejectCancelled();
180
- });
215
+ rejectAfterCancelWrite();
181
216
  };
182
217
  const onAbort = () => settleCancel();
183
218
  this.pendingRequests.set(key, {
@@ -205,7 +240,7 @@ class JsonRpcConnection {
205
240
  await this.writeMessage(message);
206
241
  requestWritten = true;
207
242
  if (cancelAfterWrite)
208
- await writeCancel();
243
+ await rejectAfterCancelWrite?.();
209
244
  } catch (error) {
210
245
  if (settled)
211
246
  return responsePromise;
@@ -244,19 +279,6 @@ class JsonRpcConnection {
244
279
  this.notificationHandlers.clear();
245
280
  this.requestHandlers.clear();
246
281
  }
247
- handleData = (chunk) => {
248
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
249
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
250
- this.drainInputBuffer();
251
- };
252
- handleClose = () => {
253
- for (const handler of this.closeHandlers) {
254
- handler();
255
- }
256
- };
257
- handleStreamError = (error) => {
258
- this.emitError(error);
259
- };
260
282
  drainInputBuffer() {
261
283
  while (true) {
262
284
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR);
@@ -604,33 +626,29 @@ function isPosition(value) {
604
626
 
605
627
  // ../lsp-core/src/lsp/transport.ts
606
628
  class LspClientNotStartedError extends Error {
607
- serverId;
608
- root;
609
- name = "LspClientNotStartedError";
610
629
  constructor(serverId, root) {
611
630
  super("LSP client not started");
612
631
  this.serverId = serverId;
613
632
  this.root = root;
633
+ this.name = "LspClientNotStartedError";
614
634
  }
615
635
  }
616
636
 
617
637
  class LspClientTransport {
618
- root;
619
- server;
620
- proc = null;
621
- connection = null;
622
- stderrBuffer = [];
623
- processExited = false;
624
- diagnosticsStore = new Map;
625
- requestTimeoutMs;
626
- initializeTimeoutMs;
627
- workspaceApplyEditHandler = null;
628
- diagnosticPullSupported = false;
629
638
  constructor(root, server, timeouts = {}) {
630
639
  this.root = root;
631
640
  this.server = server;
641
+ this.proc = null;
642
+ this.connection = null;
643
+ this.stderrBuffer = [];
644
+ this.processExited = false;
645
+ this.diagnosticsStore = new Map;
646
+ this.workspaceApplyEditHandler = null;
647
+ this.diagnosticPullSupported = false;
648
+ this.documentFormattingSupported = false;
632
649
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
633
650
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
651
+ this.timerProvider = timeouts.timerProvider ?? realTimerProvider;
634
652
  }
635
653
  pid() {
636
654
  return this.proc?.pid;
@@ -650,6 +668,12 @@ class LspClientTransport {
650
668
  isDiagnosticPullSupported() {
651
669
  return this.diagnosticPullSupported;
652
670
  }
671
+ setDocumentFormattingSupported(supported) {
672
+ this.documentFormattingSupported = supported;
673
+ }
674
+ isDocumentFormattingSupported() {
675
+ return this.documentFormattingSupported;
676
+ }
653
677
  handlePublishDiagnostics(params) {
654
678
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
655
679
  }
@@ -725,7 +749,7 @@ class LspClientTransport {
725
749
  const options = args[1];
726
750
  const timeoutMs = options?.timeoutMs ?? this.requestTimeoutMs;
727
751
  const timeoutController = new AbortController;
728
- const timeoutHandle = setTimeout(() => {
752
+ const timeoutHandle = this.timerProvider.setTimeout(() => {
729
753
  const stderrTail = this.stderrBuffer.slice(-5).join(`
730
754
  `);
731
755
  timeoutController.abort(new LspRequestTimeoutError(method, stderrTail || undefined));
@@ -744,7 +768,7 @@ class LspClientTransport {
744
768
  }
745
769
  throw error;
746
770
  } finally {
747
- clearTimeout(timeoutHandle);
771
+ this.timerProvider.clearTimeout(timeoutHandle);
748
772
  combinedSignal.dispose();
749
773
  }
750
774
  }
@@ -863,6 +887,14 @@ function supportsDiagnosticPull(capabilities) {
863
887
  return false;
864
888
  return Object.hasOwn(capabilities, "diagnosticProvider");
865
889
  }
890
+ function supportsDocumentFormatting(capabilities) {
891
+ if (capabilities === undefined)
892
+ return false;
893
+ const provider = capabilities.documentFormattingProvider;
894
+ if (provider === undefined || provider === null || provider === false)
895
+ return false;
896
+ return provider === true || typeof provider === "object";
897
+ }
866
898
 
867
899
  class LspClientConnection extends LspClientTransport {
868
900
  async initialize() {
@@ -879,6 +911,7 @@ class LspClientConnection extends LspClientTransport {
879
911
  references: {},
880
912
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
881
913
  publishDiagnostics: {},
914
+ formatting: { dynamicRegistration: false },
882
915
  rename: {
883
916
  prepareSupport: true,
884
917
  prepareSupportDefaultBehavior: 1
@@ -920,6 +953,7 @@ class LspClientConnection extends LspClientTransport {
920
953
  initializationOptions: this.server.initialization
921
954
  }, { timeoutMs: this.initializeTimeoutMs });
922
955
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
956
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
923
957
  await this.sendNotification("initialized", {});
924
958
  await this.sendNotification("workspace/didChangeConfiguration", {
925
959
  settings: { json: { validate: { enable: true } } }
@@ -1125,6 +1159,17 @@ function canonicalPath(filePath) {
1125
1159
  return absolute;
1126
1160
  }
1127
1161
  }
1162
+ function normalizeDocumentUri(uri) {
1163
+ let decoded = uri;
1164
+ try {
1165
+ decoded = decodeURIComponent(uri);
1166
+ } catch {
1167
+ decoded = uri;
1168
+ }
1169
+ if (process.platform !== "win32")
1170
+ return decoded;
1171
+ return decoded.replace(/^(file:\/\/\/)([a-z]):/, (_match, prefix, drive) => `${prefix}${drive.toUpperCase()}:`);
1172
+ }
1128
1173
  function isSameOrDescendant(candidate, parent) {
1129
1174
  const suffix = relative(parent, candidate);
1130
1175
  return suffix === "" || !suffix.startsWith("..") && suffix !== "..";
@@ -1135,17 +1180,18 @@ function movedPath(candidate, oldPath, newPath) {
1135
1180
  }
1136
1181
 
1137
1182
  class WorkspaceDocumentState {
1138
- sendNotification;
1139
- clearDiagnostics;
1140
- openDocuments = new Map;
1141
- openByUri = new Map;
1142
- openPromises = new Map;
1143
- now;
1144
- versionlessPublishQuiescenceMs;
1145
1183
  constructor(sendNotification, clearDiagnostics, options = {}) {
1146
1184
  this.sendNotification = sendNotification;
1147
1185
  this.clearDiagnostics = clearDiagnostics;
1148
- this.now = options.now ?? (() => Date.now());
1186
+ this.openDocuments = new Map;
1187
+ this.openByUri = new Map;
1188
+ this.openPromises = new Map;
1189
+ this.timerProvider = options.timerProvider ?? {
1190
+ now: options.now ?? (() => Date.now()),
1191
+ setTimeout: (callback, delayMs) => setTimeout(callback, delayMs),
1192
+ clearTimeout: (handle) => clearTimeout(handle)
1193
+ };
1194
+ this.now = () => this.timerProvider.now();
1149
1195
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1150
1196
  }
1151
1197
  async openFile(filePath) {
@@ -1167,7 +1213,7 @@ class WorkspaceDocumentState {
1167
1213
  return this.openDocuments.get(canonicalPath(filePath))?.version;
1168
1214
  }
1169
1215
  getStoredDiagnostics(uri) {
1170
- const state = this.openByUri.get(uri);
1216
+ const state = this.openByUri.get(normalizeDocumentUri(uri));
1171
1217
  if (!state)
1172
1218
  return [];
1173
1219
  return state.lastPublish?.diagnostics ?? state.pullCache?.diagnostics ?? [];
@@ -1189,13 +1235,13 @@ class WorkspaceDocumentState {
1189
1235
  return state !== undefined && state.uri === snapshot.uri && state.version === snapshot.version && state.generation === snapshot.documentGeneration;
1190
1236
  }
1191
1237
  getPullCache(snapshot) {
1192
- const state = this.openByUri.get(snapshot.uri);
1238
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1193
1239
  if (!state?.pullCache || state.pullCache.documentVersion !== snapshot.version)
1194
1240
  return null;
1195
1241
  return state.pullCache;
1196
1242
  }
1197
1243
  recordPullDiagnostics(snapshot, report) {
1198
- const state = this.openByUri.get(snapshot.uri);
1244
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1199
1245
  if (!state)
1200
1246
  return;
1201
1247
  state.pullCache = {
@@ -1205,7 +1251,7 @@ class WorkspaceDocumentState {
1205
1251
  };
1206
1252
  }
1207
1253
  recordPublishedDiagnostics(params) {
1208
- const state = this.openByUri.get(params.uri);
1254
+ const state = this.openByUri.get(normalizeDocumentUri(params.uri));
1209
1255
  if (!state)
1210
1256
  return;
1211
1257
  state.publishGeneration += 1;
@@ -1219,7 +1265,7 @@ class WorkspaceDocumentState {
1219
1265
  this.notifyWaiters(state);
1220
1266
  }
1221
1267
  resolvePushDiagnostics(snapshot) {
1222
- const state = this.openByUri.get(snapshot.uri);
1268
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1223
1269
  if (!state?.lastPublish)
1224
1270
  return { status: "missing" };
1225
1271
  const publish = state.lastPublish;
@@ -1233,7 +1279,7 @@ class WorkspaceDocumentState {
1233
1279
  return waitMs === 0 ? { status: "ready", diagnostics: publish.diagnostics } : { status: "wait", waitMs };
1234
1280
  }
1235
1281
  waitForDiagnosticsActivity(snapshot, timeoutMs) {
1236
- const state = this.openByUri.get(snapshot.uri);
1282
+ const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
1237
1283
  if (!state || timeoutMs <= 0)
1238
1284
  return Promise.resolve();
1239
1285
  return new Promise((resolveActivity) => {
@@ -1242,11 +1288,11 @@ class WorkspaceDocumentState {
1242
1288
  if (settled)
1243
1289
  return;
1244
1290
  settled = true;
1245
- clearTimeout(timer);
1291
+ this.timerProvider.clearTimeout(timer);
1246
1292
  state.waiters.delete(finish);
1247
1293
  resolveActivity();
1248
1294
  };
1249
- const timer = setTimeout(finish, timeoutMs);
1295
+ const timer = this.timerProvider.setTimeout(finish, timeoutMs);
1250
1296
  if (typeof timer.unref === "function")
1251
1297
  timer.unref();
1252
1298
  state.waiters.add(finish);
@@ -1354,7 +1400,7 @@ class WorkspaceDocumentState {
1354
1400
  waiters: new Set
1355
1401
  };
1356
1402
  this.openDocuments.set(path, state);
1357
- this.openByUri.set(state.uri, state);
1403
+ this.openByUri.set(normalizeDocumentUri(state.uri), state);
1358
1404
  this.notifyWaiters(state);
1359
1405
  await this.sendNotification("textDocument/didOpen", {
1360
1406
  textDocument: { uri: state.uri, languageId: state.languageId, version: state.version, text }
@@ -1379,7 +1425,7 @@ class WorkspaceDocumentState {
1379
1425
  }
1380
1426
  async closeDocument(state) {
1381
1427
  this.openDocuments.delete(state.path);
1382
- this.openByUri.delete(state.uri);
1428
+ this.openByUri.delete(normalizeDocumentUri(state.uri));
1383
1429
  this.clearDiagnostics(state.uri);
1384
1430
  this.notifyWaiters(state);
1385
1431
  await this.sendNotification("textDocument/didClose", { textDocument: { uri: state.uri } });
@@ -1408,13 +1454,11 @@ import { dirname, isAbsolute, relative as relative2, resolve as resolve2 } from
1408
1454
  import { fileURLToPath } from "node:url";
1409
1455
 
1410
1456
  class WorkspaceEditPathError extends Error {
1411
- path;
1412
- detail;
1413
- name = "WorkspaceEditPathError";
1414
1457
  constructor(path, detail) {
1415
1458
  super(`${detail}: ${path}`);
1416
1459
  this.path = path;
1417
1460
  this.detail = detail;
1461
+ this.name = "WorkspaceEditPathError";
1418
1462
  }
1419
1463
  }
1420
1464
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -1706,13 +1750,11 @@ function canonicalFingerprint(operations) {
1706
1750
 
1707
1751
  // ../lsp-core/src/lsp/workspace-edit-types.ts
1708
1752
  class WorkspaceEditValidationError extends Error {
1709
- changeIndex;
1710
- detail;
1711
- name = "WorkspaceEditValidationError";
1712
1753
  constructor(changeIndex, detail) {
1713
1754
  super(`change ${changeIndex}: ${detail}`);
1714
1755
  this.changeIndex = changeIndex;
1715
1756
  this.detail = detail;
1757
+ this.name = "WorkspaceEditValidationError";
1716
1758
  }
1717
1759
  }
1718
1760
 
@@ -1798,14 +1840,14 @@ function parseSinglePathResource(input, kind) {
1798
1840
  return;
1799
1841
  }
1800
1842
  if (kind === "create") {
1801
- const options2 = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
1843
+ const options = parseOptions(change["options"], ["overwrite", "ignoreIfExists"], changeIndex);
1802
1844
  target.operations.push({
1803
1845
  kind,
1804
1846
  changeIndex,
1805
1847
  path: resolvedPath.path,
1806
1848
  reportedPath: resolvedPath.requestedPath,
1807
- overwrite: options2["overwrite"] ?? false,
1808
- ignoreIfExists: options2["ignoreIfExists"] ?? false,
1849
+ overwrite: options["overwrite"] ?? false,
1850
+ ignoreIfExists: options["ignoreIfExists"] ?? false,
1809
1851
  followedSymbolicLink: resolvedPath.followedSymbolicLink
1810
1852
  });
1811
1853
  return;
@@ -2210,10 +2252,9 @@ function simulateDelete(operation, virtual) {
2210
2252
  import { existsSync as existsSync4, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2211
2253
  import { dirname as dirname3, resolve as resolve4 } from "node:path";
2212
2254
  class WorkspaceSnapshotBuilder {
2213
- workspaceRoot;
2214
- snapshots = new Map;
2215
2255
  constructor(workspaceRoot) {
2216
2256
  this.workspaceRoot = workspaceRoot;
2257
+ this.snapshots = new Map;
2217
2258
  }
2218
2259
  build(operations) {
2219
2260
  this.add(this.workspaceRoot, false);
@@ -2257,8 +2298,10 @@ function snapshotOperations(operations, workspaceRoot) {
2257
2298
 
2258
2299
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2259
2300
  class PlanPathIndex {
2260
- firstChangeByPath = new Map;
2261
- reportedPathByCanonical = new Map;
2301
+ constructor() {
2302
+ this.firstChangeByPath = new Map;
2303
+ this.reportedPathByCanonical = new Map;
2304
+ }
2262
2305
  build(operations) {
2263
2306
  for (const operation of operations) {
2264
2307
  switch (operation.kind) {
@@ -2274,11 +2317,11 @@ class PlanPathIndex {
2274
2317
  }
2275
2318
  }
2276
2319
  }
2277
- add(path, reportedPath2, changeIndex) {
2320
+ add(path, reportedPath, changeIndex) {
2278
2321
  if (!this.firstChangeByPath.has(path))
2279
2322
  this.firstChangeByPath.set(path, changeIndex);
2280
2323
  if (!this.reportedPathByCanonical.has(path))
2281
- this.reportedPathByCanonical.set(path, reportedPath2);
2324
+ this.reportedPathByCanonical.set(path, reportedPath);
2282
2325
  }
2283
2326
  }
2284
2327
  function fingerprintWorkspaceEdit(edit, workspaceRoot) {
@@ -2347,14 +2390,11 @@ function isRecord3(value) {
2347
2390
  }
2348
2391
 
2349
2392
  class WorkspaceMutationController {
2350
- workspaceRoot;
2351
- documents;
2352
- activeLease = null;
2353
- nextLeaseId = 1;
2354
- io;
2355
2393
  constructor(workspaceRoot, documents) {
2356
2394
  this.workspaceRoot = workspaceRoot;
2357
2395
  this.documents = documents;
2396
+ this.activeLease = null;
2397
+ this.nextLeaseId = 1;
2358
2398
  }
2359
2399
  setIo(io) {
2360
2400
  this.io = io;
@@ -2393,8 +2433,8 @@ class WorkspaceMutationController {
2393
2433
  };
2394
2434
  }
2395
2435
  lease.phase = "applying";
2396
- lease.applyCompletion = new Promise((resolve5) => {
2397
- lease.resolveApply = resolve5;
2436
+ lease.applyCompletion = new Promise((resolve) => {
2437
+ lease.resolveApply = resolve;
2398
2438
  });
2399
2439
  const edit = isRecord3(params) ? params["edit"] : undefined;
2400
2440
  const record = edit === undefined ? { fingerprint: null, result: failure("workspace/applyEdit params.edit is required", 0) } : await this.applyEdit(edit, lease);
@@ -2467,14 +2507,12 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2467
2507
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2468
2508
 
2469
2509
  class LspClient extends LspClientConnection {
2470
- diagnosticPullErrors = [];
2471
- documents;
2472
- workspaceMutations;
2473
- diagnosticsFreshnessTimeoutMs;
2474
2510
  constructor(root, server, options = {}) {
2475
2511
  super(root, server, options);
2512
+ this.diagnosticPullErrors = [];
2476
2513
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2477
2514
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2515
+ timerProvider: this.timerProvider,
2478
2516
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
2479
2517
  });
2480
2518
  this.workspaceMutations = new WorkspaceMutationController(root, this.documents);
@@ -2527,6 +2565,18 @@ class LspClient extends LspClientConnection {
2527
2565
  textDocument: { uri: pathToFileURL3(absPath).href }
2528
2566
  }, options);
2529
2567
  }
2568
+ async formatDocument(filePath, options, signal) {
2569
+ if (!this.isDocumentFormattingSupported())
2570
+ return null;
2571
+ const absPath = this.resolveWorkspacePath(filePath);
2572
+ await this.openFile(absPath);
2573
+ const requestOptions = signal === undefined ? {} : { signal };
2574
+ const edits = await this.sendRequest("textDocument/formatting", {
2575
+ textDocument: { uri: pathToFileURL3(absPath).href },
2576
+ options
2577
+ }, requestOptions);
2578
+ return edits ?? [];
2579
+ }
2530
2580
  async workspaceSymbols(query, signal) {
2531
2581
  const options = signal === undefined ? {} : { signal };
2532
2582
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -2566,7 +2616,7 @@ class LspClient extends LspClientConnection {
2566
2616
  const absPath = this.resolveWorkspacePath(filePath);
2567
2617
  const uri = pathToFileURL3(absPath).href;
2568
2618
  await this.openFile(absPath);
2569
- const deadlineAt = Date.now() + this.diagnosticsFreshnessTimeoutMs;
2619
+ const deadlineAt = this.timerProvider.now() + this.diagnosticsFreshnessTimeoutMs;
2570
2620
  for (;; ) {
2571
2621
  signal?.throwIfAborted();
2572
2622
  const snapshot = this.documents.captureDiagnosticSnapshot(absPath);
@@ -2579,13 +2629,13 @@ class LspClient extends LspClientConnection {
2579
2629
  if (!pushFallbackOnly) {
2580
2630
  const cached = this.documents.getPullCache(snapshot);
2581
2631
  try {
2582
- const remainingMs2 = deadlineAt - Date.now();
2583
- if (remainingMs2 <= 0)
2632
+ const remainingMs = deadlineAt - this.timerProvider.now();
2633
+ if (remainingMs <= 0)
2584
2634
  return this.freshnessTimeout(absPath);
2585
2635
  const result = await this.sendRequest("textDocument/diagnostic", {
2586
2636
  textDocument: { uri },
2587
2637
  ...cached?.resultId === undefined ? {} : { previousResultId: cached.resultId }
2588
- }, { timeoutMs: remainingMs2, ...signal === undefined ? {} : { signal } });
2638
+ }, { timeoutMs: remainingMs, ...signal === undefined ? {} : { signal } });
2589
2639
  if (!this.documents.isCurrentSnapshot(snapshot))
2590
2640
  continue;
2591
2641
  const report = this.parseDiagnosticPullReport(result);
@@ -2614,7 +2664,7 @@ class LspClient extends LspClientConnection {
2614
2664
  }
2615
2665
  if (!pushFallbackOnly)
2616
2666
  continue;
2617
- const remainingMs = deadlineAt - Date.now();
2667
+ const remainingMs = deadlineAt - this.timerProvider.now();
2618
2668
  if (remainingMs <= 0) {
2619
2669
  if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
2620
2670
  const cached = this.documents.getPullCache(snapshot);
@@ -2666,7 +2716,7 @@ function waitForDiagnosticsActivity(wait, signal) {
2666
2716
  return wait;
2667
2717
  if (signal.aborted)
2668
2718
  return Promise.reject(abortError2(signal));
2669
- return new Promise((resolve6, reject) => {
2719
+ return new Promise((resolve, reject) => {
2670
2720
  const onAbort = () => {
2671
2721
  signal.removeEventListener("abort", onAbort);
2672
2722
  reject(abortError2(signal));
@@ -2674,7 +2724,7 @@ function waitForDiagnosticsActivity(wait, signal) {
2674
2724
  signal.addEventListener("abort", onAbort, { once: true });
2675
2725
  wait.then(() => {
2676
2726
  signal.removeEventListener("abort", onAbort);
2677
- resolve6();
2727
+ resolve();
2678
2728
  }, (error) => {
2679
2729
  signal.removeEventListener("abort", onAbort);
2680
2730
  reject(error);
@@ -2742,7 +2792,7 @@ async function stopClientBestEffort(client) {
2742
2792
  function awaitWithSignal(promise, signal) {
2743
2793
  if (!signal)
2744
2794
  return promise;
2745
- return new Promise((resolve6, reject) => {
2795
+ return new Promise((resolve, reject) => {
2746
2796
  let settled = false;
2747
2797
  const onAbort = () => {
2748
2798
  if (settled)
@@ -2760,7 +2810,7 @@ function awaitWithSignal(promise, signal) {
2760
2810
  return;
2761
2811
  settled = true;
2762
2812
  signal.removeEventListener("abort", onAbort);
2763
- resolve6(value);
2813
+ resolve(value);
2764
2814
  }, (err) => {
2765
2815
  if (settled)
2766
2816
  return;
@@ -2772,18 +2822,16 @@ function awaitWithSignal(promise, signal) {
2772
2822
  }
2773
2823
 
2774
2824
  class LspManager {
2775
- clients = new Map;
2776
- reaperHandle = null;
2777
- signalDisposer = null;
2778
- disposed = false;
2779
- idleTimeoutMs;
2780
- initTimeoutMs;
2781
- reaperIntervalMs;
2782
- clientFactory;
2783
- now;
2784
2825
  constructor(options = {}) {
2826
+ this.clients = new Map;
2827
+ this.pendingStops = new Map;
2828
+ this.respawnBudgets = new Map;
2829
+ this.reaperHandle = null;
2830
+ this.signalDisposer = null;
2831
+ this.disposed = false;
2785
2832
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
2786
2833
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
2834
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
2787
2835
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
2788
2836
  this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
2789
2837
  this.now = options.now ?? (() => Date.now());
@@ -2803,24 +2851,79 @@ class LspManager {
2803
2851
  getKey(root, serverId) {
2804
2852
  return `${root}::${serverId}`;
2805
2853
  }
2854
+ tombstoneStop(key, client) {
2855
+ const stop = stopClientBestEffort(client);
2856
+ this.pendingStops.set(key, stop);
2857
+ stop.finally(() => {
2858
+ if (this.pendingStops.get(key) === stop) {
2859
+ this.pendingStops.delete(key);
2860
+ }
2861
+ });
2862
+ return stop;
2863
+ }
2864
+ recordDeadGeneration(key) {
2865
+ let budget = this.respawnBudgets.get(key);
2866
+ if (budget === undefined) {
2867
+ budget = { deadGenerations: 0, exhaustedAt: null };
2868
+ this.respawnBudgets.set(key, budget);
2869
+ }
2870
+ budget.deadGenerations += 1;
2871
+ }
2872
+ markHealthyGeneration(key) {
2873
+ this.respawnBudgets.delete(key);
2874
+ }
2875
+ ensureRespawnAllowed(key, root, serverId) {
2876
+ const budget = this.respawnBudgets.get(key);
2877
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
2878
+ return;
2879
+ if (budget.exhaustedAt === null) {
2880
+ budget.exhaustedAt = this.now();
2881
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
2882
+ }
2883
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
2884
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
2885
+ }
2886
+ budget.deadGenerations = 0;
2887
+ budget.exhaustedAt = null;
2888
+ }
2806
2889
  reapStale() {
2807
2890
  const t = this.now();
2808
2891
  for (const [key, managed] of this.clients) {
2809
2892
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
2810
- stopClientBestEffort(managed.client);
2811
2893
  this.clients.delete(key);
2894
+ this.tombstoneStop(key, managed.client);
2812
2895
  continue;
2813
2896
  }
2814
2897
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
2815
- stopClientBestEffort(managed.client);
2816
2898
  this.clients.delete(key);
2899
+ this.tombstoneStop(key, managed.client);
2817
2900
  }
2818
2901
  }
2819
2902
  }
2903
+ evictForAdmission() {
2904
+ while (this.clients.size >= this.maxResidentClients) {
2905
+ const victim = this.leastRecentlyUsedIdleClient();
2906
+ if (!victim)
2907
+ return;
2908
+ this.clients.delete(victim.key);
2909
+ this.tombstoneStop(victim.key, victim.managed.client);
2910
+ }
2911
+ }
2912
+ leastRecentlyUsedIdleClient() {
2913
+ let candidate = null;
2914
+ for (const [key, managed] of this.clients) {
2915
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
2916
+ continue;
2917
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
2918
+ candidate = { key, managed };
2919
+ }
2920
+ }
2921
+ return candidate;
2922
+ }
2820
2923
  async tryDeleteIfOrphaned(key, managed) {
2821
2924
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
2822
2925
  this.clients.delete(key);
2823
- await stopClientBestEffort(managed.client);
2926
+ await this.tombstoneStop(key, managed.client);
2824
2927
  }
2825
2928
  }
2826
2929
  async getClient(root, server, signal) {
@@ -2829,12 +2932,22 @@ class LspManager {
2829
2932
  }
2830
2933
  signal?.throwIfAborted();
2831
2934
  const key = this.getKey(root, server.id);
2935
+ for (;; ) {
2936
+ const pendingStop = this.pendingStops.get(key);
2937
+ if (pendingStop === undefined)
2938
+ break;
2939
+ await awaitWithSignal(pendingStop, signal);
2940
+ signal?.throwIfAborted();
2941
+ }
2942
+ if (this.disposed) {
2943
+ throw new Error("LspManager has been disposed");
2944
+ }
2832
2945
  let managed = this.clients.get(key);
2833
2946
  if (managed) {
2834
2947
  const t = this.now();
2835
2948
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
2836
- await stopClientBestEffort(managed.client);
2837
2949
  this.clients.delete(key);
2950
+ await this.tombstoneStop(key, managed.client);
2838
2951
  managed = undefined;
2839
2952
  }
2840
2953
  }
@@ -2855,14 +2968,20 @@ class LspManager {
2855
2968
  signal.throwIfAborted();
2856
2969
  }
2857
2970
  if (!managed.client.isAlive()) {
2858
- await stopClientBestEffort(managed.client);
2859
- this.clients.delete(key);
2971
+ this.recordDeadGeneration(key);
2972
+ if (this.clients.get(key) === managed) {
2973
+ this.clients.delete(key);
2974
+ }
2975
+ await this.tombstoneStop(key, managed.client);
2860
2976
  return this.getClient(root, server, signal);
2861
2977
  }
2978
+ this.markHealthyGeneration(key);
2862
2979
  managed.refCount++;
2863
2980
  managed.lastUsedAt = this.now();
2864
2981
  return managed.client;
2865
2982
  }
2983
+ this.evictForAdmission();
2984
+ this.ensureRespawnAllowed(key, root, server.id);
2866
2985
  const client = this.clientFactory(root, server);
2867
2986
  const initStartedAt = this.now();
2868
2987
  const initPromise = (async () => {
@@ -2886,7 +3005,7 @@ class LspManager {
2886
3005
  if (this.clients.get(key) === newManaged) {
2887
3006
  this.clients.delete(key);
2888
3007
  }
2889
- await stopClientBestEffort(client);
3008
+ await this.tombstoneStop(key, client);
2890
3009
  throw err;
2891
3010
  }
2892
3011
  newManaged.pendingWaiters--;
@@ -2897,6 +3016,15 @@ class LspManager {
2897
3016
  await this.tryDeleteIfOrphaned(key, newManaged);
2898
3017
  signal.throwIfAborted();
2899
3018
  }
3019
+ if (!client.isAlive()) {
3020
+ this.recordDeadGeneration(key);
3021
+ if (this.clients.get(key) === newManaged) {
3022
+ this.clients.delete(key);
3023
+ }
3024
+ await this.tombstoneStop(key, client);
3025
+ return this.getClient(root, server, signal);
3026
+ }
3027
+ this.markHealthyGeneration(key);
2900
3028
  newManaged.refCount++;
2901
3029
  newManaged.lastUsedAt = this.now();
2902
3030
  return client;
@@ -2917,14 +3045,20 @@ class LspManager {
2917
3045
  if (client && managed.client !== client)
2918
3046
  return;
2919
3047
  this.clients.delete(key);
2920
- stopClientBestEffort(managed.client);
3048
+ this.tombstoneStop(key, managed.client);
2921
3049
  }
2922
3050
  warmupClient(root, server) {
2923
3051
  if (this.disposed)
2924
3052
  return;
2925
3053
  const key = this.getKey(root, server.id);
2926
- if (this.clients.has(key))
3054
+ if (this.clients.has(key) || this.pendingStops.has(key))
3055
+ return;
3056
+ this.evictForAdmission();
3057
+ try {
3058
+ this.ensureRespawnAllowed(key, root, server.id);
3059
+ } catch {
2927
3060
  return;
3061
+ }
2928
3062
  const client = this.clientFactory(root, server);
2929
3063
  const initStartedAt = this.now();
2930
3064
  const initPromise = (async () => {
@@ -2950,7 +3084,7 @@ class LspManager {
2950
3084
  if (this.clients.get(key) === managed) {
2951
3085
  this.clients.delete(key);
2952
3086
  }
2953
- stopClientBestEffort(client);
3087
+ this.tombstoneStop(key, client);
2954
3088
  });
2955
3089
  }
2956
3090
  isServerInitializing(root, serverId) {
@@ -2994,8 +3128,11 @@ class LspManager {
2994
3128
  for (const managed of this.clients.values()) {
2995
3129
  stopPromises.push(stopClientBestEffort(managed.client));
2996
3130
  }
3131
+ const tombstonedStops = [...this.pendingStops.values()];
2997
3132
  this.clients.clear();
2998
- await Promise.allSettled(stopPromises);
3133
+ this.respawnBudgets.clear();
3134
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3135
+ this.pendingStops.clear();
2999
3136
  }
3000
3137
  }
3001
3138
  var _defaultInstance = null;
@@ -3060,7 +3197,7 @@ ${body}` : `${body}
3060
3197
  await writeChunk(output, payload);
3061
3198
  }
3062
3199
  function writeChunk(output, chunk) {
3063
- return new Promise((resolve6, reject) => {
3200
+ return new Promise((resolve, reject) => {
3064
3201
  let settled = false;
3065
3202
  const onError = (error) => {
3066
3203
  if (settled)
@@ -3080,7 +3217,7 @@ function writeChunk(output, chunk) {
3080
3217
  return;
3081
3218
  }
3082
3219
  output.removeListener("error", onError);
3083
- resolve6();
3220
+ resolve();
3084
3221
  });
3085
3222
  } catch (error) {
3086
3223
  output.removeListener("error", onError);
@@ -3189,6 +3326,7 @@ async function runJsonRpcStdioServer(config) {
3189
3326
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
3190
3327
  isClosed = true;
3191
3328
  config.onIdleTimeout?.();
3329
+ config.input.destroy();
3192
3330
  });
3193
3331
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
3194
3332
  isClosed = true;
@@ -3285,7 +3423,11 @@ function createParentWatchdog(config, onDeadParent) {
3285
3423
  const probeAlive = config.probeAlive ?? isProcessAlive;
3286
3424
  let fired = false;
3287
3425
  const timer = setInterval(() => {
3288
- if (fired || probeAlive(parentPid))
3426
+ if (fired)
3427
+ return;
3428
+ const alive = probeAlive(parentPid);
3429
+ config.onPoll?.(alive);
3430
+ if (alive)
3289
3431
  return;
3290
3432
  fired = true;
3291
3433
  onDeadParent(parentPid, pollIntervalMs);
@@ -3320,8 +3462,8 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
3320
3462
  };
3321
3463
  }
3322
3464
  // ../lsp-core/src/lsp/client-wrapper.ts
3323
- import { existsSync as existsSync9, realpathSync as realpathSync4, statSync as statSync3 } from "node:fs";
3324
- import { basename as basename3, dirname as dirname6, join as join4, resolve as resolve7 } from "node:path";
3465
+ import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
3466
+ import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
3325
3467
 
3326
3468
  // ../lsp-core/src/request-context.ts
3327
3469
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -3330,18 +3472,17 @@ import { homedir } from "node:os";
3330
3472
  import { basename as basename2, delimiter as delimiter2, dirname as dirname4, isAbsolute as isAbsolute2, join as join2, relative as relative4, resolve as resolve6 } from "node:path";
3331
3473
 
3332
3474
  class LspRequestContextParseError extends Error {
3333
- code;
3334
- name = "LspRequestContextParseError";
3335
3475
  constructor(code, message) {
3336
3476
  super(message);
3337
3477
  this.code = code;
3478
+ this.name = "LspRequestContextParseError";
3338
3479
  }
3339
3480
  }
3340
3481
 
3341
3482
  class LspRequestContextUnavailableError extends Error {
3342
- name = "LspRequestContextUnavailableError";
3343
3483
  constructor() {
3344
3484
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
3485
+ this.name = "LspRequestContextUnavailableError";
3345
3486
  }
3346
3487
  }
3347
3488
  var storage = new AsyncLocalStorage;
@@ -3371,7 +3512,7 @@ function contextEnv(key) {
3371
3512
  }
3372
3513
  function createStandaloneMcpRequestContext(input = {}) {
3373
3514
  const env = input.env ?? process.env;
3374
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
3515
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
3375
3516
  const home = input.homeDir ?? homedir();
3376
3517
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
3377
3518
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -3502,57 +3643,52 @@ function errorCode(error) {
3502
3643
  return typeof code === "string" ? code : undefined;
3503
3644
  }
3504
3645
 
3505
- // ../lsp-core/src/lsp/server-install-state.ts
3506
- import { existsSync as existsSync6, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3507
- import { dirname as dirname5 } from "node:path";
3508
- function getInstallDecisionsPath() {
3509
- return lspRequestContext().installDecisionsPath;
3510
- }
3511
- function loadInstallDecisions() {
3512
- const path = getInstallDecisionsPath();
3513
- if (!existsSync6(path))
3514
- return {};
3515
- try {
3516
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
3517
- return isInstallDecisions(parsed) ? parsed : {};
3518
- } catch {
3519
- return {};
3646
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3647
+ import { existsSync as existsSync6, realpathSync as realpathSync4 } from "node:fs";
3648
+ import { dirname as dirname5, join as join3 } from "node:path";
3649
+
3650
+ // ../lsp-core/src/lsp/workspace-markers.ts
3651
+ var GIT_WORKSPACE_MARKER = ".git";
3652
+ var PROJECT_WORKSPACE_MARKERS = [
3653
+ "package.json",
3654
+ "pyproject.toml",
3655
+ "Cargo.toml",
3656
+ "go.mod",
3657
+ "pom.xml",
3658
+ "build.gradle"
3659
+ ];
3660
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
3661
+
3662
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
3663
+ function findWorkspaceRootOutsideContext(directory) {
3664
+ const marked = nearestMarkedAncestor(directory);
3665
+ if (marked !== undefined)
3666
+ return marked;
3667
+ return realpathSync4(nearestExistingAncestor(directory));
3668
+ }
3669
+ function nearestMarkedAncestor(directory) {
3670
+ let current = directory;
3671
+ for (;; ) {
3672
+ if (existsSync6(current) && WORKSPACE_MARKERS.some((marker) => existsSync6(join3(current, marker)))) {
3673
+ return realpathSync4(current);
3674
+ }
3675
+ const parent = dirname5(current);
3676
+ if (parent === current)
3677
+ return;
3678
+ current = parent;
3520
3679
  }
3521
3680
  }
3522
- function loadInstallDecision(serverId) {
3523
- return loadInstallDecisions()[serverId];
3524
- }
3525
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3526
- const decisions = loadInstallDecisions();
3527
- decisions[serverId] = { decision, decidedAt };
3528
- writeInstallDecisions(decisions);
3529
- }
3530
- function isInstallDecision(value) {
3531
- return value === "declined" || value === "allowed";
3532
- }
3533
- function writeInstallDecisions(decisions) {
3534
- const path = getInstallDecisionsPath();
3535
- mkdirSync(dirname5(path), { recursive: true });
3536
- const tmpPath = `${path}.tmp`;
3537
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3538
- `, "utf8");
3539
- renameSync2(tmpPath, path);
3540
- }
3541
- function isInstallDecisions(value) {
3542
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3543
- }
3544
- function isInstallDecisionRecord(value) {
3545
- if (!isRecord5(value))
3546
- return false;
3547
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3548
- }
3549
- function isRecord5(value) {
3550
- return typeof value === "object" && value !== null && !Array.isArray(value);
3681
+ function nearestExistingAncestor(directory) {
3682
+ let current = directory;
3683
+ while (!existsSync6(current)) {
3684
+ const parent = dirname5(current);
3685
+ if (parent === current)
3686
+ return current;
3687
+ current = parent;
3688
+ }
3689
+ return current;
3551
3690
  }
3552
3691
 
3553
- // ../lsp-core/src/lsp/config-loader.ts
3554
- import { existsSync as existsSync7, readFileSync as readFileSync4 } from "node:fs";
3555
-
3556
3692
  // ../lsp-core/src/lsp/server-definitions.ts
3557
3693
  var LSP_INSTALL_HINTS = {
3558
3694
  typescript: "npm install -g typescript-language-server typescript",
@@ -3598,6 +3734,26 @@ var LSP_INSTALL_HINTS = {
3598
3734
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
3599
3735
  razor: "Razor runs through the Roslyn language server (cohosting). " + "Install: dotnet tool install -g roslyn-language-server --prerelease (requires v5.8.0+). See https://github.com/dotnet/razor"
3600
3736
  };
3737
+ var LSP_LOCAL_INSTALL_HINTS = {
3738
+ typescript: "bun add -d typescript-language-server typescript",
3739
+ vue: "bun add -d @vue/language-server",
3740
+ eslint: "bun add -d vscode-langservers-extracted",
3741
+ oxlint: "bun add -d oxlint",
3742
+ biome: "bun add -d @biomejs/biome",
3743
+ svelte: "bun add -d svelte-language-server",
3744
+ astro: "bun add -d @astrojs/language-server",
3745
+ bash: "bun add -d bash-language-server",
3746
+ "bash-ls": "bun add -d bash-language-server",
3747
+ "yaml-ls": "bun add -d yaml-language-server",
3748
+ php: "bun add -d intelephense",
3749
+ prisma: "bun add -d prisma",
3750
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
3751
+ pyright: "uv add --dev pyright",
3752
+ basedpyright: "uv add --dev basedpyright",
3753
+ ruff: "uv add --dev ruff",
3754
+ ty: "uv add --dev ty",
3755
+ "ruby-lsp": "bundle add ruby-lsp --group development"
3756
+ };
3601
3757
  var BUILTIN_SERVERS = {
3602
3758
  typescript: {
3603
3759
  command: ["typescript-language-server", "--stdio"],
@@ -3700,7 +3856,56 @@ var BUILTIN_SERVERS = {
3700
3856
  }
3701
3857
  };
3702
3858
 
3859
+ // ../lsp-core/src/lsp/server-install-state.ts
3860
+ import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
3861
+ import { dirname as dirname6 } from "node:path";
3862
+ function getInstallDecisionsPath() {
3863
+ return lspRequestContext().installDecisionsPath;
3864
+ }
3865
+ function loadInstallDecisions() {
3866
+ const path = getInstallDecisionsPath();
3867
+ if (!existsSync7(path))
3868
+ return {};
3869
+ try {
3870
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
3871
+ return isInstallDecisions(parsed) ? parsed : {};
3872
+ } catch {
3873
+ return {};
3874
+ }
3875
+ }
3876
+ function loadInstallDecision(serverId) {
3877
+ return loadInstallDecisions()[serverId];
3878
+ }
3879
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
3880
+ const decisions = loadInstallDecisions();
3881
+ decisions[serverId] = { decision, decidedAt };
3882
+ writeInstallDecisions(decisions);
3883
+ }
3884
+ function isInstallDecision(value) {
3885
+ return value === "declined" || value === "allowed";
3886
+ }
3887
+ function writeInstallDecisions(decisions) {
3888
+ const path = getInstallDecisionsPath();
3889
+ mkdirSync(dirname6(path), { recursive: true });
3890
+ const tmpPath = `${path}.tmp`;
3891
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
3892
+ `, "utf8");
3893
+ renameSync2(tmpPath, path);
3894
+ }
3895
+ function isInstallDecisions(value) {
3896
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
3897
+ }
3898
+ function isInstallDecisionRecord(value) {
3899
+ if (!isRecord5(value))
3900
+ return false;
3901
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
3902
+ }
3903
+ function isRecord5(value) {
3904
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3905
+ }
3906
+
3703
3907
  // ../lsp-core/src/lsp/config-loader.ts
3908
+ import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
3704
3909
  function getProjectConfigPaths() {
3705
3910
  return lspRequestContext().projectConfigPaths;
3706
3911
  }
@@ -3708,7 +3913,7 @@ function getUserConfigPath() {
3708
3913
  return lspRequestContext().userConfigPath;
3709
3914
  }
3710
3915
  function loadJsonFile(path) {
3711
- if (!existsSync7(path))
3916
+ if (!existsSync8(path))
3712
3917
  return null;
3713
3918
  try {
3714
3919
  const parsed = JSON.parse(readFileSync4(path, "utf-8"));
@@ -3755,10 +3960,10 @@ function getMergedServers() {
3755
3960
  }
3756
3961
  if (seen.has(id))
3757
3962
  continue;
3758
- const server2 = createServerFromEntry(id, entry, source);
3759
- if (!server2)
3963
+ const server = createServerFromEntry(id, entry, source);
3964
+ if (!server)
3760
3965
  continue;
3761
- servers.push(server2);
3966
+ servers.push(server);
3762
3967
  seen.add(id);
3763
3968
  }
3764
3969
  }
@@ -3790,7 +3995,7 @@ function createServerFromEntry(id, entry, source) {
3790
3995
  if (source === "project") {
3791
3996
  if (!builtin)
3792
3997
  return null;
3793
- const server3 = createServer({
3998
+ const server = createServer({
3794
3999
  id,
3795
4000
  command: builtin.command,
3796
4001
  extensions: entry.extensions ?? builtin.extensions,
@@ -3798,35 +4003,35 @@ function createServerFromEntry(id, entry, source) {
3798
4003
  source
3799
4004
  });
3800
4005
  if (entry.initialization !== undefined) {
3801
- server3.initialization = entry.initialization;
4006
+ server.initialization = entry.initialization;
3802
4007
  }
3803
- return server3;
4008
+ return server;
3804
4009
  }
3805
4010
  if (entry.command && entry.extensions) {
3806
- const server3 = createServer({
4011
+ const server = createServer({
3807
4012
  id,
3808
4013
  command: entry.command,
3809
4014
  extensions: entry.extensions,
3810
4015
  priority: entry.priority ?? 0,
3811
4016
  source
3812
4017
  });
3813
- applyOptionalServerFields(server3, entry);
3814
- return server3;
4018
+ applyOptionalServerFields(server, entry);
4019
+ return server;
3815
4020
  }
3816
4021
  if (!builtin)
3817
4022
  return null;
3818
- const server2 = createServer({
4023
+ const server = createServer({
3819
4024
  id,
3820
4025
  command: entry.command ?? builtin.command,
3821
4026
  extensions: entry.extensions ?? builtin.extensions,
3822
4027
  priority: entry.priority ?? 0,
3823
4028
  source
3824
4029
  });
3825
- applyOptionalServerFields(server2, entry);
3826
- return server2;
4030
+ applyOptionalServerFields(server, entry);
4031
+ return server;
3827
4032
  }
3828
4033
  function createServer(input) {
3829
- const server2 = {
4034
+ const server = {
3830
4035
  id: input.id,
3831
4036
  command: input.command,
3832
4037
  extensions: input.extensions,
@@ -3834,19 +4039,19 @@ function createServer(input) {
3834
4039
  source: input.source
3835
4040
  };
3836
4041
  if (input.env !== undefined) {
3837
- server2.env = input.env;
4042
+ server.env = input.env;
3838
4043
  }
3839
4044
  if (input.initialization !== undefined) {
3840
- server2.initialization = input.initialization;
4045
+ server.initialization = input.initialization;
3841
4046
  }
3842
- return server2;
4047
+ return server;
3843
4048
  }
3844
- function applyOptionalServerFields(server2, entry) {
4049
+ function applyOptionalServerFields(server, entry) {
3845
4050
  if (entry.env !== undefined) {
3846
- server2.env = entry.env;
4051
+ server.env = entry.env;
3847
4052
  }
3848
4053
  if (entry.initialization !== undefined) {
3849
- server2.initialization = entry.initialization;
4054
+ server.initialization = entry.initialization;
3850
4055
  }
3851
4056
  }
3852
4057
  function isConfigJson(value) {
@@ -3896,64 +4101,165 @@ function getDisabledServerIds() {
3896
4101
  }
3897
4102
 
3898
4103
  // ../lsp-core/src/lsp/server-installation.ts
3899
- import { existsSync as existsSync8 } from "node:fs";
3900
- import { delimiter as delimiter3, join as join3 } from "node:path";
3901
- function isServerInstalled(command, _workingDirectory) {
3902
- if (command.length === 0)
3903
- return false;
3904
- const [cmd] = command;
3905
- if (!cmd)
3906
- return false;
3907
- if (cmd.includes("/") || cmd.includes("\\")) {
3908
- if (existsSync8(cmd))
3909
- return true;
4104
+ import { existsSync as existsSync9 } from "node:fs";
4105
+ import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
4106
+ var LOCAL_BIN_RULES = [
4107
+ {
4108
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4109
+ binDirs: [join4("node_modules", ".bin")]
4110
+ },
4111
+ {
4112
+ markers: [
4113
+ "pyproject.toml",
4114
+ "ty.toml",
4115
+ "requirements.txt",
4116
+ "setup.py",
4117
+ "setup.cfg",
4118
+ "Pipfile",
4119
+ "pyrightconfig.json",
4120
+ "ruff.toml",
4121
+ ".ruff.toml"
4122
+ ],
4123
+ binDirs: [
4124
+ join4(".venv", "bin"),
4125
+ join4(".venv", "Scripts"),
4126
+ join4("venv", "bin"),
4127
+ join4("venv", "Scripts"),
4128
+ join4(".env", "bin"),
4129
+ join4(".env", "Scripts")
4130
+ ]
4131
+ },
4132
+ {
4133
+ markers: ["Gemfile", "Gemfile.lock"],
4134
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4135
+ },
4136
+ {
4137
+ markers: ["go.mod", "go.sum", "go.work"],
4138
+ binDirs: ["bin"]
4139
+ }
4140
+ ];
4141
+ var resolutionCache = new Map;
4142
+ var probeCount = 0;
4143
+ function probe(path) {
4144
+ probeCount += 1;
4145
+ return existsSync9(path);
4146
+ }
4147
+ function executableSuffixes(platform, pathExt) {
4148
+ if (platform !== "win32")
4149
+ return [""];
4150
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4151
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4152
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4153
+ }
4154
+ function probeWithSuffixes(directory, command, suffixes) {
4155
+ for (const suffix of suffixes) {
4156
+ const candidate = join4(directory, command + suffix);
4157
+ if (probe(candidate))
4158
+ return candidate;
3910
4159
  }
3911
- const isWindows = process.platform === "win32";
3912
- let exts = [""];
3913
- if (isWindows) {
3914
- const pathExt = process.env["PATHEXT"] ?? "";
3915
- if (pathExt) {
3916
- const systemExts = pathExt.split(";").filter(Boolean);
3917
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
3918
- } else {
3919
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4160
+ return null;
4161
+ }
4162
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4163
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4164
+ let current = resolve7(workingDirectory);
4165
+ while (true) {
4166
+ for (const rule of LOCAL_BIN_RULES) {
4167
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4168
+ continue;
4169
+ for (const binDir of rule.binDirs) {
4170
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4171
+ if (found !== null)
4172
+ return found;
4173
+ }
3920
4174
  }
4175
+ if (probe(join4(current, ".git")))
4176
+ return null;
4177
+ if (boundary !== undefined && current === boundary)
4178
+ return null;
4179
+ const parent = dirname7(current);
4180
+ if (parent === current)
4181
+ return null;
4182
+ current = parent;
3921
4183
  }
3922
- let pathEnv = process.env["PATH"] ?? "";
3923
- if (isWindows && !pathEnv) {
4184
+ }
4185
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4186
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4187
+ if (platform === "win32" && !pathEnv) {
3924
4188
  pathEnv = process.env["Path"] ?? "";
3925
4189
  }
3926
- const paths = pathEnv.split(delimiter3);
3927
- for (const p of paths) {
3928
- for (const suffix of exts) {
3929
- if (existsSync8(join3(p, cmd + suffix))) {
3930
- return true;
3931
- }
3932
- }
4190
+ for (const entry of pathEnv.split(delimiter3)) {
4191
+ if (entry.length === 0)
4192
+ continue;
4193
+ const found = probeWithSuffixes(entry, command, suffixes);
4194
+ if (found !== null)
4195
+ return found;
3933
4196
  }
3934
- if (cmd === "node")
3935
- return true;
3936
- return false;
4197
+ return null;
4198
+ }
4199
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4200
+ if (command.length === 0)
4201
+ return null;
4202
+ const [cmd] = command;
4203
+ if (cmd === undefined || cmd.length === 0)
4204
+ return null;
4205
+ const platform = options.platform ?? process.platform;
4206
+ const suffixes = executableSuffixes(platform, options.pathExt);
4207
+ if (cmd.includes("/") || cmd.includes("\\")) {
4208
+ const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4209
+ return probe(explicit) ? explicit : null;
4210
+ }
4211
+ const cacheKey = JSON.stringify([
4212
+ workingDirectory ?? "",
4213
+ cmd,
4214
+ platform,
4215
+ options.stopAt ?? "",
4216
+ options.pathExt ?? "",
4217
+ options.pathEnv ?? process.env["PATH"] ?? ""
4218
+ ]);
4219
+ const cached = resolutionCache.get(cacheKey);
4220
+ if (cached !== undefined)
4221
+ return cached;
4222
+ let resolved = null;
4223
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4224
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4225
+ }
4226
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4227
+ if (resolved === null && cmd === "node")
4228
+ resolved = cmd;
4229
+ resolutionCache.set(cacheKey, resolved);
4230
+ return resolved;
4231
+ }
4232
+ function isServerInstalled(command, workingDirectory, options = {}) {
4233
+ if (command.length === 0)
4234
+ return false;
4235
+ return resolveServerBinary(command, workingDirectory, options) !== null;
3937
4236
  }
3938
4237
 
3939
4238
  // ../lsp-core/src/lsp/server-resolution.ts
4239
+ function withResolvedCommand(command, binaryPath) {
4240
+ return [binaryPath, ...command.slice(1)];
4241
+ }
3940
4242
  function findServerForExtension(ext) {
3941
4243
  const servers = getMergedServers();
3942
- for (const server2 of servers) {
3943
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4244
+ const workingDirectory = contextCwd();
4245
+ for (const server of servers) {
4246
+ if (!server.extensions.includes(ext))
4247
+ continue;
4248
+ const binaryPath = resolveServerBinary(server.command, workingDirectory);
4249
+ if (binaryPath !== null) {
3944
4250
  const resolvedServer = {
3945
- id: server2.id,
3946
- command: server2.command,
3947
- extensions: server2.extensions,
3948
- priority: server2.priority
4251
+ id: server.id,
4252
+ command: withResolvedCommand(server.command, binaryPath),
4253
+ extensions: server.extensions,
4254
+ priority: server.priority
3949
4255
  };
3950
- if (server2.env !== undefined) {
4256
+ if (server.env !== undefined) {
3951
4257
  return {
3952
4258
  status: "found",
3953
4259
  server: {
3954
4260
  ...resolvedServer,
3955
- env: server2.env,
3956
- ...server2.initialization === undefined ? {} : { initialization: server2.initialization }
4261
+ env: server.env,
4262
+ ...server.initialization === undefined ? {} : { initialization: server.initialization }
3957
4263
  }
3958
4264
  };
3959
4265
  }
@@ -3961,20 +4267,20 @@ function findServerForExtension(ext) {
3961
4267
  status: "found",
3962
4268
  server: {
3963
4269
  ...resolvedServer,
3964
- ...server2.initialization === undefined ? {} : { initialization: server2.initialization }
4270
+ ...server.initialization === undefined ? {} : { initialization: server.initialization }
3965
4271
  }
3966
4272
  };
3967
4273
  }
3968
4274
  }
3969
- for (const server2 of servers) {
3970
- if (server2.extensions.includes(ext)) {
3971
- const installHint = LSP_INSTALL_HINTS[server2.id] ?? `Install '${server2.command[0]}' and ensure it's in your PATH`;
4275
+ for (const server of servers) {
4276
+ if (server.extensions.includes(ext)) {
4277
+ const installHint = LSP_INSTALL_HINTS[server.id] ?? `Install '${server.command[0]}' and ensure it's in your PATH`;
3972
4278
  return {
3973
4279
  status: "not_installed",
3974
4280
  server: {
3975
- id: server2.id,
3976
- command: server2.command,
3977
- extensions: server2.extensions
4281
+ id: server.id,
4282
+ command: server.command,
4283
+ extensions: server.extensions
3978
4284
  },
3979
4285
  installHint
3980
4286
  };
@@ -3990,20 +4296,21 @@ function findServerForExtension(ext) {
3990
4296
  function getAllServers() {
3991
4297
  const servers = getMergedServers();
3992
4298
  const disabled = getDisabledServerIds();
4299
+ const workingDirectory = contextCwd();
3993
4300
  const result = [];
3994
4301
  const seen = new Set;
3995
- for (const server2 of servers) {
3996
- if (seen.has(server2.id))
4302
+ for (const server of servers) {
4303
+ if (seen.has(server.id))
3997
4304
  continue;
3998
4305
  result.push({
3999
- id: server2.id,
4000
- installed: isServerInstalled(server2.command),
4001
- extensions: server2.extensions,
4306
+ id: server.id,
4307
+ installed: isServerInstalled(server.command, workingDirectory),
4308
+ extensions: server.extensions,
4002
4309
  disabled: false,
4003
- source: server2.source,
4004
- priority: server2.priority
4310
+ source: server.source,
4311
+ priority: server.priority
4005
4312
  });
4006
- seen.add(server2.id);
4313
+ seen.add(server.id);
4007
4314
  }
4008
4315
  for (const id of disabled) {
4009
4316
  if (seen.has(id))
@@ -4011,7 +4318,7 @@ function getAllServers() {
4011
4318
  const builtin = BUILTIN_SERVERS[id];
4012
4319
  result.push({
4013
4320
  id,
4014
- installed: builtin ? isServerInstalled(builtin.command) : false,
4321
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4015
4322
  extensions: builtin?.extensions ?? [],
4016
4323
  disabled: true,
4017
4324
  source: "disabled",
@@ -4022,7 +4329,6 @@ function getAllServers() {
4022
4329
  }
4023
4330
 
4024
4331
  // ../lsp-core/src/lsp/client-wrapper.ts
4025
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4026
4332
  function isDirectoryPath(filePath) {
4027
4333
  try {
4028
4334
  return statSync3(filePath).isDirectory();
@@ -4035,36 +4341,40 @@ function findWorkspaceRoot(filePath) {
4035
4341
  const abs = resolveReadablePathInsideContext(filePath);
4036
4342
  let dir = abs;
4037
4343
  if (!isDirectoryPath(dir)) {
4038
- dir = dirname6(dir);
4344
+ dir = dirname8(dir);
4039
4345
  }
4346
+ if (!isPathInside(cwd, abs))
4347
+ return findWorkspaceRootOutsideContext(dir);
4040
4348
  const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4349
+ let nearestPackageRoot;
4041
4350
  while (isPathInside(cwd, dir)) {
4042
4351
  const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4043
4352
  if (canonicalDir !== undefined) {
4044
- for (const marker of WORKSPACE_MARKERS) {
4045
- if (existsSync9(join4(dir, marker))) {
4046
- return canonicalDir;
4047
- }
4353
+ if (existsSync10(join5(dir, GIT_WORKSPACE_MARKER))) {
4354
+ return canonicalDir;
4355
+ }
4356
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4357
+ nearestPackageRoot = canonicalDir;
4048
4358
  }
4049
4359
  }
4050
4360
  if (dir === cwd)
4051
4361
  break;
4052
- dir = dirname6(dir);
4362
+ dir = dirname8(dir);
4053
4363
  }
4054
- return fallbackRoot;
4364
+ return nearestPackageRoot ?? fallbackRoot;
4365
+ }
4366
+ function hasProjectWorkspaceMarker(directory) {
4367
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync10(join5(directory, marker)));
4055
4368
  }
4056
4369
  function resolveReadablePathInsideContext(filePath) {
4057
4370
  const cwd = contextCwd();
4058
- const abs = resolve7(cwd, filePath);
4371
+ const abs = resolve8(cwd, filePath);
4059
4372
  if (isPathInside(cwd, abs))
4060
4373
  return abs;
4061
4374
  const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4062
4375
  if (rebased !== undefined)
4063
4376
  return rebased;
4064
- const canonical = canonicalizeExistingOrNearestAncestor(abs);
4065
- if (isPathInside(cwd, canonical))
4066
- return canonical;
4067
- throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4377
+ return canonicalizeExistingOrNearestAncestor(abs);
4068
4378
  }
4069
4379
  function resolvePathInsideContext(filePath) {
4070
4380
  const cwd = contextCwd();
@@ -4079,12 +4389,12 @@ function rebaseThroughCanonicalAncestor(path, cwd) {
4079
4389
  let current = path;
4080
4390
  const suffix = [];
4081
4391
  while (true) {
4082
- if (existsSync9(current)) {
4083
- const canonical = realpathSync4(current);
4392
+ if (existsSync10(current)) {
4393
+ const canonical = realpathSync5(current);
4084
4394
  if (isPathInside(cwd, canonical))
4085
- return suffix.length === 0 ? canonical : join4(canonical, ...suffix);
4395
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
4086
4396
  }
4087
- const parent = dirname6(current);
4397
+ const parent = dirname8(current);
4088
4398
  if (parent === current)
4089
4399
  return;
4090
4400
  suffix.unshift(basename3(current));
@@ -4092,9 +4402,9 @@ function rebaseThroughCanonicalAncestor(path, cwd) {
4092
4402
  }
4093
4403
  }
4094
4404
  function existingDirectoryInsideContext(directory, cwd) {
4095
- if (!existsSync9(directory))
4405
+ if (!existsSync10(directory))
4096
4406
  return;
4097
- const canonical = realpathSync4(directory);
4407
+ const canonical = realpathSync5(directory);
4098
4408
  if (!statSync3(canonical).isDirectory())
4099
4409
  return;
4100
4410
  return isPathInside(cwd, canonical) ? canonical : undefined;
@@ -4107,7 +4417,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
4107
4417
  return canonical;
4108
4418
  if (current === cwd)
4109
4419
  return;
4110
- current = dirname6(current);
4420
+ current = dirname8(current);
4111
4421
  }
4112
4422
  return;
4113
4423
  }
@@ -4134,33 +4444,46 @@ function formatServerLookupError(result) {
4134
4444
  ].join(`
4135
4445
  `);
4136
4446
  }
4447
+ function formatInstallOptions(serverId, installHint) {
4448
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
4449
+ if (localHint === undefined) {
4450
+ return ["To install, run:", ` ${installHint}`];
4451
+ }
4452
+ return [
4453
+ "To install in THIS repository (preferred — no global install needed):",
4454
+ ` ${localHint}`,
4455
+ "",
4456
+ "Or install it globally:",
4457
+ ` ${installHint}`
4458
+ ];
4459
+ }
4137
4460
  function formatNotInstalled(result) {
4138
- const { server: server2, installHint } = result;
4139
- const extensions = server2.extensions.join(", ");
4140
- const decision = loadInstallDecision(server2.id)?.decision;
4461
+ const { server, installHint } = result;
4462
+ const extensions = server.extensions.join(", ");
4463
+ const decision = loadInstallDecision(server.id)?.decision;
4141
4464
  const context = lspRequestContext();
4142
4465
  if (decision === "declined") {
4143
- return `LSP server '${server2.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
4466
+ return `LSP server '${server.id}' (${extensions}) is NOT INSTALLED; user previously declined installation — proceed without LSP.`;
4144
4467
  }
4145
4468
  const header = [
4146
- `LSP server '${server2.id}' for ${extensions} is NOT INSTALLED.`,
4469
+ `LSP server '${server.id}' for ${extensions} is NOT INSTALLED.`,
4147
4470
  "",
4148
- `Command not found: ${server2.command[0]}`,
4471
+ `Command not found: ${server.command[0]}`,
4149
4472
  ""
4150
4473
  ];
4474
+ const installOptions = formatInstallOptions(server.id, installHint);
4151
4475
  if (decision === "allowed") {
4152
4476
  return [
4153
4477
  ...header,
4154
4478
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4155
- ` ${installHint}`
4479
+ ...installOptions.slice(1)
4156
4480
  ].join(`
4157
4481
  `);
4158
4482
  }
4159
4483
  if (!context.capabilities.installDecisionTool) {
4160
4484
  return [
4161
4485
  ...header,
4162
- "To install, run:",
4163
- ` ${installHint}`,
4486
+ ...installOptions,
4164
4487
  "",
4165
4488
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4166
4489
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4169,13 +4492,12 @@ function formatNotInstalled(result) {
4169
4492
  }
4170
4493
  return [
4171
4494
  ...header,
4172
- "To install, run:",
4173
- ` ${installHint}`,
4495
+ ...installOptions,
4174
4496
  "",
4175
4497
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4176
4498
  "- If the user agrees: run the install command above, then retry this tool.",
4177
4499
  "- If the user declines, OR has NOT explicitly asked for LSP installation:",
4178
- ` call lsp_install_decision { server_id: "${server2.id}", decision: "declined" },`,
4500
+ ` call lsp_install_decision { server_id: "${server.id}", decision: "declined" },`,
4179
4501
  ` which writes to ${context.installDecisionsPath},`,
4180
4502
  " then ignore this message and proceed WITHOUT LSP."
4181
4503
  ].join(`
@@ -4199,34 +4521,34 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4199
4521
  if (result.status !== "found") {
4200
4522
  throw new LspServerLookupError(formatServerLookupError(result), result);
4201
4523
  }
4202
- const server2 = result.server;
4524
+ const server = result.server;
4203
4525
  const root = findWorkspaceRoot(absPath);
4204
- const manager2 = options.manager ?? getLspManager();
4526
+ const manager = options.manager ?? getLspManager();
4205
4527
  const acquireAndCall = async (allowRetry) => {
4206
- const client = await manager2.getClient(root, server2, options.signal);
4528
+ const client = await manager.getClient(root, server, options.signal);
4207
4529
  try {
4208
4530
  return await fn(client, root, absPath);
4209
4531
  } catch (err) {
4210
4532
  if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4211
- manager2.invalidateClient(root, server2.id, client);
4533
+ manager.invalidateClient(root, server.id, client);
4212
4534
  return acquireAndCall(false);
4213
4535
  }
4214
4536
  if (err instanceof LspRequestTimeoutError) {
4215
- if (manager2.isServerInitializing(root, server2.id)) {
4537
+ if (manager.isServerInitializing(root, server.id)) {
4216
4538
  throw new LspServerInitializingError(err);
4217
4539
  }
4218
4540
  }
4219
4541
  throw err;
4220
4542
  } finally {
4221
- manager2.releaseClient(root, server2.id);
4543
+ manager.releaseClient(root, server.id);
4222
4544
  }
4223
4545
  };
4224
4546
  return acquireAndCall(true);
4225
4547
  }
4226
4548
 
4227
4549
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4228
- import { existsSync as existsSync10, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4229
- import { join as join5, resolve as resolve8 } from "node:path";
4550
+ import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
4551
+ import { join as join6, resolve as resolve9 } from "node:path";
4230
4552
 
4231
4553
  // ../lsp-core/src/lsp/formatters.ts
4232
4554
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -4241,10 +4563,10 @@ function uriToPath(uri) {
4241
4563
  }
4242
4564
  function formatLocation(loc) {
4243
4565
  if ("targetUri" in loc) {
4244
- const uri2 = uriToPath(loc.targetUri);
4245
- const line2 = loc.targetRange.start.line + 1;
4246
- const char2 = loc.targetRange.start.character;
4247
- return `${uri2}:${line2}:${char2}`;
4566
+ const uri = uriToPath(loc.targetUri);
4567
+ const line = loc.targetRange.start.line + 1;
4568
+ const char = loc.targetRange.start.character;
4569
+ return `${uri}:${line}:${char}`;
4248
4570
  }
4249
4571
  const uri = uriToPath(loc.uri);
4250
4572
  const line = loc.range.start.line + 1;
@@ -4356,7 +4678,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4356
4678
  for (const entry of entries) {
4357
4679
  if (files.length >= maxFiles)
4358
4680
  return;
4359
- const fullPath = join5(currentDir, entry);
4681
+ const fullPath = join6(currentDir, entry);
4360
4682
  let stat;
4361
4683
  try {
4362
4684
  stat = lstatSync4(fullPath);
@@ -4381,15 +4703,15 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4381
4703
  if (!extension.startsWith(".")) {
4382
4704
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4383
4705
  }
4384
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4385
- if (!existsSync10(absDir)) {
4706
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
4707
+ if (!existsSync11(absDir)) {
4386
4708
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4387
4709
  }
4388
4710
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
4389
4711
  if (serverResult.status !== "found") {
4390
4712
  throw new LspServerLookupError(formatServerLookupError(serverResult));
4391
4713
  }
4392
- const server2 = serverResult.server;
4714
+ const server = serverResult.server;
4393
4715
  const allFiles = (options.listFiles ?? collectFilesWithExtension)(absDir, extension, maxFiles + 1);
4394
4716
  const wasCapped = allFiles.length > maxFiles;
4395
4717
  const filesToProcess = allFiles.slice(0, maxFiles);
@@ -4404,12 +4726,12 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4404
4726
  return { output, totalDiagnostics: 0, fileFailures: [] };
4405
4727
  }
4406
4728
  const root = options.workspaceRoot ?? findWorkspaceRoot(absDir);
4407
- const manager2 = options.manager ?? getLspManager();
4729
+ const manager = options.manager ?? getLspManager();
4408
4730
  const allDiagnostics = [];
4409
4731
  const fileErrors = [];
4410
4732
  const maxConcurrency = Math.max(1, options.maxConcurrency ?? DIRECTORY_DIAGNOSTICS_MAX_CONCURRENCY);
4411
4733
  options.signal?.throwIfAborted();
4412
- const client = await manager2.getClient(root, server2, options.signal);
4734
+ const client = await manager.getClient(root, server, options.signal);
4413
4735
  try {
4414
4736
  let nextIndex = 0;
4415
4737
  const workers = Array.from({ length: Math.min(maxConcurrency, filesToProcess.length) }, async () => {
@@ -4437,7 +4759,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4437
4759
  });
4438
4760
  await Promise.all(workers);
4439
4761
  } finally {
4440
- manager2.releaseClient(root, server2.id);
4762
+ manager.releaseClient(root, server.id);
4441
4763
  }
4442
4764
  const displayDiagnostics = allDiagnostics.slice(0, DEFAULT_MAX_DIAGNOSTICS);
4443
4765
  const wasDiagCapped = allDiagnostics.length > DEFAULT_MAX_DIAGNOSTICS;
@@ -4469,7 +4791,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4469
4791
 
4470
4792
  // ../lsp-core/src/lsp/infer-extension.ts
4471
4793
  import { lstatSync as lstatSync5, readdirSync as readdirSync4 } from "node:fs";
4472
- import { join as join6 } from "node:path";
4794
+ import { join as join7 } from "node:path";
4473
4795
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
4474
4796
  var MAX_SCAN_ENTRIES = 500;
4475
4797
  function inferExtensionFromDirectory(directory) {
@@ -4487,7 +4809,7 @@ function inferExtensionFromDirectory(directory) {
4487
4809
  for (const entry of entries) {
4488
4810
  if (scanned >= MAX_SCAN_ENTRIES)
4489
4811
  return;
4490
- const fullPath = join6(dir, entry);
4812
+ const fullPath = join7(dir, entry);
4491
4813
  let stat;
4492
4814
  try {
4493
4815
  stat = lstatSync5(fullPath);
@@ -4646,8 +4968,8 @@ function clientOptions(signal) {
4646
4968
  }
4647
4969
 
4648
4970
  // ../lsp-core/src/tools/result.ts
4649
- function text(text2, details, isError = false) {
4650
- return { content: [{ type: "text", text: text2 }], details, isError };
4971
+ function text(text, details, isError = false) {
4972
+ return { content: [{ type: "text", text }], details, isError };
4651
4973
  }
4652
4974
 
4653
4975
  // ../lsp-core/src/tools/diagnostics.ts
@@ -4667,7 +4989,7 @@ async function executeLspDiagnostics(params, signal) {
4667
4989
  const extension = inferExtensionFromDirectory(absPath);
4668
4990
  if (!extension) {
4669
4991
  const message = `No supported source files found in directory: ${absPath}`;
4670
- const details3 = {
4992
+ const details = {
4671
4993
  filePath,
4672
4994
  severity,
4673
4995
  mode: "directory",
@@ -4677,24 +4999,24 @@ async function executeLspDiagnostics(params, signal) {
4677
4999
  error: message,
4678
5000
  errorKind: "no_files"
4679
5001
  };
4680
- return text(message, details3);
5002
+ return text(message, details);
4681
5003
  }
4682
- const output2 = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
4683
- const details2 = {
5004
+ const output = await aggregateDiagnosticsForDirectory(absPath, extension, severity, undefined, signal === undefined ? {} : { signal });
5005
+ const details = {
4684
5006
  filePath,
4685
5007
  severity,
4686
5008
  mode: "directory",
4687
5009
  diagnostics: [],
4688
- totalDiagnostics: output2.totalDiagnostics,
5010
+ totalDiagnostics: output.totalDiagnostics,
4689
5011
  truncated: false,
4690
- fileFailures: [...output2.fileFailures]
5012
+ fileFailures: [...output.fileFailures]
4691
5013
  };
4692
- return text(output2.output, details2);
5014
+ return text(output.output, details);
4693
5015
  }
4694
5016
  const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
4695
5017
  if (result.transientError) {
4696
5018
  const message = result.transientError.message;
4697
- const details2 = {
5019
+ const details = {
4698
5020
  filePath,
4699
5021
  severity,
4700
5022
  mode: "file",
@@ -4704,7 +5026,7 @@ async function executeLspDiagnostics(params, signal) {
4704
5026
  error: message,
4705
5027
  errorKind: result.transientError.kind
4706
5028
  };
4707
- return text(message, details2, true);
5029
+ return text(message, details, true);
4708
5030
  }
4709
5031
  const diagnostics = filterDiagnosticsBySeverity(asDiagnosticArray(result), severity);
4710
5032
  const total = diagnostics.length;
@@ -4738,6 +5060,96 @@ async function executeLspDiagnostics(params, signal) {
4738
5060
  throw error;
4739
5061
  }
4740
5062
  }
5063
+ // ../lsp-core/src/lsp/format-document.ts
5064
+ import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
5065
+ var DEFAULT_FORMATTING_OPTIONS = {
5066
+ tabSize: 4,
5067
+ insertSpaces: false,
5068
+ trimTrailingWhitespace: true,
5069
+ insertFinalNewline: true,
5070
+ trimFinalNewlines: true
5071
+ };
5072
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5073
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5074
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5075
+ if (edits === null)
5076
+ return { status: "unavailable", reason: "capability_not_advertised" };
5077
+ if (edits.length === 0)
5078
+ return UNCHANGED;
5079
+ const before = readFileSync5(filePath, "utf-8");
5080
+ const normalized = normalizeTextEdits(before, edits, 0);
5081
+ if (normalized.text === before)
5082
+ return UNCHANGED;
5083
+ writeAtomically(filePath, normalized.text);
5084
+ await client.openFile(filePath);
5085
+ return {
5086
+ status: "formatted",
5087
+ ...lineDelta(normalized.edits)
5088
+ };
5089
+ }
5090
+ function lineDelta(edits) {
5091
+ let linesAdded = 0;
5092
+ let linesRemoved = 0;
5093
+ for (const edit of edits) {
5094
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5095
+ linesAdded += edit.newText.split(`
5096
+ `).length;
5097
+ }
5098
+ return { linesAdded, linesRemoved };
5099
+ }
5100
+ function writeAtomically(filePath, content) {
5101
+ const tempPath = `${filePath}.omo-format.tmp`;
5102
+ writeFileSync3(tempPath, content, "utf-8");
5103
+ try {
5104
+ renameSync3(tempPath, filePath);
5105
+ } catch (error) {
5106
+ try {
5107
+ unlinkSync(tempPath);
5108
+ } catch {}
5109
+ throw error;
5110
+ }
5111
+ }
5112
+
5113
+ // ../lsp-core/src/tools/format.ts
5114
+ async function executeLspFormat(params, signal) {
5115
+ const filePath = requireString(params, "filePath");
5116
+ try {
5117
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5118
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5119
+ } catch (error) {
5120
+ const missingDependency = missingDependencyResult(error, {
5121
+ filePath,
5122
+ status: "unavailable",
5123
+ reason: "server_unavailable",
5124
+ linesAdded: 0,
5125
+ linesRemoved: 0
5126
+ });
5127
+ if (missingDependency)
5128
+ return missingDependency;
5129
+ throw error;
5130
+ }
5131
+ }
5132
+ function formatDetails(filePath, result) {
5133
+ if (result.status === "unavailable") {
5134
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5135
+ }
5136
+ return {
5137
+ filePath,
5138
+ status: result.status,
5139
+ linesAdded: result.linesAdded,
5140
+ linesRemoved: result.linesRemoved
5141
+ };
5142
+ }
5143
+ function describeResult(filePath, result) {
5144
+ if (result.status === "unavailable") {
5145
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5146
+ }
5147
+ if (result.status === "unchanged") {
5148
+ return `Already formatted: ${filePath}`;
5149
+ }
5150
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5151
+ }
5152
+
4741
5153
  // ../lsp-core/src/tools/install-decision.ts
4742
5154
  async function executeLspInstallDecision(params) {
4743
5155
  const serverId = requireString(params, "server_id");
@@ -4745,7 +5157,7 @@ async function executeLspInstallDecision(params) {
4745
5157
  if (!isInstallDecision(decision)) {
4746
5158
  return text(`Invalid decision '${String(decision)}'. Expected "declined" or "allowed".`, { serverId, errorKind: "invalid_decision" }, true);
4747
5159
  }
4748
- const serverIds = [...new Set(getMergedServers().map((server2) => server2.id))];
5160
+ const serverIds = [...new Set(getMergedServers().map((server) => server.id))];
4749
5161
  if (!serverIds.includes(serverId)) {
4750
5162
  const preview = serverIds.slice(0, 20).join(", ");
4751
5163
  return text(`Unknown LSP server '${serverId}'. Known servers: ${preview}${serverIds.length > 20 ? "..." : ""}`, { serverId, errorKind: "unknown_server" }, true);
@@ -4885,10 +5297,10 @@ function objectSchema(properties, required = []) {
4885
5297
  async function executeLspStatus() {
4886
5298
  const servers = getAllServers();
4887
5299
  const snapshots = getLspManager().getSnapshot();
4888
- const installed = servers.filter((server2) => server2.installed && !server2.disabled);
4889
- const configuredLines = servers.map((server2) => {
4890
- const state = server2.disabled ? "disabled" : server2.installed ? "installed" : "missing";
4891
- return `- ${server2.id}: ${state}; source=${server2.source}; extensions=${server2.extensions.join(", ")}`;
5300
+ const installed = servers.filter((server) => server.installed && !server.disabled);
5301
+ const configuredLines = servers.map((server) => {
5302
+ const state = server.disabled ? "disabled" : server.installed ? "installed" : "missing";
5303
+ return `- ${server.id}: ${state}; source=${server.source}; extensions=${server.extensions.join(", ")}`;
4892
5304
  });
4893
5305
  const activeLines = snapshots.map((snapshot) => {
4894
5306
  const state = snapshot.alive ? snapshot.isInitializing ? "initializing" : "alive" : "dead";
@@ -4931,8 +5343,8 @@ async function executeLspSymbols(params, signal) {
4931
5343
  errorKind: "missing_query"
4932
5344
  });
4933
5345
  }
4934
- const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
4935
- return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5346
+ const symbols = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5347
+ return formatSymbolsResult(filePath, scope, symbols, limit, query);
4936
5348
  }
4937
5349
  const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
4938
5350
  return formatSymbolsResult(filePath, scope, symbols, limit);
@@ -5070,6 +5482,16 @@ var LSP_MCP_TOOLS = [
5070
5482
  }, ["filePath", "line", "character", "newName"]),
5071
5483
  execute: executeLspRename
5072
5484
  },
5485
+ {
5486
+ name: "format",
5487
+ aliases: ["lsp_format"],
5488
+ title: "LSP Format",
5489
+ description: "Format a source file with its language server and write the returned edits to disk.",
5490
+ inputSchema: objectSchema({
5491
+ filePath: { type: "string", description: "Source file path to format." }
5492
+ }, ["filePath"]),
5493
+ execute: executeLspFormat
5494
+ },
5073
5495
  {
5074
5496
  name: "install_decision",
5075
5497
  aliases: ["lsp_install_decision"],
@@ -5177,7 +5599,6 @@ function requestedProtocolVersion(params) {
5177
5599
  return params["protocolVersion"];
5178
5600
  }
5179
5601
  // src/cli.ts
5180
- import { argv, stderr } from "node:process";
5181
5602
  async function main() {
5182
5603
  const [command = "mcp"] = argv.slice(2);
5183
5604
  try {