oh-my-opencode 5.0.0-beta.3 → 5.0.0-beta.31

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 (639) hide show
  1. package/.agents/command/publish.md +44 -16
  2. package/.agents/skills/publish/SKILL.md +44 -16
  3. package/.agents/skills/senpi-qa/SKILL.md +80 -0
  4. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
  5. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
  6. package/.agents/skills/work-with-pr/SKILL.md +37 -23
  7. package/.opencode/command/publish.md +44 -16
  8. package/.opencode/skills/work-with-pr/SKILL.md +37 -23
  9. package/README.ja.md +25 -21
  10. package/README.ko.md +25 -21
  11. package/README.md +38 -23
  12. package/README.ru.md +24 -20
  13. package/README.zh-cn.md +25 -21
  14. package/dist/agents/atlas/agent.d.ts +0 -1
  15. package/dist/agents/sisyphus/grok-4.d.ts +20 -0
  16. package/dist/agents/sisyphus/index.d.ts +2 -0
  17. package/dist/agents/sisyphus-agent-config.d.ts +6 -0
  18. package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
  19. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
  20. package/dist/agents/types.d.ts +2 -2
  21. package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
  22. package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
  23. package/dist/cli/fallback-lane-policy.d.ts +1 -0
  24. package/dist/cli/index.js +22601 -20302
  25. package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
  26. package/dist/cli/run/on-complete-hook.d.ts +2 -0
  27. package/dist/cli/runtime-commands.d.ts +1 -1
  28. package/dist/cli/worktree-sweep/classify.d.ts +16 -0
  29. package/dist/cli/worktree-sweep/format.d.ts +8 -0
  30. package/dist/cli/worktree-sweep/git.d.ts +19 -0
  31. package/dist/cli/worktree-sweep/index.d.ts +7 -0
  32. package/dist/cli/worktree-sweep/options.d.ts +2 -0
  33. package/dist/cli/worktree-sweep/parse-worktree-list.d.ts +8 -0
  34. package/dist/cli/worktree-sweep/sweep.d.ts +2 -0
  35. package/dist/cli/worktree-sweep/types.d.ts +65 -0
  36. package/dist/cli/worktree-sweep/worktree-sweep.d.ts +2 -0
  37. package/dist/cli-node/index.js +22219 -19897
  38. package/dist/config/schema/background-task.d.ts +1 -0
  39. package/dist/config/schema/commands.d.ts +1 -1
  40. package/dist/config/schema/hooks.d.ts +1 -1
  41. package/dist/config/schema/oh-my-opencode-config.d.ts +5 -1
  42. package/dist/config/schema/ulw-execute.d.ts +5 -0
  43. package/dist/config/validate.d.ts +2 -0
  44. package/dist/create-hooks.d.ts +3 -1
  45. package/dist/features/background-agent/constants.d.ts +0 -7
  46. package/dist/features/background-agent/manager.d.ts +2 -1
  47. package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
  48. package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
  49. package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
  50. package/dist/features/btw-side/context-injector.d.ts +15 -0
  51. package/dist/features/btw-side/index.d.ts +8 -0
  52. package/dist/features/btw-side/metadata.d.ts +15 -0
  53. package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
  54. package/dist/features/btw-side/server-session-registry.d.ts +8 -0
  55. package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
  56. package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
  57. package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
  58. package/dist/features/btw-side/tui-controller.d.ts +19 -0
  59. package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
  60. package/dist/features/btw-side/tui-keymap.d.ts +17 -0
  61. package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
  62. package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
  63. package/dist/features/btw-side/tui-picker.d.ts +9 -0
  64. package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
  65. package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
  66. package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
  67. package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
  68. package/dist/features/btw-side/tui-side-start.d.ts +9 -0
  69. package/dist/features/btw-side/tui-wiring.d.ts +8 -0
  70. package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
  71. package/dist/features/builtin-commands/types.d.ts +1 -1
  72. package/dist/features/opengateway-provider/index.d.ts +13 -0
  73. package/dist/features/task-toast-manager/manager.d.ts +0 -24
  74. package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +15 -0
  75. package/dist/hooks/anthropic-context-window-limit-recovery/message-storage-directory.d.ts +0 -3
  76. package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +1 -0
  77. package/dist/hooks/anthropic-context-window-limit-recovery/storage/empty-messages.d.ts +0 -1
  78. package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
  79. package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
  80. package/dist/hooks/atlas/event-handler.d.ts +1 -0
  81. package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
  82. package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
  83. package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
  84. package/dist/hooks/atlas/types.d.ts +1 -0
  85. package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
  86. package/dist/hooks/claude-code-hooks/stop.d.ts +2 -0
  87. package/dist/hooks/claude-code-hooks/todo.d.ts +0 -1
  88. package/dist/hooks/claude-code-hooks/transcript.d.ts +2 -0
  89. package/dist/hooks/fsync-skip-warning/index.d.ts +4 -0
  90. package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +1 -0
  91. package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +13 -0
  92. package/dist/hooks/index.d.ts +1 -1
  93. package/dist/hooks/keyword-detector/hook.d.ts +7 -0
  94. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
  95. package/dist/hooks/model-fallback/hook.d.ts +1 -1
  96. package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
  97. package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
  98. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
  99. package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
  100. package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
  101. package/dist/hooks/runtime-fallback/types.d.ts +3 -1
  102. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  103. package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
  104. package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
  105. package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
  106. package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
  107. package/dist/index.js +12989 -7152
  108. package/dist/oh-my-opencode.schema.json +20 -2
  109. package/dist/plugin/chat-message/types.d.ts +3 -3
  110. package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
  111. package/dist/plugin/event-session-lifecycle.d.ts +1 -0
  112. package/dist/plugin/hooks/create-core-hooks.d.ts +2 -1
  113. package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
  114. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  115. package/dist/plugin/messages-transform.d.ts +1 -0
  116. package/dist/plugin-dispose.d.ts +3 -0
  117. package/dist/shared/agent-tool-restrictions.d.ts +0 -1
  118. package/dist/shared/index.d.ts +2 -0
  119. package/dist/shared/legacy-plugin-warning.d.ts +2 -1
  120. package/dist/shared/normalize-sdk-response.d.ts +1 -0
  121. package/dist/shared/plugin-entry-migrator.d.ts +4 -3
  122. package/dist/shared/plugin-entry-shape.d.ts +6 -0
  123. package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
  124. package/dist/shared/shell-env.d.ts +1 -1
  125. package/dist/skills/ast-grep/AGENTS.md +51 -0
  126. package/dist/skills/coding-agent-sessions/AGENTS.md +62 -0
  127. package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
  128. package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  129. package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
  130. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  131. package/dist/skills/data-scientist/SKILL.md +99 -239
  132. package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
  133. package/dist/skills/data-scientist/references/placement.md +74 -0
  134. package/dist/skills/data-scientist/references/polars-lane.md +95 -0
  135. package/dist/skills/data-scientist/references/uv-setup.md +1 -1
  136. package/dist/skills/data-scientist/references/visualization.md +64 -0
  137. package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  138. package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  139. package/dist/skills/debugging/SKILL.md +2 -0
  140. package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
  141. package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
  142. package/dist/skills/debugging/references/runtimes/go.md +15 -1
  143. package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
  144. package/dist/skills/debugging/references/runtimes/node.md +25 -0
  145. package/dist/skills/debugging/references/runtimes/python.md +13 -0
  146. package/dist/skills/debugging/references/runtimes/rust.md +41 -0
  147. package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
  148. package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
  149. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  150. package/dist/skills/debugging/references/tools/dap.md +103 -0
  151. package/dist/skills/debugging/references/tools/frida.md +193 -0
  152. package/dist/skills/frontend/SKILL.md +11 -7
  153. package/dist/skills/frontend/references/design/_INDEX.md +1 -0
  154. package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
  155. package/dist/skills/frontend/references/design/stylegallery.md +80 -0
  156. package/dist/skills/frontend/references/designpowers/README.md +1 -1
  157. package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  158. package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  159. package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  160. package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
  161. package/dist/skills/frontend/references/designpowers/routing.md +5 -5
  162. package/dist/skills/review-work/SKILL.md +3 -3
  163. package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  164. package/dist/skills/ultimate-browsing/SKILL.md +2 -0
  165. package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  166. package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
  167. package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  168. package/dist/skills/{start-work → ulw-execute}/SKILL.md +9 -8
  169. package/dist/skills/ulw-plan/SKILL.md +6 -6
  170. package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
  171. package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
  172. package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
  173. package/dist/skills/ulw-research/SKILL.md +4 -2
  174. package/dist/skills/visual-qa/AGENTS.md +58 -0
  175. package/dist/skills/visual-qa/SKILL.md +3 -2
  176. package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
  177. package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
  178. package/dist/tools/delegate-task/sync-session-cleanup.d.ts +3 -0
  179. package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -0
  180. package/dist/tools/delegate-task/tool-description.d.ts +3 -1
  181. package/dist/tools/delegate-task/types.d.ts +4 -0
  182. package/dist/tui.d.ts +12 -0
  183. package/dist/tui.js +11522 -11501
  184. package/package.json +42 -36
  185. package/packages/git-bash-mcp/dist/cli.js +6 -1
  186. package/packages/git-bash-mcp/package.json +1 -1
  187. package/packages/lsp-core/src/index.ts +1 -0
  188. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
  189. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
  190. package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
  191. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +163 -13
  192. package/packages/lsp-core/src/lsp/client-wrapper.ts +110 -23
  193. package/packages/lsp-core/src/lsp/client.ts +26 -0
  194. package/packages/lsp-core/src/lsp/connection.ts +16 -0
  195. package/packages/lsp-core/src/lsp/constants.ts +6 -0
  196. package/packages/lsp-core/src/lsp/errors.ts +15 -0
  197. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  198. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  199. package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
  200. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  201. package/packages/lsp-core/src/lsp/manager.ts +138 -12
  202. package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
  203. package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
  204. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  205. package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
  206. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  207. package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
  208. package/packages/lsp-core/src/lsp/transport.ts +9 -0
  209. package/packages/lsp-core/src/lsp/types.ts +8 -0
  210. package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
  211. package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
  212. package/packages/lsp-core/src/mcp.ts +3 -0
  213. package/packages/lsp-core/src/request-context.test.ts +29 -0
  214. package/packages/lsp-core/src/request-context.ts +1 -1
  215. package/packages/lsp-core/src/tool-surface.test.ts +13 -1
  216. package/packages/lsp-core/src/tools/definitions.ts +14 -0
  217. package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
  218. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  219. package/packages/lsp-core/src/tools/format.ts +56 -0
  220. package/packages/lsp-core/src/tools/index.ts +1 -0
  221. package/packages/lsp-core/src/tools/navigation.ts +4 -2
  222. package/packages/lsp-core/src/tools/rename.ts +4 -2
  223. package/packages/lsp-core/src/tools/symbols.ts +1 -1
  224. package/packages/lsp-core/src/tools/types.ts +10 -0
  225. package/packages/lsp-daemon/dist/cli.js +752 -307
  226. package/packages/lsp-daemon/dist/client.d.ts +10 -0
  227. package/packages/lsp-daemon/dist/client.js +712 -264
  228. package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
  229. package/packages/lsp-daemon/dist/daemon-client.js +3 -0
  230. package/packages/lsp-daemon/dist/ensure-daemon.js +1 -0
  231. package/packages/lsp-daemon/dist/index.js +716 -273
  232. package/packages/lsp-daemon/dist/proxy.js +3 -0
  233. package/packages/lsp-daemon/dist/version-reap.js +1 -1
  234. package/packages/lsp-daemon/package.json +1 -1
  235. package/packages/lsp-tools-mcp/dist/cli.js +671 -228
  236. package/packages/lsp-tools-mcp/dist/lsp/manager.js +207 -103
  237. package/packages/lsp-tools-mcp/dist/mcp.js +673 -230
  238. package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
  239. package/packages/lsp-tools-mcp/dist/tools.js +677 -238
  240. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -4
  241. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -4
  242. package/packages/omo-codex/plugin/AGENTS.md +47 -0
  243. package/packages/omo-codex/plugin/README.md +1 -1
  244. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +34 -33
  245. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  246. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  247. package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
  248. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +323 -117
  249. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +275 -85
  250. package/packages/omo-codex/plugin/components/codegraph/package.json +4 -4
  251. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +1 -0
  252. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +12 -0
  253. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +1 -0
  254. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +47 -0
  255. package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
  256. package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
  257. package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
  258. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  259. package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
  260. package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
  261. package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
  262. package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
  263. package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
  264. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
  265. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  266. package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
  267. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
  268. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
  269. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
  270. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  271. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
  272. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +1 -5
  273. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
  274. package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
  275. package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
  276. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
  277. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +702 -278
  278. package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
  279. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  280. package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
  281. package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
  282. package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
  283. package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
  284. package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
  285. package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
  286. package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
  287. package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
  288. package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
  289. package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
  290. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  291. package/packages/omo-codex/plugin/components/rules/package.json +7 -7
  292. package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
  293. package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
  294. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +9 -5
  295. package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
  296. package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
  297. package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
  298. package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
  299. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
  300. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
  301. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
  302. package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
  303. package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
  304. package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
  305. package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
  306. package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
  307. package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
  308. package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +1 -2
  309. package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
  310. package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
  311. package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
  312. package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
  313. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +5 -6
  314. package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
  315. package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
  316. package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
  317. package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
  318. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  319. package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
  320. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +3 -9
  321. package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
  322. package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
  323. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2463 -437
  324. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
  325. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  326. package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
  327. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
  328. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
  329. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
  330. package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
  331. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -0
  332. package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
  333. package/packages/omo-codex/plugin/components/ultrawork/directive.md +13 -1
  334. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  335. package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -5
  336. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +13 -1
  337. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -6
  338. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
  339. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
  340. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
  341. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
  342. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
  343. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
  344. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +5 -4
  345. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
  346. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
  347. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
  348. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
  349. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
  350. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
  351. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
  352. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
  353. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
  354. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
  355. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
  356. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
  357. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
  358. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
  359. package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
  360. package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +17 -0
  361. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
  362. package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
  363. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +13 -1
  364. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +2 -0
  365. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
  366. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
  367. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
  368. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +124 -68
  369. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
  370. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +9 -6
  371. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +1 -1
  372. package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -1
  373. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
  374. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +7 -10
  375. package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +3 -2
  376. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
  377. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +15 -0
  378. package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +50 -0
  379. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  380. package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
  381. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
  382. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
  383. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
  384. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +2 -0
  385. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
  386. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
  387. package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
  388. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +16 -5
  389. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +3 -1
  390. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
  391. package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
  392. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +11 -14
  393. package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +3 -2
  394. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
  395. package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +73 -0
  396. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
  397. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +44 -1
  398. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
  399. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
  400. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +27 -2
  401. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +18 -0
  402. package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
  403. package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
  404. package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
  405. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
  406. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +45 -2
  407. package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +20 -0
  408. package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
  409. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
  410. package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
  411. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
  412. package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
  413. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  414. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  415. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  416. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  417. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  418. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  419. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  420. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  421. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  422. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  423. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  424. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  425. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  426. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  427. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  428. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  429. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
  430. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  431. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +17 -0
  432. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  433. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  434. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  435. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  436. package/packages/omo-codex/plugin/model-catalog.json +3 -3
  437. package/packages/omo-codex/plugin/package-lock.json +681 -395
  438. package/packages/omo-codex/plugin/package.json +2 -2
  439. package/packages/omo-codex/plugin/scripts/AGENTS.md +40 -0
  440. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -1
  441. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
  442. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +11 -11
  443. package/packages/omo-codex/plugin/shared/package.json +3 -4
  444. package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
  445. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
  446. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
  447. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  448. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
  449. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  450. package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
  451. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
  452. package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
  453. package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
  454. package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
  455. package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
  456. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  457. package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  458. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
  459. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
  460. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
  461. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
  462. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
  463. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
  464. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
  465. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
  466. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
  467. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  468. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
  469. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
  470. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
  471. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
  472. package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
  473. package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
  474. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
  475. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  476. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  477. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  478. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
  479. package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
  480. package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
  481. package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  482. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
  483. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  484. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
  485. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  486. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +13 -1
  487. package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +12 -11
  488. package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
  489. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
  490. package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
  491. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
  492. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -6
  493. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
  494. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
  495. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
  496. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
  497. package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
  498. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
  499. package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
  500. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
  501. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +8 -28
  502. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
  503. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  504. package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
  505. package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
  506. package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
  507. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
  508. package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
  509. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -1
  510. package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
  511. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -4
  512. package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
  513. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  514. package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
  515. package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
  516. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -12
  517. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
  518. package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
  519. package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
  520. package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
  521. package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
  522. package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
  523. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
  524. package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
  525. package/packages/omo-codex/scripts/AGENTS.md +36 -0
  526. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
  527. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2637 -549
  528. package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
  529. package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
  530. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
  531. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
  532. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
  533. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
  534. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
  535. package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
  536. package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
  537. package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
  538. package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
  539. package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
  540. package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
  541. package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
  542. package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
  543. package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
  544. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
  545. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
  546. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
  547. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
  548. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
  549. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
  550. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
  551. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
  552. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
  553. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
  554. package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
  555. package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
  556. package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
  557. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
  558. package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
  559. package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
  560. package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
  561. package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
  562. package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
  563. package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
  564. package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
  565. package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
  566. package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
  567. package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
  568. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
  569. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
  570. package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
  571. package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
  572. package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +9 -8
  573. package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -6
  574. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
  575. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
  576. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
  577. package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
  578. package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
  579. package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
  580. package/script/qa/web-terminal-visual-qa.mjs +2 -0
  581. package/script/qa/xterm-live-terminal.mjs +18 -2
  582. package/dist/config/schema/start-work.d.ts +0 -5
  583. package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
  584. package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
  585. package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
  586. package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
  587. package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
  588. package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
  589. package/dist/skills/data-scientist/references/execution-templates.md +0 -197
  590. package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
  591. package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
  592. package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
  593. package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
  594. package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
  595. package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
  596. package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
  597. package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
  598. package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
  599. package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
  600. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
  601. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
  602. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
  603. package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
  604. package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
  605. package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
  606. package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
  607. package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
  608. package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
  609. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
  610. package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
  611. package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
  612. package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
  613. package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
  614. package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
  615. /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
  616. /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
  617. /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
  618. /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
  619. /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
  620. /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
  621. /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
  622. /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
  623. /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
  624. /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
  625. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
  626. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
  627. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/LICENSE +0 -0
  628. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
  629. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
  630. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
  631. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
  632. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
  633. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
  634. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
  635. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
  636. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
  637. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
  638. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
  639. /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
@@ -23,28 +23,24 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
23
23
  var REQUEST_TIMEOUT_MS = 15000;
24
24
  var INIT_TIMEOUT_MS = 60000;
25
25
  var IDLE_TIMEOUT_MS = 5 * 60000;
26
+ var MAX_RESIDENT_CLIENTS = 6;
26
27
  var REAPER_INTERVAL_MS = 60000;
27
28
  var STOP_HARD_KILL_TIMEOUT_MS = 5000;
28
29
  var STOP_SIGKILL_GRACE_MS = 1000;
30
+ var CLIENT_RESPAWN_RETRY_LIMIT = 2;
31
+ var CLIENT_RESPAWN_COOLDOWN_MS = 60000;
29
32
 
30
33
  // ../lsp-core/src/lsp/errors.ts
31
34
  class LspConnectionClosedError extends Error {
32
- serverId;
33
- root;
34
- name = "LspConnectionClosedError";
35
35
  constructor(serverId, root, message) {
36
36
  super(message ?? `LSP connection closed for ${serverId} at ${root}`);
37
37
  this.serverId = serverId;
38
38
  this.root = root;
39
+ this.name = "LspConnectionClosedError";
39
40
  }
40
41
  }
41
42
 
42
43
  class LspProcessExitedError extends Error {
43
- serverId;
44
- root;
45
- exitCode;
46
- stderrTail;
47
- name = "LspProcessExitedError";
48
44
  constructor(serverId, root, exitCode, stderrTail) {
49
45
  const stderrSuffix = stderrTail ? `
50
46
  stderr tail: ${stderrTail}` : "";
@@ -53,46 +49,59 @@ stderr tail: ${stderrTail}` : "";
53
49
  this.root = root;
54
50
  this.exitCode = exitCode;
55
51
  this.stderrTail = stderrTail;
52
+ this.name = "LspProcessExitedError";
56
53
  }
57
54
  }
58
55
 
59
56
  class LspRequestTimeoutError extends Error {
60
- method;
61
- stderrTail;
62
- name = "LspRequestTimeoutError";
63
57
  constructor(method, stderrTail) {
64
58
  const stderrSuffix = stderrTail ? `
65
59
  recent stderr: ${stderrTail}` : "";
66
60
  super(`LSP request timeout (method: ${method})${stderrSuffix}`);
67
61
  this.method = method;
68
62
  this.stderrTail = stderrTail;
63
+ this.name = "LspRequestTimeoutError";
69
64
  }
70
65
  }
71
66
 
72
67
  class LspInvalidPathError extends Error {
73
- name = "LspInvalidPathError";
68
+ constructor() {
69
+ super(...arguments);
70
+ this.name = "LspInvalidPathError";
71
+ }
74
72
  }
75
73
 
76
74
  class LspServerLookupError extends Error {
77
- lookup;
78
- name = "LspServerLookupError";
79
75
  constructor(message, lookup) {
80
76
  super(message);
81
77
  this.lookup = lookup;
78
+ this.name = "LspServerLookupError";
82
79
  }
83
80
  }
84
81
 
85
82
  class LspServerInitializingError extends Error {
86
- originalError;
87
- name = "LspServerInitializingError";
88
83
  constructor(originalError) {
89
84
  super(`LSP server is still initializing. Please retry in a few seconds. Original error: ${originalError.message}`);
90
85
  this.originalError = originalError;
86
+ this.name = "LspServerInitializingError";
91
87
  }
92
88
  }
93
89
 
94
90
  class LspProcessSpawnError extends Error {
95
- name = "LspProcessSpawnError";
91
+ constructor() {
92
+ super(...arguments);
93
+ this.name = "LspProcessSpawnError";
94
+ }
95
+ }
96
+
97
+ class LspClientRespawnBudgetExceededError extends Error {
98
+ constructor(serverId, root, retryLimit) {
99
+ super(`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` + `(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`);
100
+ this.serverId = serverId;
101
+ this.root = root;
102
+ this.retryLimit = retryLimit;
103
+ this.name = "LspClientRespawnBudgetExceededError";
104
+ }
96
105
  }
97
106
  function isLspDeadConnectionError(err) {
98
107
  return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
@@ -108,20 +117,31 @@ var METHOD_NOT_FOUND = -32601;
108
117
  var INTERNAL_ERROR = -32603;
109
118
 
110
119
  class JsonRpcConnection {
111
- reader;
112
- writer;
113
- pendingRequests = new Map;
114
- notificationHandlers = new Map;
115
- requestHandlers = new Map;
116
- closeHandlers = [];
117
- errorHandlers = [];
118
- inputBuffer = Buffer.alloc(0);
119
- nextRequestId = 1;
120
- listening = false;
121
- disposed = false;
122
120
  constructor(reader, writer) {
123
121
  this.reader = reader;
124
122
  this.writer = writer;
123
+ this.pendingRequests = new Map;
124
+ this.notificationHandlers = new Map;
125
+ this.requestHandlers = new Map;
126
+ this.closeHandlers = [];
127
+ this.errorHandlers = [];
128
+ this.inputBuffer = Buffer.alloc(0);
129
+ this.nextRequestId = 1;
130
+ this.listening = false;
131
+ this.disposed = false;
132
+ this.handleData = (chunk) => {
133
+ const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
134
+ this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
135
+ this.drainInputBuffer();
136
+ };
137
+ this.handleClose = () => {
138
+ for (const handler of this.closeHandlers) {
139
+ handler();
140
+ }
141
+ };
142
+ this.handleStreamError = (error) => {
143
+ this.emitError(error);
144
+ };
125
145
  }
126
146
  listen() {
127
147
  if (this.listening)
@@ -242,19 +262,6 @@ class JsonRpcConnection {
242
262
  this.notificationHandlers.clear();
243
263
  this.requestHandlers.clear();
244
264
  }
245
- handleData = (chunk) => {
246
- const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, "utf8");
247
- this.inputBuffer = Buffer.concat([this.inputBuffer, chunkBuffer]);
248
- this.drainInputBuffer();
249
- };
250
- handleClose = () => {
251
- for (const handler of this.closeHandlers) {
252
- handler();
253
- }
254
- };
255
- handleStreamError = (error) => {
256
- this.emitError(error);
257
- };
258
265
  drainInputBuffer() {
259
266
  while (true) {
260
267
  const headerEnd = this.inputBuffer.indexOf(HEADER_SEPARATOR);
@@ -602,31 +609,26 @@ function isPosition(value) {
602
609
 
603
610
  // ../lsp-core/src/lsp/transport.ts
604
611
  class LspClientNotStartedError extends Error {
605
- serverId;
606
- root;
607
- name = "LspClientNotStartedError";
608
612
  constructor(serverId, root) {
609
613
  super("LSP client not started");
610
614
  this.serverId = serverId;
611
615
  this.root = root;
616
+ this.name = "LspClientNotStartedError";
612
617
  }
613
618
  }
614
619
 
615
620
  class LspClientTransport {
616
- root;
617
- server;
618
- proc = null;
619
- connection = null;
620
- stderrBuffer = [];
621
- processExited = false;
622
- diagnosticsStore = new Map;
623
- requestTimeoutMs;
624
- initializeTimeoutMs;
625
- workspaceApplyEditHandler = null;
626
- diagnosticPullSupported = false;
627
621
  constructor(root, server, timeouts = {}) {
628
622
  this.root = root;
629
623
  this.server = server;
624
+ this.proc = null;
625
+ this.connection = null;
626
+ this.stderrBuffer = [];
627
+ this.processExited = false;
628
+ this.diagnosticsStore = new Map;
629
+ this.workspaceApplyEditHandler = null;
630
+ this.diagnosticPullSupported = false;
631
+ this.documentFormattingSupported = false;
630
632
  this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
631
633
  this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
632
634
  }
@@ -648,6 +650,12 @@ class LspClientTransport {
648
650
  isDiagnosticPullSupported() {
649
651
  return this.diagnosticPullSupported;
650
652
  }
653
+ setDocumentFormattingSupported(supported) {
654
+ this.documentFormattingSupported = supported;
655
+ }
656
+ isDocumentFormattingSupported() {
657
+ return this.documentFormattingSupported;
658
+ }
651
659
  handlePublishDiagnostics(params) {
652
660
  this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
653
661
  }
@@ -861,6 +869,14 @@ function supportsDiagnosticPull(capabilities) {
861
869
  return false;
862
870
  return Object.hasOwn(capabilities, "diagnosticProvider");
863
871
  }
872
+ function supportsDocumentFormatting(capabilities) {
873
+ if (capabilities === undefined)
874
+ return false;
875
+ const provider = capabilities.documentFormattingProvider;
876
+ if (provider === undefined || provider === null || provider === false)
877
+ return false;
878
+ return provider === true || typeof provider === "object";
879
+ }
864
880
 
865
881
  class LspClientConnection extends LspClientTransport {
866
882
  async initialize() {
@@ -877,6 +893,7 @@ class LspClientConnection extends LspClientTransport {
877
893
  references: {},
878
894
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
879
895
  publishDiagnostics: {},
896
+ formatting: { dynamicRegistration: false },
880
897
  rename: {
881
898
  prepareSupport: true,
882
899
  prepareSupportDefaultBehavior: 1
@@ -918,6 +935,7 @@ class LspClientConnection extends LspClientTransport {
918
935
  initializationOptions: this.server.initialization
919
936
  }, { timeoutMs: this.initializeTimeoutMs });
920
937
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
938
+ this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
921
939
  await this.sendNotification("initialized", {});
922
940
  await this.sendNotification("workspace/didChangeConfiguration", {
923
941
  settings: { json: { validate: { enable: true } } }
@@ -1133,16 +1151,12 @@ function movedPath(candidate, oldPath, newPath) {
1133
1151
  }
1134
1152
 
1135
1153
  class WorkspaceDocumentState {
1136
- sendNotification;
1137
- clearDiagnostics;
1138
- openDocuments = new Map;
1139
- openByUri = new Map;
1140
- openPromises = new Map;
1141
- now;
1142
- versionlessPublishQuiescenceMs;
1143
1154
  constructor(sendNotification, clearDiagnostics, options = {}) {
1144
1155
  this.sendNotification = sendNotification;
1145
1156
  this.clearDiagnostics = clearDiagnostics;
1157
+ this.openDocuments = new Map;
1158
+ this.openByUri = new Map;
1159
+ this.openPromises = new Map;
1146
1160
  this.now = options.now ?? (() => Date.now());
1147
1161
  this.versionlessPublishQuiescenceMs = options.versionlessPublishQuiescenceMs ?? DEFAULT_VERSIONLESS_PUBLISH_QUIESCENCE_MS;
1148
1162
  }
@@ -1406,13 +1420,11 @@ import { dirname, isAbsolute, relative as relative2, resolve as resolve2 } from
1406
1420
  import { fileURLToPath } from "node:url";
1407
1421
 
1408
1422
  class WorkspaceEditPathError extends Error {
1409
- path;
1410
- detail;
1411
- name = "WorkspaceEditPathError";
1412
1423
  constructor(path, detail) {
1413
1424
  super(`${detail}: ${path}`);
1414
1425
  this.path = path;
1415
1426
  this.detail = detail;
1427
+ this.name = "WorkspaceEditPathError";
1416
1428
  }
1417
1429
  }
1418
1430
  function isPathInsideWorkspace(filePath, workspaceRoot) {
@@ -1704,13 +1716,11 @@ function canonicalFingerprint(operations) {
1704
1716
 
1705
1717
  // ../lsp-core/src/lsp/workspace-edit-types.ts
1706
1718
  class WorkspaceEditValidationError extends Error {
1707
- changeIndex;
1708
- detail;
1709
- name = "WorkspaceEditValidationError";
1710
1719
  constructor(changeIndex, detail) {
1711
1720
  super(`change ${changeIndex}: ${detail}`);
1712
1721
  this.changeIndex = changeIndex;
1713
1722
  this.detail = detail;
1723
+ this.name = "WorkspaceEditValidationError";
1714
1724
  }
1715
1725
  }
1716
1726
 
@@ -2208,10 +2218,9 @@ function simulateDelete(operation, virtual) {
2208
2218
  import { existsSync as existsSync4, lstatSync as lstatSync3, readdirSync as readdirSync2 } from "node:fs";
2209
2219
  import { dirname as dirname3, resolve as resolve4 } from "node:path";
2210
2220
  class WorkspaceSnapshotBuilder {
2211
- workspaceRoot;
2212
- snapshots = new Map;
2213
2221
  constructor(workspaceRoot) {
2214
2222
  this.workspaceRoot = workspaceRoot;
2223
+ this.snapshots = new Map;
2215
2224
  }
2216
2225
  build(operations) {
2217
2226
  this.add(this.workspaceRoot, false);
@@ -2255,8 +2264,10 @@ function snapshotOperations(operations, workspaceRoot) {
2255
2264
 
2256
2265
  // ../lsp-core/src/lsp/workspace-edit-plan.ts
2257
2266
  class PlanPathIndex {
2258
- firstChangeByPath = new Map;
2259
- reportedPathByCanonical = new Map;
2267
+ constructor() {
2268
+ this.firstChangeByPath = new Map;
2269
+ this.reportedPathByCanonical = new Map;
2270
+ }
2260
2271
  build(operations) {
2261
2272
  for (const operation of operations) {
2262
2273
  switch (operation.kind) {
@@ -2345,14 +2356,11 @@ function isRecord3(value) {
2345
2356
  }
2346
2357
 
2347
2358
  class WorkspaceMutationController {
2348
- workspaceRoot;
2349
- documents;
2350
- activeLease = null;
2351
- nextLeaseId = 1;
2352
- io;
2353
2359
  constructor(workspaceRoot, documents) {
2354
2360
  this.workspaceRoot = workspaceRoot;
2355
2361
  this.documents = documents;
2362
+ this.activeLease = null;
2363
+ this.nextLeaseId = 1;
2356
2364
  }
2357
2365
  setIo(io) {
2358
2366
  this.io = io;
@@ -2465,12 +2473,9 @@ var DIAGNOSTICS_FRESHNESS_TIMEOUT_MS = 3000;
2465
2473
  var VERSIONLESS_PUBLISH_QUIESCENCE_MS = 250;
2466
2474
 
2467
2475
  class LspClient extends LspClientConnection {
2468
- diagnosticPullErrors = [];
2469
- documents;
2470
- workspaceMutations;
2471
- diagnosticsFreshnessTimeoutMs;
2472
2476
  constructor(root, server, options = {}) {
2473
2477
  super(root, server, options);
2478
+ this.diagnosticPullErrors = [];
2474
2479
  this.diagnosticsFreshnessTimeoutMs = options.diagnosticsFreshnessTimeoutMs ?? DIAGNOSTICS_FRESHNESS_TIMEOUT_MS;
2475
2480
  this.documents = new WorkspaceDocumentState((method, params) => this.sendNotification(method, params), (uri) => this.diagnosticsStore.delete(uri), {
2476
2481
  versionlessPublishQuiescenceMs: options.versionlessPublishQuiescenceMs ?? VERSIONLESS_PUBLISH_QUIESCENCE_MS
@@ -2525,6 +2530,18 @@ class LspClient extends LspClientConnection {
2525
2530
  textDocument: { uri: pathToFileURL3(absPath).href }
2526
2531
  }, options);
2527
2532
  }
2533
+ async formatDocument(filePath, options, signal) {
2534
+ if (!this.isDocumentFormattingSupported())
2535
+ return null;
2536
+ const absPath = this.resolveWorkspacePath(filePath);
2537
+ await this.openFile(absPath);
2538
+ const requestOptions = signal === undefined ? {} : { signal };
2539
+ const edits = await this.sendRequest("textDocument/formatting", {
2540
+ textDocument: { uri: pathToFileURL3(absPath).href },
2541
+ options
2542
+ }, requestOptions);
2543
+ return edits ?? [];
2544
+ }
2528
2545
  async workspaceSymbols(query, signal) {
2529
2546
  const options = signal === undefined ? {} : { signal };
2530
2547
  return this.sendRequest("workspace/symbol", { query }, options);
@@ -2770,18 +2787,16 @@ function awaitWithSignal(promise, signal) {
2770
2787
  }
2771
2788
 
2772
2789
  class LspManager {
2773
- clients = new Map;
2774
- reaperHandle = null;
2775
- signalDisposer = null;
2776
- disposed = false;
2777
- idleTimeoutMs;
2778
- initTimeoutMs;
2779
- reaperIntervalMs;
2780
- clientFactory;
2781
- now;
2782
2790
  constructor(options = {}) {
2791
+ this.clients = new Map;
2792
+ this.pendingStops = new Map;
2793
+ this.respawnBudgets = new Map;
2794
+ this.reaperHandle = null;
2795
+ this.signalDisposer = null;
2796
+ this.disposed = false;
2783
2797
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
2784
2798
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
2799
+ this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
2785
2800
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
2786
2801
  this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
2787
2802
  this.now = options.now ?? (() => Date.now());
@@ -2801,24 +2816,79 @@ class LspManager {
2801
2816
  getKey(root, serverId) {
2802
2817
  return `${root}::${serverId}`;
2803
2818
  }
2819
+ tombstoneStop(key, client) {
2820
+ const stop = stopClientBestEffort(client);
2821
+ this.pendingStops.set(key, stop);
2822
+ stop.finally(() => {
2823
+ if (this.pendingStops.get(key) === stop) {
2824
+ this.pendingStops.delete(key);
2825
+ }
2826
+ });
2827
+ return stop;
2828
+ }
2829
+ recordDeadGeneration(key) {
2830
+ let budget = this.respawnBudgets.get(key);
2831
+ if (budget === undefined) {
2832
+ budget = { deadGenerations: 0, exhaustedAt: null };
2833
+ this.respawnBudgets.set(key, budget);
2834
+ }
2835
+ budget.deadGenerations += 1;
2836
+ }
2837
+ markHealthyGeneration(key) {
2838
+ this.respawnBudgets.delete(key);
2839
+ }
2840
+ ensureRespawnAllowed(key, root, serverId) {
2841
+ const budget = this.respawnBudgets.get(key);
2842
+ if (budget === undefined || budget.deadGenerations < CLIENT_RESPAWN_RETRY_LIMIT)
2843
+ return;
2844
+ if (budget.exhaustedAt === null) {
2845
+ budget.exhaustedAt = this.now();
2846
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
2847
+ }
2848
+ if (this.now() - budget.exhaustedAt < CLIENT_RESPAWN_COOLDOWN_MS) {
2849
+ throw new LspClientRespawnBudgetExceededError(serverId, root, CLIENT_RESPAWN_RETRY_LIMIT);
2850
+ }
2851
+ budget.deadGenerations = 0;
2852
+ budget.exhaustedAt = null;
2853
+ }
2804
2854
  reapStale() {
2805
2855
  const t = this.now();
2806
2856
  for (const [key, managed] of this.clients) {
2807
2857
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
2808
- stopClientBestEffort(managed.client);
2809
2858
  this.clients.delete(key);
2859
+ this.tombstoneStop(key, managed.client);
2810
2860
  continue;
2811
2861
  }
2812
2862
  if (!managed.isInitializing && managed.refCount === 0 && managed.pendingWaiters === 0 && t - managed.lastUsedAt > this.idleTimeoutMs) {
2813
- stopClientBestEffort(managed.client);
2814
2863
  this.clients.delete(key);
2864
+ this.tombstoneStop(key, managed.client);
2815
2865
  }
2816
2866
  }
2817
2867
  }
2868
+ evictForAdmission() {
2869
+ while (this.clients.size >= this.maxResidentClients) {
2870
+ const victim = this.leastRecentlyUsedIdleClient();
2871
+ if (!victim)
2872
+ return;
2873
+ this.clients.delete(victim.key);
2874
+ this.tombstoneStop(victim.key, victim.managed.client);
2875
+ }
2876
+ }
2877
+ leastRecentlyUsedIdleClient() {
2878
+ let candidate = null;
2879
+ for (const [key, managed] of this.clients) {
2880
+ if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
2881
+ continue;
2882
+ if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
2883
+ candidate = { key, managed };
2884
+ }
2885
+ }
2886
+ return candidate;
2887
+ }
2818
2888
  async tryDeleteIfOrphaned(key, managed) {
2819
2889
  if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
2820
2890
  this.clients.delete(key);
2821
- await stopClientBestEffort(managed.client);
2891
+ await this.tombstoneStop(key, managed.client);
2822
2892
  }
2823
2893
  }
2824
2894
  async getClient(root, server, signal) {
@@ -2827,12 +2897,22 @@ class LspManager {
2827
2897
  }
2828
2898
  signal?.throwIfAborted();
2829
2899
  const key = this.getKey(root, server.id);
2900
+ for (;; ) {
2901
+ const pendingStop = this.pendingStops.get(key);
2902
+ if (pendingStop === undefined)
2903
+ break;
2904
+ await awaitWithSignal(pendingStop, signal);
2905
+ signal?.throwIfAborted();
2906
+ }
2907
+ if (this.disposed) {
2908
+ throw new Error("LspManager has been disposed");
2909
+ }
2830
2910
  let managed = this.clients.get(key);
2831
2911
  if (managed) {
2832
2912
  const t = this.now();
2833
2913
  if (managed.isInitializing && managed.initializingSince !== null && t - managed.initializingSince > this.initTimeoutMs) {
2834
- await stopClientBestEffort(managed.client);
2835
2914
  this.clients.delete(key);
2915
+ await this.tombstoneStop(key, managed.client);
2836
2916
  managed = undefined;
2837
2917
  }
2838
2918
  }
@@ -2853,14 +2933,20 @@ class LspManager {
2853
2933
  signal.throwIfAborted();
2854
2934
  }
2855
2935
  if (!managed.client.isAlive()) {
2856
- await stopClientBestEffort(managed.client);
2857
- this.clients.delete(key);
2936
+ this.recordDeadGeneration(key);
2937
+ if (this.clients.get(key) === managed) {
2938
+ this.clients.delete(key);
2939
+ }
2940
+ await this.tombstoneStop(key, managed.client);
2858
2941
  return this.getClient(root, server, signal);
2859
2942
  }
2943
+ this.markHealthyGeneration(key);
2860
2944
  managed.refCount++;
2861
2945
  managed.lastUsedAt = this.now();
2862
2946
  return managed.client;
2863
2947
  }
2948
+ this.evictForAdmission();
2949
+ this.ensureRespawnAllowed(key, root, server.id);
2864
2950
  const client = this.clientFactory(root, server);
2865
2951
  const initStartedAt = this.now();
2866
2952
  const initPromise = (async () => {
@@ -2884,7 +2970,7 @@ class LspManager {
2884
2970
  if (this.clients.get(key) === newManaged) {
2885
2971
  this.clients.delete(key);
2886
2972
  }
2887
- await stopClientBestEffort(client);
2973
+ await this.tombstoneStop(key, client);
2888
2974
  throw err;
2889
2975
  }
2890
2976
  newManaged.pendingWaiters--;
@@ -2895,6 +2981,15 @@ class LspManager {
2895
2981
  await this.tryDeleteIfOrphaned(key, newManaged);
2896
2982
  signal.throwIfAborted();
2897
2983
  }
2984
+ if (!client.isAlive()) {
2985
+ this.recordDeadGeneration(key);
2986
+ if (this.clients.get(key) === newManaged) {
2987
+ this.clients.delete(key);
2988
+ }
2989
+ await this.tombstoneStop(key, client);
2990
+ return this.getClient(root, server, signal);
2991
+ }
2992
+ this.markHealthyGeneration(key);
2898
2993
  newManaged.refCount++;
2899
2994
  newManaged.lastUsedAt = this.now();
2900
2995
  return client;
@@ -2915,14 +3010,20 @@ class LspManager {
2915
3010
  if (client && managed.client !== client)
2916
3011
  return;
2917
3012
  this.clients.delete(key);
2918
- stopClientBestEffort(managed.client);
3013
+ this.tombstoneStop(key, managed.client);
2919
3014
  }
2920
3015
  warmupClient(root, server) {
2921
3016
  if (this.disposed)
2922
3017
  return;
2923
3018
  const key = this.getKey(root, server.id);
2924
- if (this.clients.has(key))
3019
+ if (this.clients.has(key) || this.pendingStops.has(key))
2925
3020
  return;
3021
+ this.evictForAdmission();
3022
+ try {
3023
+ this.ensureRespawnAllowed(key, root, server.id);
3024
+ } catch {
3025
+ return;
3026
+ }
2926
3027
  const client = this.clientFactory(root, server);
2927
3028
  const initStartedAt = this.now();
2928
3029
  const initPromise = (async () => {
@@ -2948,7 +3049,7 @@ class LspManager {
2948
3049
  if (this.clients.get(key) === managed) {
2949
3050
  this.clients.delete(key);
2950
3051
  }
2951
- stopClientBestEffort(client);
3052
+ this.tombstoneStop(key, client);
2952
3053
  });
2953
3054
  }
2954
3055
  isServerInitializing(root, serverId) {
@@ -2992,8 +3093,11 @@ class LspManager {
2992
3093
  for (const managed of this.clients.values()) {
2993
3094
  stopPromises.push(stopClientBestEffort(managed.client));
2994
3095
  }
3096
+ const tombstonedStops = [...this.pendingStops.values()];
2995
3097
  this.clients.clear();
2996
- await Promise.allSettled(stopPromises);
3098
+ this.respawnBudgets.clear();
3099
+ await Promise.allSettled([...stopPromises, ...tombstonedStops]);
3100
+ this.pendingStops.clear();
2997
3101
  }
2998
3102
  }
2999
3103
  var _defaultInstance = null;
@@ -3013,7 +3117,7 @@ async function disposeDefaultLspManager() {
3013
3117
  // src/daemon-client.ts
3014
3118
  import { connect } from "node:net";
3015
3119
  import { homedir as homedir3 } from "node:os";
3016
- import { join as join7 } from "node:path";
3120
+ import { join as join8 } from "node:path";
3017
3121
 
3018
3122
  // ../lsp-core/src/request-context.ts
3019
3123
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -3022,18 +3126,17 @@ import { homedir } from "node:os";
3022
3126
  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";
3023
3127
 
3024
3128
  class LspRequestContextParseError extends Error {
3025
- code;
3026
- name = "LspRequestContextParseError";
3027
3129
  constructor(code, message) {
3028
3130
  super(message);
3029
3131
  this.code = code;
3132
+ this.name = "LspRequestContextParseError";
3030
3133
  }
3031
3134
  }
3032
3135
 
3033
3136
  class LspRequestContextUnavailableError extends Error {
3034
- name = "LspRequestContextUnavailableError";
3035
3137
  constructor() {
3036
3138
  super("LSP request context is required. Standalone MCP startup must install one with runWithRequestContext(createStandaloneMcpRequestContext()).");
3139
+ this.name = "LspRequestContextUnavailableError";
3037
3140
  }
3038
3141
  }
3039
3142
  var storage = new AsyncLocalStorage;
@@ -3053,7 +3156,7 @@ function contextCwd() {
3053
3156
  }
3054
3157
  function createStandaloneMcpRequestContext(input = {}) {
3055
3158
  const env = input.env ?? process.env;
3056
- const cwd = canonicalCwd(input.cwd ?? process.cwd());
3159
+ const cwd = canonicalCwd(input.cwd ?? env["LSP_TOOLS_MCP_CWD"] ?? process.cwd());
3057
3160
  const home = input.homeDir ?? homedir();
3058
3161
  const projectConfigPaths = translateProjectConfigEnv(env["LSP_TOOLS_MCP_PROJECT_CONFIG"], cwd);
3059
3162
  const userConfigPath = translateHomeConfigEnv(env["LSP_TOOLS_MCP_USER_CONFIG"], home, ".codex/lsp-client.json");
@@ -3191,7 +3294,6 @@ function isPlainRecord(value) {
3191
3294
 
3192
3295
  // src/daemon-request-error.ts
3193
3296
  class DaemonRequestError extends Error {
3194
- requestWritten;
3195
3297
  constructor(message, requestWritten) {
3196
3298
  super(message);
3197
3299
  this.name = "DaemonRequestError";
@@ -3214,7 +3316,6 @@ class DaemonRequestCancelledError extends DaemonRequestError {
3214
3316
  }
3215
3317
 
3216
3318
  class DaemonRequestTimedOutError extends DaemonRequestError {
3217
- timeoutMs;
3218
3319
  constructor(requestWritten, timeoutMs) {
3219
3320
  super("daemon request timed out", requestWritten);
3220
3321
  this.name = "DaemonRequestTimedOutError";
@@ -3293,14 +3394,12 @@ var PROTOCOL_ERROR_CODE = -32002;
3293
3394
  var AUTH_TOKEN_BYTES = 32;
3294
3395
 
3295
3396
  class UnsafePrivateDirectoryError extends Error {
3296
- path;
3297
- reason;
3298
- name = "UnsafePrivateDirectoryError";
3299
- code = "unsafe_private_directory";
3300
3397
  constructor(path, reason) {
3301
3398
  super(`unsafe private directory ${path}: ${reason}`);
3302
3399
  this.path = path;
3303
3400
  this.reason = reason;
3401
+ this.name = "UnsafePrivateDirectoryError";
3402
+ this.code = "unsafe_private_directory";
3304
3403
  }
3305
3404
  }
3306
3405
  function authEnvelope(token) {
@@ -3484,20 +3583,18 @@ var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
3484
3583
  var DAEMON_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
3485
3584
 
3486
3585
  class InvalidRuntimeOverrideError extends Error {
3487
- code = "invalid_runtime_override";
3488
- reason;
3489
3586
  constructor(reason, message) {
3490
3587
  super(message);
3588
+ this.code = "invalid_runtime_override";
3491
3589
  this.name = "InvalidRuntimeOverrideError";
3492
3590
  this.reason = reason;
3493
3591
  }
3494
3592
  }
3495
3593
 
3496
3594
  class InvalidDaemonVersionError extends Error {
3497
- code = "invalid_daemon_version";
3498
- version;
3499
3595
  constructor(version) {
3500
3596
  super("LSP daemon version must match [A-Za-z0-9][A-Za-z0-9._+-]{0,127}");
3597
+ this.code = "invalid_daemon_version";
3501
3598
  this.name = "InvalidDaemonVersionError";
3502
3599
  this.version = version;
3503
3600
  }
@@ -3543,10 +3640,9 @@ var requireFromHere = createRequire(import.meta.url);
3543
3640
  var MAX_SOCKET_PATH_LENGTH = 100;
3544
3641
 
3545
3642
  class InvalidDaemonDirectoryError extends Error {
3546
- code = "invalid_daemon_directory";
3547
- directory;
3548
3643
  constructor(directory) {
3549
3644
  super(`${OMO_LSP_DAEMON_DIR} must be an absolute path`);
3645
+ this.code = "invalid_daemon_directory";
3550
3646
  this.name = "InvalidDaemonDirectoryError";
3551
3647
  this.directory = directory;
3552
3648
  }
@@ -3741,7 +3837,8 @@ function spawnDaemonProcess(paths) {
3741
3837
  try {
3742
3838
  const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
3743
3839
  detached: true,
3744
- stdio: ["ignore", logFd, logFd]
3840
+ stdio: ["ignore", logFd, logFd],
3841
+ windowsHide: true
3745
3842
  });
3746
3843
  child.once("spawn", () => closeSync2(logFd));
3747
3844
  child.once("error", (error) => {
@@ -4022,6 +4119,7 @@ async function runJsonRpcStdioServer(config) {
4022
4119
  const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
4023
4120
  isClosed = true;
4024
4121
  config.onIdleTimeout?.();
4122
+ config.input.destroy();
4025
4123
  });
4026
4124
  const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
4027
4125
  isClosed = true;
@@ -4118,7 +4216,11 @@ function createParentWatchdog(config, onDeadParent) {
4118
4216
  const probeAlive = config.probeAlive ?? isProcessAlive;
4119
4217
  let fired = false;
4120
4218
  const timer = setInterval(() => {
4121
- if (fired || probeAlive(parentPid))
4219
+ if (fired)
4220
+ return;
4221
+ const alive = probeAlive(parentPid);
4222
+ config.onPoll?.(alive);
4223
+ if (alive)
4122
4224
  return;
4123
4225
  fired = true;
4124
4226
  onDeadParent(parentPid, pollIntervalMs);
@@ -4153,60 +4255,55 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
4153
4255
  };
4154
4256
  }
4155
4257
  // ../lsp-core/src/lsp/client-wrapper.ts
4156
- import { existsSync as existsSync10, statSync as statSync4 } from "node:fs";
4157
- import { dirname as dirname8, join as join4, resolve as resolve7 } from "node:path";
4258
+ import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync4 } from "node:fs";
4259
+ import { basename as basename3, dirname as dirname10, join as join5, resolve as resolve8 } from "node:path";
4158
4260
 
4159
- // ../lsp-core/src/lsp/server-install-state.ts
4160
- import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4161
- import { dirname as dirname7 } from "node:path";
4162
- function getInstallDecisionsPath() {
4163
- return lspRequestContext().installDecisionsPath;
4164
- }
4165
- function loadInstallDecisions() {
4166
- const path2 = getInstallDecisionsPath();
4167
- if (!existsSync7(path2))
4168
- return {};
4169
- try {
4170
- const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4171
- return isInstallDecisions(parsed) ? parsed : {};
4172
- } catch {
4173
- return {};
4261
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4262
+ import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
4263
+ import { dirname as dirname7, join as join3 } from "node:path";
4264
+
4265
+ // ../lsp-core/src/lsp/workspace-markers.ts
4266
+ var GIT_WORKSPACE_MARKER = ".git";
4267
+ var PROJECT_WORKSPACE_MARKERS = [
4268
+ "package.json",
4269
+ "pyproject.toml",
4270
+ "Cargo.toml",
4271
+ "go.mod",
4272
+ "pom.xml",
4273
+ "build.gradle"
4274
+ ];
4275
+ var WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS];
4276
+
4277
+ // ../lsp-core/src/lsp/outside-context-workspace.ts
4278
+ function findWorkspaceRootOutsideContext(directory) {
4279
+ const marked = nearestMarkedAncestor(directory);
4280
+ if (marked !== undefined)
4281
+ return marked;
4282
+ return realpathSync4(nearestExistingAncestor(directory));
4283
+ }
4284
+ function nearestMarkedAncestor(directory) {
4285
+ let current = directory;
4286
+ for (;; ) {
4287
+ if (existsSync7(current) && WORKSPACE_MARKERS.some((marker) => existsSync7(join3(current, marker)))) {
4288
+ return realpathSync4(current);
4289
+ }
4290
+ const parent = dirname7(current);
4291
+ if (parent === current)
4292
+ return;
4293
+ current = parent;
4174
4294
  }
4175
4295
  }
4176
- function loadInstallDecision(serverId) {
4177
- return loadInstallDecisions()[serverId];
4178
- }
4179
- function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4180
- const decisions = loadInstallDecisions();
4181
- decisions[serverId] = { decision, decidedAt };
4182
- writeInstallDecisions(decisions);
4183
- }
4184
- function isInstallDecision(value) {
4185
- return value === "declined" || value === "allowed";
4186
- }
4187
- function writeInstallDecisions(decisions) {
4188
- const path2 = getInstallDecisionsPath();
4189
- mkdirSync3(dirname7(path2), { recursive: true });
4190
- const tmpPath = `${path2}.tmp`;
4191
- writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4192
- `, "utf8");
4193
- renameSync2(tmpPath, path2);
4194
- }
4195
- function isInstallDecisions(value) {
4196
- return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4197
- }
4198
- function isInstallDecisionRecord(value) {
4199
- if (!isRecord5(value))
4200
- return false;
4201
- return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4202
- }
4203
- function isRecord5(value) {
4204
- return typeof value === "object" && value !== null && !Array.isArray(value);
4296
+ function nearestExistingAncestor(directory) {
4297
+ let current = directory;
4298
+ while (!existsSync7(current)) {
4299
+ const parent = dirname7(current);
4300
+ if (parent === current)
4301
+ return current;
4302
+ current = parent;
4303
+ }
4304
+ return current;
4205
4305
  }
4206
4306
 
4207
- // ../lsp-core/src/lsp/config-loader.ts
4208
- import { existsSync as existsSync8, readFileSync as readFileSync5 } from "node:fs";
4209
-
4210
4307
  // ../lsp-core/src/lsp/server-definitions.ts
4211
4308
  var LSP_INSTALL_HINTS = {
4212
4309
  typescript: "npm install -g typescript-language-server typescript",
@@ -4252,6 +4349,26 @@ var LSP_INSTALL_HINTS = {
4252
4349
  julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
4253
4350
  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"
4254
4351
  };
4352
+ var LSP_LOCAL_INSTALL_HINTS = {
4353
+ typescript: "bun add -d typescript-language-server typescript",
4354
+ vue: "bun add -d @vue/language-server",
4355
+ eslint: "bun add -d vscode-langservers-extracted",
4356
+ oxlint: "bun add -d oxlint",
4357
+ biome: "bun add -d @biomejs/biome",
4358
+ svelte: "bun add -d svelte-language-server",
4359
+ astro: "bun add -d @astrojs/language-server",
4360
+ bash: "bun add -d bash-language-server",
4361
+ "bash-ls": "bun add -d bash-language-server",
4362
+ "yaml-ls": "bun add -d yaml-language-server",
4363
+ php: "bun add -d intelephense",
4364
+ prisma: "bun add -d prisma",
4365
+ dockerfile: "bun add -d dockerfile-language-server-nodejs",
4366
+ pyright: "uv add --dev pyright",
4367
+ basedpyright: "uv add --dev basedpyright",
4368
+ ruff: "uv add --dev ruff",
4369
+ ty: "uv add --dev ty",
4370
+ "ruby-lsp": "bundle add ruby-lsp --group development"
4371
+ };
4255
4372
  var BUILTIN_SERVERS = {
4256
4373
  typescript: {
4257
4374
  command: ["typescript-language-server", "--stdio"],
@@ -4354,7 +4471,56 @@ var BUILTIN_SERVERS = {
4354
4471
  }
4355
4472
  };
4356
4473
 
4474
+ // ../lsp-core/src/lsp/server-install-state.ts
4475
+ import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync4, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
4476
+ import { dirname as dirname8 } from "node:path";
4477
+ function getInstallDecisionsPath() {
4478
+ return lspRequestContext().installDecisionsPath;
4479
+ }
4480
+ function loadInstallDecisions() {
4481
+ const path2 = getInstallDecisionsPath();
4482
+ if (!existsSync8(path2))
4483
+ return {};
4484
+ try {
4485
+ const parsed = JSON.parse(readFileSync4(path2, "utf8"));
4486
+ return isInstallDecisions(parsed) ? parsed : {};
4487
+ } catch {
4488
+ return {};
4489
+ }
4490
+ }
4491
+ function loadInstallDecision(serverId) {
4492
+ return loadInstallDecisions()[serverId];
4493
+ }
4494
+ function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
4495
+ const decisions = loadInstallDecisions();
4496
+ decisions[serverId] = { decision, decidedAt };
4497
+ writeInstallDecisions(decisions);
4498
+ }
4499
+ function isInstallDecision(value) {
4500
+ return value === "declined" || value === "allowed";
4501
+ }
4502
+ function writeInstallDecisions(decisions) {
4503
+ const path2 = getInstallDecisionsPath();
4504
+ mkdirSync3(dirname8(path2), { recursive: true });
4505
+ const tmpPath = `${path2}.tmp`;
4506
+ writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
4507
+ `, "utf8");
4508
+ renameSync2(tmpPath, path2);
4509
+ }
4510
+ function isInstallDecisions(value) {
4511
+ return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
4512
+ }
4513
+ function isInstallDecisionRecord(value) {
4514
+ if (!isRecord5(value))
4515
+ return false;
4516
+ return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
4517
+ }
4518
+ function isRecord5(value) {
4519
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4520
+ }
4521
+
4357
4522
  // ../lsp-core/src/lsp/config-loader.ts
4523
+ import { existsSync as existsSync9, readFileSync as readFileSync5 } from "node:fs";
4358
4524
  function getProjectConfigPaths() {
4359
4525
  return lspRequestContext().projectConfigPaths;
4360
4526
  }
@@ -4362,7 +4528,7 @@ function getUserConfigPath() {
4362
4528
  return lspRequestContext().userConfigPath;
4363
4529
  }
4364
4530
  function loadJsonFile(path2) {
4365
- if (!existsSync8(path2))
4531
+ if (!existsSync9(path2))
4366
4532
  return null;
4367
4533
  try {
4368
4534
  const parsed = JSON.parse(readFileSync5(path2, "utf-8"));
@@ -4550,54 +4716,155 @@ function getDisabledServerIds() {
4550
4716
  }
4551
4717
 
4552
4718
  // ../lsp-core/src/lsp/server-installation.ts
4553
- import { existsSync as existsSync9 } from "node:fs";
4554
- import { delimiter as delimiter3, join as join3 } from "node:path";
4555
- function isServerInstalled(command, _workingDirectory) {
4556
- if (command.length === 0)
4557
- return false;
4558
- const [cmd] = command;
4559
- if (!cmd)
4560
- return false;
4561
- if (cmd.includes("/") || cmd.includes("\\")) {
4562
- if (existsSync9(cmd))
4563
- return true;
4719
+ import { existsSync as existsSync10 } from "node:fs";
4720
+ import { delimiter as delimiter3, dirname as dirname9, isAbsolute as isAbsolute5, join as join4, resolve as resolve7 } from "node:path";
4721
+ var LOCAL_BIN_RULES = [
4722
+ {
4723
+ markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
4724
+ binDirs: [join4("node_modules", ".bin")]
4725
+ },
4726
+ {
4727
+ markers: [
4728
+ "pyproject.toml",
4729
+ "ty.toml",
4730
+ "requirements.txt",
4731
+ "setup.py",
4732
+ "setup.cfg",
4733
+ "Pipfile",
4734
+ "pyrightconfig.json",
4735
+ "ruff.toml",
4736
+ ".ruff.toml"
4737
+ ],
4738
+ binDirs: [
4739
+ join4(".venv", "bin"),
4740
+ join4(".venv", "Scripts"),
4741
+ join4("venv", "bin"),
4742
+ join4("venv", "Scripts"),
4743
+ join4(".env", "bin"),
4744
+ join4(".env", "Scripts")
4745
+ ]
4746
+ },
4747
+ {
4748
+ markers: ["Gemfile", "Gemfile.lock"],
4749
+ binDirs: [join4("vendor", "bundle", "bin"), "bin"]
4750
+ },
4751
+ {
4752
+ markers: ["go.mod", "go.sum", "go.work"],
4753
+ binDirs: ["bin"]
4564
4754
  }
4565
- const isWindows = process.platform === "win32";
4566
- let exts = [""];
4567
- if (isWindows) {
4568
- const pathExt = process.env["PATHEXT"] ?? "";
4569
- if (pathExt) {
4570
- const systemExts = pathExt.split(";").filter(Boolean);
4571
- exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4572
- } else {
4573
- exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
4755
+ ];
4756
+ var resolutionCache = new Map;
4757
+ var probeCount = 0;
4758
+ function probe(path2) {
4759
+ probeCount += 1;
4760
+ return existsSync10(path2);
4761
+ }
4762
+ function executableSuffixes(platform, pathExt) {
4763
+ if (platform !== "win32")
4764
+ return [""];
4765
+ const configured = pathExt ?? process.env["PATHEXT"] ?? "";
4766
+ const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
4767
+ return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
4768
+ }
4769
+ function probeWithSuffixes(directory, command, suffixes) {
4770
+ for (const suffix of suffixes) {
4771
+ const candidate = join4(directory, command + suffix);
4772
+ if (probe(candidate))
4773
+ return candidate;
4774
+ }
4775
+ return null;
4776
+ }
4777
+ function resolveLocal(command, workingDirectory, suffixes, stopAt) {
4778
+ const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
4779
+ let current = resolve7(workingDirectory);
4780
+ while (true) {
4781
+ for (const rule of LOCAL_BIN_RULES) {
4782
+ if (!rule.markers.some((marker) => probe(join4(current, marker))))
4783
+ continue;
4784
+ for (const binDir of rule.binDirs) {
4785
+ const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
4786
+ if (found !== null)
4787
+ return found;
4788
+ }
4574
4789
  }
4790
+ if (probe(join4(current, ".git")))
4791
+ return null;
4792
+ if (boundary !== undefined && current === boundary)
4793
+ return null;
4794
+ const parent = dirname9(current);
4795
+ if (parent === current)
4796
+ return null;
4797
+ current = parent;
4575
4798
  }
4576
- let pathEnv = process.env["PATH"] ?? "";
4577
- if (isWindows && !pathEnv) {
4799
+ }
4800
+ function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
4801
+ let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
4802
+ if (platform === "win32" && !pathEnv) {
4578
4803
  pathEnv = process.env["Path"] ?? "";
4579
4804
  }
4580
- const paths = pathEnv.split(delimiter3);
4581
- for (const p of paths) {
4582
- for (const suffix of exts) {
4583
- if (existsSync9(join3(p, cmd + suffix))) {
4584
- return true;
4585
- }
4586
- }
4805
+ for (const entry of pathEnv.split(delimiter3)) {
4806
+ if (entry.length === 0)
4807
+ continue;
4808
+ const found = probeWithSuffixes(entry, command, suffixes);
4809
+ if (found !== null)
4810
+ return found;
4587
4811
  }
4588
- if (cmd === "node")
4589
- return true;
4590
- return false;
4812
+ return null;
4813
+ }
4814
+ function resolveServerBinary(command, workingDirectory, options = {}) {
4815
+ if (command.length === 0)
4816
+ return null;
4817
+ const [cmd] = command;
4818
+ if (cmd === undefined || cmd.length === 0)
4819
+ return null;
4820
+ const platform = options.platform ?? process.platform;
4821
+ const suffixes = executableSuffixes(platform, options.pathExt);
4822
+ if (cmd.includes("/") || cmd.includes("\\")) {
4823
+ const explicit = isAbsolute5(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
4824
+ return probe(explicit) ? explicit : null;
4825
+ }
4826
+ const cacheKey = JSON.stringify([
4827
+ workingDirectory ?? "",
4828
+ cmd,
4829
+ platform,
4830
+ options.stopAt ?? "",
4831
+ options.pathExt ?? "",
4832
+ options.pathEnv ?? process.env["PATH"] ?? ""
4833
+ ]);
4834
+ const cached = resolutionCache.get(cacheKey);
4835
+ if (cached !== undefined)
4836
+ return cached;
4837
+ let resolved = null;
4838
+ if (workingDirectory !== undefined && workingDirectory.length > 0) {
4839
+ resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
4840
+ }
4841
+ resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
4842
+ if (resolved === null && cmd === "node")
4843
+ resolved = cmd;
4844
+ resolutionCache.set(cacheKey, resolved);
4845
+ return resolved;
4846
+ }
4847
+ function isServerInstalled(command, workingDirectory, options = {}) {
4848
+ if (command.length === 0)
4849
+ return false;
4850
+ return resolveServerBinary(command, workingDirectory, options) !== null;
4591
4851
  }
4592
4852
 
4593
4853
  // ../lsp-core/src/lsp/server-resolution.ts
4854
+ function withResolvedCommand(command, binaryPath) {
4855
+ return [binaryPath, ...command.slice(1)];
4856
+ }
4594
4857
  function findServerForExtension(ext) {
4595
4858
  const servers = getMergedServers();
4859
+ const workingDirectory = contextCwd();
4596
4860
  for (const server2 of servers) {
4597
- if (server2.extensions.includes(ext) && isServerInstalled(server2.command)) {
4861
+ if (!server2.extensions.includes(ext))
4862
+ continue;
4863
+ const binaryPath = resolveServerBinary(server2.command, workingDirectory);
4864
+ if (binaryPath !== null) {
4598
4865
  const resolvedServer = {
4599
4866
  id: server2.id,
4600
- command: server2.command,
4867
+ command: withResolvedCommand(server2.command, binaryPath),
4601
4868
  extensions: server2.extensions,
4602
4869
  priority: server2.priority
4603
4870
  };
@@ -4644,6 +4911,7 @@ function findServerForExtension(ext) {
4644
4911
  function getAllServers() {
4645
4912
  const servers = getMergedServers();
4646
4913
  const disabled = getDisabledServerIds();
4914
+ const workingDirectory = contextCwd();
4647
4915
  const result = [];
4648
4916
  const seen = new Set;
4649
4917
  for (const server2 of servers) {
@@ -4651,7 +4919,7 @@ function getAllServers() {
4651
4919
  continue;
4652
4920
  result.push({
4653
4921
  id: server2.id,
4654
- installed: isServerInstalled(server2.command),
4922
+ installed: isServerInstalled(server2.command, workingDirectory),
4655
4923
  extensions: server2.extensions,
4656
4924
  disabled: false,
4657
4925
  source: server2.source,
@@ -4665,7 +4933,7 @@ function getAllServers() {
4665
4933
  const builtin = BUILTIN_SERVERS[id];
4666
4934
  result.push({
4667
4935
  id,
4668
- installed: builtin ? isServerInstalled(builtin.command) : false,
4936
+ installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
4669
4937
  extensions: builtin?.extensions ?? [],
4670
4938
  disabled: true,
4671
4939
  source: "disabled",
@@ -4676,7 +4944,6 @@ function getAllServers() {
4676
4944
  }
4677
4945
 
4678
4946
  // ../lsp-core/src/lsp/client-wrapper.ts
4679
- var WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
4680
4947
  function isDirectoryPath(filePath) {
4681
4948
  try {
4682
4949
  return statSync4(filePath).isDirectory();
@@ -4685,32 +4952,90 @@ function isDirectoryPath(filePath) {
4685
4952
  }
4686
4953
  }
4687
4954
  function findWorkspaceRoot(filePath) {
4688
- const abs = resolvePathInsideContext(filePath);
4955
+ const cwd = contextCwd();
4956
+ const abs = resolveReadablePathInsideContext(filePath);
4689
4957
  let dir = abs;
4690
4958
  if (!isDirectoryPath(dir)) {
4691
- dir = dirname8(dir);
4692
- }
4693
- let prevDir = "";
4694
- while (dir !== prevDir) {
4695
- for (const marker of WORKSPACE_MARKERS) {
4696
- if (existsSync10(join4(dir, marker))) {
4697
- return dir;
4959
+ dir = dirname10(dir);
4960
+ }
4961
+ if (!isPathInside(cwd, abs))
4962
+ return findWorkspaceRootOutsideContext(dir);
4963
+ const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
4964
+ let nearestPackageRoot;
4965
+ while (isPathInside(cwd, dir)) {
4966
+ const canonicalDir = existingDirectoryInsideContext(dir, cwd);
4967
+ if (canonicalDir !== undefined) {
4968
+ if (existsSync11(join5(dir, GIT_WORKSPACE_MARKER))) {
4969
+ return canonicalDir;
4970
+ }
4971
+ if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
4972
+ nearestPackageRoot = canonicalDir;
4698
4973
  }
4699
4974
  }
4700
- prevDir = dir;
4701
- dir = dirname8(dir);
4975
+ if (dir === cwd)
4976
+ break;
4977
+ dir = dirname10(dir);
4702
4978
  }
4703
- return dirname8(abs);
4979
+ return nearestPackageRoot ?? fallbackRoot;
4980
+ }
4981
+ function hasProjectWorkspaceMarker(directory) {
4982
+ return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync11(join5(directory, marker)));
4983
+ }
4984
+ function resolveReadablePathInsideContext(filePath) {
4985
+ const cwd = contextCwd();
4986
+ const abs = resolve8(cwd, filePath);
4987
+ if (isPathInside(cwd, abs))
4988
+ return abs;
4989
+ const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
4990
+ if (rebased !== undefined)
4991
+ return rebased;
4992
+ return canonicalizeExistingOrNearestAncestor(abs);
4704
4993
  }
4705
4994
  function resolvePathInsideContext(filePath) {
4706
4995
  const cwd = contextCwd();
4707
- const abs = resolve7(cwd, filePath);
4996
+ const abs = resolveReadablePathInsideContext(filePath);
4708
4997
  const canonical = canonicalizeExistingOrNearestAncestor(abs);
4709
4998
  if (!isPathInside(cwd, canonical)) {
4710
4999
  throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
4711
5000
  }
4712
5001
  return canonical;
4713
5002
  }
5003
+ function rebaseThroughCanonicalAncestor(path2, cwd) {
5004
+ let current = path2;
5005
+ const suffix = [];
5006
+ while (true) {
5007
+ if (existsSync11(current)) {
5008
+ const canonical = realpathSync5(current);
5009
+ if (isPathInside(cwd, canonical))
5010
+ return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
5011
+ }
5012
+ const parent = dirname10(current);
5013
+ if (parent === current)
5014
+ return;
5015
+ suffix.unshift(basename3(current));
5016
+ current = parent;
5017
+ }
5018
+ }
5019
+ function existingDirectoryInsideContext(directory, cwd) {
5020
+ if (!existsSync11(directory))
5021
+ return;
5022
+ const canonical = realpathSync5(directory);
5023
+ if (!statSync4(canonical).isDirectory())
5024
+ return;
5025
+ return isPathInside(cwd, canonical) ? canonical : undefined;
5026
+ }
5027
+ function nearestExistingDirectoryInsideContext(directory, cwd) {
5028
+ let current = directory;
5029
+ while (isPathInside(cwd, current)) {
5030
+ const canonical = existingDirectoryInsideContext(current, cwd);
5031
+ if (canonical !== undefined)
5032
+ return canonical;
5033
+ if (current === cwd)
5034
+ return;
5035
+ current = dirname10(current);
5036
+ }
5037
+ return;
5038
+ }
4714
5039
  function formatServerLookupError(result) {
4715
5040
  if (result.status === "not_installed") {
4716
5041
  return formatNotInstalled(result);
@@ -4734,6 +5059,19 @@ function formatServerLookupError(result) {
4734
5059
  ].join(`
4735
5060
  `);
4736
5061
  }
5062
+ function formatInstallOptions(serverId, installHint) {
5063
+ const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
5064
+ if (localHint === undefined) {
5065
+ return ["To install, run:", ` ${installHint}`];
5066
+ }
5067
+ return [
5068
+ "To install in THIS repository (preferred — no global install needed):",
5069
+ ` ${localHint}`,
5070
+ "",
5071
+ "Or install it globally:",
5072
+ ` ${installHint}`
5073
+ ];
5074
+ }
4737
5075
  function formatNotInstalled(result) {
4738
5076
  const { server: server2, installHint } = result;
4739
5077
  const extensions = server2.extensions.join(", ");
@@ -4748,19 +5086,19 @@ function formatNotInstalled(result) {
4748
5086
  `Command not found: ${server2.command[0]}`,
4749
5087
  ""
4750
5088
  ];
5089
+ const installOptions = formatInstallOptions(server2.id, installHint);
4751
5090
  if (decision === "allowed") {
4752
5091
  return [
4753
5092
  ...header,
4754
5093
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
4755
- ` ${installHint}`
5094
+ ...installOptions.slice(1)
4756
5095
  ].join(`
4757
5096
  `);
4758
5097
  }
4759
5098
  if (!context.capabilities.installDecisionTool) {
4760
5099
  return [
4761
5100
  ...header,
4762
- "To install, run:",
4763
- ` ${installHint}`,
5101
+ ...installOptions,
4764
5102
  "",
4765
5103
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4766
5104
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
@@ -4769,8 +5107,7 @@ function formatNotInstalled(result) {
4769
5107
  }
4770
5108
  return [
4771
5109
  ...header,
4772
- "To install, run:",
4773
- ` ${installHint}`,
5110
+ ...installOptions,
4774
5111
  "",
4775
5112
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
4776
5113
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -4781,7 +5118,7 @@ function formatNotInstalled(result) {
4781
5118
  ].join(`
4782
5119
  `);
4783
5120
  }
4784
- var READ_ONLY_RETRY_TOOLS = new Set([
5121
+ var READ_ONLY_TOOLS = new Set([
4785
5122
  "diagnostics",
4786
5123
  "definition",
4787
5124
  "references",
@@ -4790,7 +5127,7 @@ var READ_ONLY_RETRY_TOOLS = new Set([
4790
5127
  "prepareRename"
4791
5128
  ]);
4792
5129
  async function withLspClient(filePath, fn, toolName, options = {}) {
4793
- const absPath = resolvePathInsideContext(filePath);
5130
+ const absPath = READ_ONLY_TOOLS.has(toolName) ? resolveReadablePathInsideContext(filePath) : resolvePathInsideContext(filePath);
4794
5131
  if (isDirectoryPath(absPath)) {
4795
5132
  throw new LspInvalidPathError("Directory paths are not supported by this LSP tool. " + "Use lsp.diagnostics with a directory path for directory diagnostics.");
4796
5133
  }
@@ -4805,9 +5142,9 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4805
5142
  const acquireAndCall = async (allowRetry) => {
4806
5143
  const client = await manager.getClient(root, server2, options.signal);
4807
5144
  try {
4808
- return await fn(client, root);
5145
+ return await fn(client, root, absPath);
4809
5146
  } catch (err) {
4810
- if (allowRetry && READ_ONLY_RETRY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
5147
+ if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
4811
5148
  manager.invalidateClient(root, server2.id, client);
4812
5149
  return acquireAndCall(false);
4813
5150
  }
@@ -4825,8 +5162,8 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
4825
5162
  }
4826
5163
 
4827
5164
  // ../lsp-core/src/lsp/directory-diagnostics.ts
4828
- import { existsSync as existsSync11, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
4829
- import { join as join5, resolve as resolve8 } from "node:path";
5165
+ import { existsSync as existsSync12, lstatSync as lstatSync5, readdirSync as readdirSync3 } from "node:fs";
5166
+ import { join as join6, resolve as resolve9 } from "node:path";
4830
5167
 
4831
5168
  // ../lsp-core/src/lsp/formatters.ts
4832
5169
  import { fileURLToPath as fileURLToPath3 } from "node:url";
@@ -4956,7 +5293,7 @@ function collectFilesWithExtension(dir, extension, maxFiles) {
4956
5293
  for (const entry of entries) {
4957
5294
  if (files.length >= maxFiles)
4958
5295
  return;
4959
- const fullPath = join5(currentDir, entry);
5296
+ const fullPath = join6(currentDir, entry);
4960
5297
  let stat;
4961
5298
  try {
4962
5299
  stat = lstatSync5(fullPath);
@@ -4981,8 +5318,8 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
4981
5318
  if (!extension.startsWith(".")) {
4982
5319
  throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
4983
5320
  }
4984
- const absDir = resolve8(options.workspaceRoot ?? contextCwd(), directory);
4985
- if (!existsSync11(absDir)) {
5321
+ const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
5322
+ if (!existsSync12(absDir)) {
4986
5323
  throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
4987
5324
  }
4988
5325
  const serverResult = options.server === undefined ? findServerForExtension(extension) : { status: "found", server: options.server };
@@ -5069,7 +5406,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
5069
5406
 
5070
5407
  // ../lsp-core/src/lsp/infer-extension.ts
5071
5408
  import { lstatSync as lstatSync6, readdirSync as readdirSync4 } from "node:fs";
5072
- import { join as join6 } from "node:path";
5409
+ import { join as join7 } from "node:path";
5073
5410
  var SKIP_DIRECTORIES2 = new Set(["node_modules", ".git", "dist", "build", ".next", "out"]);
5074
5411
  var MAX_SCAN_ENTRIES = 500;
5075
5412
  function inferExtensionFromDirectory(directory) {
@@ -5087,7 +5424,7 @@ function inferExtensionFromDirectory(directory) {
5087
5424
  for (const entry of entries) {
5088
5425
  if (scanned >= MAX_SCAN_ENTRIES)
5089
5426
  return;
5090
- const fullPath = join6(dir, entry);
5427
+ const fullPath = join7(dir, entry);
5091
5428
  let stat;
5092
5429
  try {
5093
5430
  stat = lstatSync6(fullPath);
@@ -5262,7 +5599,7 @@ async function executeLspDiagnostics(params, signal) {
5262
5599
  const filePath = requireString(params, "filePath");
5263
5600
  const severity = severityFilter(params);
5264
5601
  try {
5265
- const absPath = resolvePathInsideContext(filePath);
5602
+ const absPath = resolveReadablePathInsideContext(filePath);
5266
5603
  if (isDirectoryPath(absPath)) {
5267
5604
  const extension = inferExtensionFromDirectory(absPath);
5268
5605
  if (!extension) {
@@ -5291,7 +5628,7 @@ async function executeLspDiagnostics(params, signal) {
5291
5628
  };
5292
5629
  return text(output2.output, details2);
5293
5630
  }
5294
- const result = await withLspClient(filePath, async (client) => client.diagnostics(filePath, signal), "diagnostics", clientOptions(signal));
5631
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.diagnostics(resolvedFilePath, signal), "diagnostics", clientOptions(signal));
5295
5632
  if (result.transientError) {
5296
5633
  const message = result.transientError.message;
5297
5634
  const details2 = {
@@ -5338,6 +5675,96 @@ async function executeLspDiagnostics(params, signal) {
5338
5675
  throw error;
5339
5676
  }
5340
5677
  }
5678
+ // ../lsp-core/src/lsp/format-document.ts
5679
+ import { readFileSync as readFileSync6, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
5680
+ var DEFAULT_FORMATTING_OPTIONS = {
5681
+ tabSize: 4,
5682
+ insertSpaces: false,
5683
+ trimTrailingWhitespace: true,
5684
+ insertFinalNewline: true,
5685
+ trimFinalNewlines: true
5686
+ };
5687
+ var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
5688
+ async function formatDocumentWithClient(client, filePath, options = {}) {
5689
+ const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
5690
+ if (edits === null)
5691
+ return { status: "unavailable", reason: "capability_not_advertised" };
5692
+ if (edits.length === 0)
5693
+ return UNCHANGED;
5694
+ const before = readFileSync6(filePath, "utf-8");
5695
+ const normalized = normalizeTextEdits(before, edits, 0);
5696
+ if (normalized.text === before)
5697
+ return UNCHANGED;
5698
+ writeAtomically(filePath, normalized.text);
5699
+ await client.openFile(filePath);
5700
+ return {
5701
+ status: "formatted",
5702
+ ...lineDelta(normalized.edits)
5703
+ };
5704
+ }
5705
+ function lineDelta(edits) {
5706
+ let linesAdded = 0;
5707
+ let linesRemoved = 0;
5708
+ for (const edit of edits) {
5709
+ linesRemoved += edit.range.end.line - edit.range.start.line + 1;
5710
+ linesAdded += edit.newText.split(`
5711
+ `).length;
5712
+ }
5713
+ return { linesAdded, linesRemoved };
5714
+ }
5715
+ function writeAtomically(filePath, content) {
5716
+ const tempPath = `${filePath}.omo-format.tmp`;
5717
+ writeFileSync3(tempPath, content, "utf-8");
5718
+ try {
5719
+ renameSync3(tempPath, filePath);
5720
+ } catch (error) {
5721
+ try {
5722
+ unlinkSync2(tempPath);
5723
+ } catch {}
5724
+ throw error;
5725
+ }
5726
+ }
5727
+
5728
+ // ../lsp-core/src/tools/format.ts
5729
+ async function executeLspFormat(params, signal) {
5730
+ const filePath = requireString(params, "filePath");
5731
+ try {
5732
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
5733
+ return text(describeResult(filePath, result), formatDetails(filePath, result));
5734
+ } catch (error) {
5735
+ const missingDependency = missingDependencyResult(error, {
5736
+ filePath,
5737
+ status: "unavailable",
5738
+ reason: "server_unavailable",
5739
+ linesAdded: 0,
5740
+ linesRemoved: 0
5741
+ });
5742
+ if (missingDependency)
5743
+ return missingDependency;
5744
+ throw error;
5745
+ }
5746
+ }
5747
+ function formatDetails(filePath, result) {
5748
+ if (result.status === "unavailable") {
5749
+ return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
5750
+ }
5751
+ return {
5752
+ filePath,
5753
+ status: result.status,
5754
+ linesAdded: result.linesAdded,
5755
+ linesRemoved: result.linesRemoved
5756
+ };
5757
+ }
5758
+ function describeResult(filePath, result) {
5759
+ if (result.status === "unavailable") {
5760
+ return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
5761
+ }
5762
+ if (result.status === "unchanged") {
5763
+ return `Already formatted: ${filePath}`;
5764
+ }
5765
+ return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
5766
+ }
5767
+
5341
5768
  // ../lsp-core/src/tools/install-decision.ts
5342
5769
  async function executeLspInstallDecision(params) {
5343
5770
  const serverId = requireString(params, "server_id");
@@ -5366,7 +5793,7 @@ async function executeLspGotoDefinition(params, signal) {
5366
5793
  const line = requireNumber(params, "line");
5367
5794
  const character = requireNumber(params, "character");
5368
5795
  try {
5369
- const result = await withLspClient(filePath, async (client) => client.definition(filePath, line, character, signal), "definition", clientOptions(signal));
5796
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.definition(resolvedFilePath, line, character, signal), "definition", clientOptions(signal));
5370
5797
  const locations = !result ? [] : Array.isArray(result) ? result : [result];
5371
5798
  const details = { filePath, line, character, locations };
5372
5799
  if (locations.length === 0)
@@ -5391,7 +5818,7 @@ async function executeLspFindReferences(params, signal) {
5391
5818
  const character = requireNumber(params, "character");
5392
5819
  const includeDeclaration = optionalBoolean(params, "includeDeclaration") ?? true;
5393
5820
  try {
5394
- const result = await withLspClient(filePath, async (client) => client.references(filePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5821
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.references(resolvedFilePath, line, character, includeDeclaration, signal), "references", clientOptions(signal));
5395
5822
  const references = Array.isArray(result) ? result : [];
5396
5823
  const total = references.length;
5397
5824
  const truncated = total > DEFAULT_MAX_REFERENCES;
@@ -5433,7 +5860,7 @@ async function executeLspPrepareRename(params, signal) {
5433
5860
  const line = requireNumber(params, "line");
5434
5861
  const character = requireNumber(params, "character");
5435
5862
  try {
5436
- const result = await withLspClient(filePath, async (client) => client.prepareRename(filePath, line, character, signal), "prepareRename", clientOptions(signal));
5863
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.prepareRename(resolvedFilePath, line, character, signal), "prepareRename", clientOptions(signal));
5437
5864
  const details = { filePath, line, character, result };
5438
5865
  return text(formatPrepareRenameResult(result), details);
5439
5866
  } catch (error) {
@@ -5454,7 +5881,7 @@ async function executeLspRename(params, signal) {
5454
5881
  const character = requireNumber(params, "character");
5455
5882
  const newName = requireString(params, "newName");
5456
5883
  try {
5457
- const result = await withLspClient(filePath, async (client) => client.rename(filePath, line, character, newName, signal), "rename", clientOptions(signal));
5884
+ const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.rename(resolvedFilePath, line, character, newName, signal), "rename", clientOptions(signal));
5458
5885
  const details = { filePath, line, character, newName, apply: result.apply, edit: result.edit };
5459
5886
  return text(formatApplyResult(result.apply), details, !result.apply.success);
5460
5887
  } catch (error) {
@@ -5534,7 +5961,7 @@ async function executeLspSymbols(params, signal) {
5534
5961
  const symbols2 = await withLspClient(filePath, async (client) => client.workspaceSymbols(query, signal), "workspaceSymbols", clientOptions(signal));
5535
5962
  return formatSymbolsResult(filePath, scope, symbols2, limit, query);
5536
5963
  }
5537
- const symbols = await withLspClient(filePath, async (client) => client.documentSymbols(filePath, signal), "documentSymbols", clientOptions(signal));
5964
+ const symbols = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => client.documentSymbols(resolvedFilePath, signal), "documentSymbols", clientOptions(signal));
5538
5965
  return formatSymbolsResult(filePath, scope, symbols, limit);
5539
5966
  } catch (error) {
5540
5967
  const query = optionalString(params, "query");
@@ -5670,6 +6097,16 @@ var LSP_MCP_TOOLS = [
5670
6097
  }, ["filePath", "line", "character", "newName"]),
5671
6098
  execute: executeLspRename
5672
6099
  },
6100
+ {
6101
+ name: "format",
6102
+ aliases: ["lsp_format"],
6103
+ title: "LSP Format",
6104
+ description: "Format a source file with its language server and write the returned edits to disk.",
6105
+ inputSchema: objectSchema({
6106
+ filePath: { type: "string", description: "Source file path to format." }
6107
+ }, ["filePath"]),
6108
+ execute: executeLspFormat
6109
+ },
5673
6110
  {
5674
6111
  name: "install_decision",
5675
6112
  aliases: ["lsp_install_decision"],
@@ -5770,7 +6207,10 @@ function requestedProtocolVersion(params) {
5770
6207
  var CONTEXT_KEY = "_context";
5771
6208
 
5772
6209
  class InvalidDaemonRequestError extends Error {
5773
- name = "InvalidDaemonRequestError";
6210
+ constructor() {
6211
+ super(...arguments);
6212
+ this.name = "InvalidDaemonRequestError";
6213
+ }
5774
6214
  }
5775
6215
  function extractRequestContext(raw) {
5776
6216
  if (!isPlainRecord(raw) || raw["method"] !== "tools/call")
@@ -5886,14 +6326,17 @@ async function callToolViaDaemon(name, args, options) {
5886
6326
  function callDiagnosticsViaDaemon(filePath, options) {
5887
6327
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
5888
6328
  }
6329
+ function callFormatViaDaemon(filePath, options) {
6330
+ return callToolViaDaemon("format", { filePath }, options);
6331
+ }
5889
6332
  function currentRequestContext(env = process.env) {
5890
6333
  const cwd = process.cwd();
5891
6334
  const home = env["HOME"] ?? homedir3();
5892
6335
  return parseLspRequestContext({
5893
6336
  cwd,
5894
- projectConfigPaths: [join7(cwd, ".codex", "lsp-client.json")],
5895
- userConfigPath: join7(home, ".codex", "lsp-client.json"),
5896
- installDecisionsPath: join7(home, ".codex", "lsp-install-decisions.json"),
6337
+ projectConfigPaths: [join8(cwd, ".codex", "lsp-client.json")],
6338
+ userConfigPath: join8(home, ".codex", "lsp-client.json"),
6339
+ installDecisionsPath: join8(home, ".codex", "lsp-install-decisions.json"),
5897
6340
  capabilities: { installDecisionTool: true }
5898
6341
  });
5899
6342
  }
@@ -5908,7 +6351,7 @@ function withContext(args, context) {
5908
6351
  function ensureDaemonAvailable(paths, ensure, signal) {
5909
6352
  if (!signal)
5910
6353
  return ensure(paths);
5911
- return new Promise((resolve9, reject) => {
6354
+ return new Promise((resolve10, reject) => {
5912
6355
  let settled = false;
5913
6356
  const finish = (run) => {
5914
6357
  if (settled)
@@ -5923,11 +6366,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5923
6366
  return;
5924
6367
  }
5925
6368
  signal.addEventListener("abort", onAbort, { once: true });
5926
- Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
6369
+ Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5927
6370
  });
5928
6371
  }
5929
6372
  function sendToolCall(paths, token, name, args, options) {
5930
- return new Promise((resolve9, reject) => {
6373
+ return new Promise((resolve10, reject) => {
5931
6374
  const socket = connect(paths.socket);
5932
6375
  const requestId = allocateProxyRequestId();
5933
6376
  let settled = false;
@@ -5980,7 +6423,7 @@ function sendToolCall(paths, token, name, args, options) {
5980
6423
  }
5981
6424
  const result = toToolResult(message, requestId);
5982
6425
  if (result)
5983
- finish(() => resolve9(result));
6426
+ finish(() => resolve10(result));
5984
6427
  else
5985
6428
  finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
5986
6429
  });
@@ -6025,8 +6468,8 @@ function isRetryableTool(name) {
6025
6468
  return name !== "rename" && name !== "lsp_rename";
6026
6469
  }
6027
6470
  // src/proxy.ts
6028
- import { existsSync as existsSync12, realpathSync as realpathSync4 } from "node:fs";
6029
- import { basename as basename3, delimiter as delimiter4, dirname as dirname9, isAbsolute as isAbsolute5 } from "node:path";
6471
+ import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
6472
+ import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
6030
6473
  var DEFAULT_STARTUP_TIMEOUT_MS = 1e4;
6031
6474
  async function runMcpStdioProxy(options = {}) {
6032
6475
  const input = options.input ?? process.stdin;
@@ -6149,34 +6592,34 @@ function canonicalizePathList(value) {
6149
6592
  return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
6150
6593
  }
6151
6594
  function canonicalizePath(value) {
6152
- if (value === undefined || !isAbsolute5(value) || !existsSync12(value))
6595
+ if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
6153
6596
  return value;
6154
- return realpathSync4(value);
6597
+ return realpathSync6(value);
6155
6598
  }
6156
6599
  function projectRootFromOpenCodeConfigPath(path2) {
6157
- if (basename3(path2) !== "lsp.json" && basename3(path2) !== "lsp-client.json")
6600
+ if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
6158
6601
  return;
6159
- const configDir = dirname9(path2);
6160
- const configDirName = basename3(configDir);
6602
+ const configDir = dirname11(path2);
6603
+ const configDirName = basename4(configDir);
6161
6604
  if (configDirName !== ".opencode" && configDirName !== ".omo")
6162
6605
  return;
6163
- return dirname9(configDir);
6606
+ return dirname11(configDir);
6164
6607
  }
6165
6608
  export {
6166
- validateDaemonVersion,
6167
- runMcpStdioProxy,
6168
- resolveDaemonRuntime,
6169
- probeDaemon,
6170
- ensureDaemonRunning,
6171
- disposeDefaultLspManager,
6172
- daemonPaths,
6173
- currentRequestContext,
6174
- callToolViaDaemon,
6175
- callDiagnosticsViaDaemon,
6176
- OMO_LSP_DAEMON_VERSION,
6177
- OMO_LSP_DAEMON_DIR,
6178
- OMO_LSP_DAEMON_CLI,
6179
- InvalidRuntimeOverrideError,
6609
+ InvalidDaemonDirectoryError,
6180
6610
  InvalidDaemonVersionError,
6181
- InvalidDaemonDirectoryError
6611
+ InvalidRuntimeOverrideError,
6612
+ OMO_LSP_DAEMON_CLI,
6613
+ OMO_LSP_DAEMON_DIR,
6614
+ OMO_LSP_DAEMON_VERSION,
6615
+ callDiagnosticsViaDaemon,
6616
+ callToolViaDaemon,
6617
+ currentRequestContext,
6618
+ daemonPaths,
6619
+ disposeDefaultLspManager,
6620
+ ensureDaemonRunning,
6621
+ probeDaemon,
6622
+ resolveDaemonRuntime,
6623
+ runMcpStdioProxy,
6624
+ validateDaemonVersion
6182
6625
  };