oh-my-opencode 4.19.0 → 4.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/.agents/command/omomomo.md +1 -1
  2. package/.agents/skills/omomomo/SKILL.md +1 -1
  3. package/.opencode/command/omomomo.md +1 -1
  4. package/README.ja.md +6 -6
  5. package/README.ko.md +6 -6
  6. package/README.md +6 -6
  7. package/README.ru.md +6 -6
  8. package/README.zh-cn.md +6 -6
  9. package/dist/agents/atlas/agent.d.ts +5 -3
  10. package/dist/agents/explore.d.ts +4 -2
  11. package/dist/agents/gpt-prompt-identity.d.ts +3 -0
  12. package/dist/agents/hephaestus/agent.d.ts +4 -2
  13. package/dist/agents/librarian.d.ts +4 -2
  14. package/dist/agents/metis.d.ts +4 -2
  15. package/dist/agents/momus.d.ts +3 -2
  16. package/dist/agents/multimodal-looker.d.ts +4 -2
  17. package/dist/agents/oracle.d.ts +4 -2
  18. package/dist/agents/sisyphus/claude-opus-5.d.ts +33 -0
  19. package/dist/agents/sisyphus/gpt-5-5.d.ts +1 -1
  20. package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +1 -0
  21. package/dist/agents/sisyphus/index.d.ts +2 -0
  22. package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
  23. package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
  24. package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +2 -2
  25. package/dist/agents/types.d.ts +2 -2
  26. package/dist/cli/index.js +23577 -19269
  27. package/dist/cli-node/index.js +23577 -19269
  28. package/dist/config/schema/agent-names.d.ts +26 -26
  29. package/dist/config/schema/agent-overrides.d.ts +400 -400
  30. package/dist/config/schema/browser-automation.d.ts +2 -2
  31. package/dist/config/schema/categories.d.ts +36 -36
  32. package/dist/config/schema/codegraph.d.ts +2 -0
  33. package/dist/config/schema/commands.d.ts +2 -2
  34. package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
  35. package/dist/config/schema/experimental.d.ts +1 -1
  36. package/dist/config/schema/fallback-models.d.ts +25 -25
  37. package/dist/config/schema/hooks.d.ts +43 -43
  38. package/dist/config/schema/internal/permission.d.ts +9 -9
  39. package/dist/config/schema/keyword-detector.d.ts +6 -6
  40. package/dist/config/schema/oh-my-opencode-config.d.ts +404 -402
  41. package/dist/config/schema/tmux.d.ts +6 -6
  42. package/dist/create-hooks.d.ts +35 -35
  43. package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
  44. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  45. package/dist/features/claude-tasks/types.d.ts +4 -4
  46. package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
  47. package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
  48. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
  49. package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
  50. package/dist/features/tmux-subagent/index.d.ts +1 -0
  51. package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
  52. package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
  53. package/dist/help/schema/acp.d.ts +3 -3
  54. package/dist/help/schema/doctor.d.ts +4 -4
  55. package/dist/help/schema/status.d.ts +3 -3
  56. package/dist/hooks/codegraph-bootstrap/hook.d.ts +3 -2
  57. package/dist/hooks/goal/types.d.ts +5 -5
  58. package/dist/hooks/non-interactive-env/constants.d.ts +4 -1
  59. package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
  60. package/dist/hooks/start-work/notepad-scaffold.d.ts +10 -0
  61. package/dist/hooks/start-work/parse-user-request.d.ts +2 -0
  62. package/dist/hooks/start-work/worktree-block.d.ts +5 -0
  63. package/dist/index.js +27370 -21301
  64. package/dist/mcp/types.d.ts +3 -3
  65. package/dist/oh-my-opencode.schema.json +11 -0
  66. package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
  67. package/dist/plugin/command-execute-before.d.ts +3 -3
  68. package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
  69. package/dist/shared/omo-process-sweep.d.ts +18 -0
  70. package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
  71. package/dist/shared/tmux/tmux-utils.d.ts +1 -1
  72. package/dist/shared/typescript-native-source-parser.d.ts +7 -0
  73. package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
  74. package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  75. package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
  76. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  77. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  78. package/dist/skills/debugging/SKILL.md +2 -1
  79. package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  80. package/dist/skills/programming/SKILL.md +11 -1
  81. package/dist/skills/programming/references/logging.md +6 -1
  82. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  83. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
  84. package/dist/skills/start-work/SKILL.md +12 -2
  85. package/dist/skills/ulw-plan/SKILL.md +21 -2
  86. package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
  87. package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
  88. package/dist/testing/create-plugin-module.d.ts +1 -0
  89. package/dist/tools/task/types.d.ts +10 -10
  90. package/dist/tui.js +23442 -19182
  91. package/package.json +14 -14
  92. package/packages/git-bash-mcp/dist/cli.js +54 -8
  93. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +62 -2
  94. package/packages/lsp-core/src/lsp/client.ts +14 -1
  95. package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +2 -2
  96. package/packages/lsp-core/src/mcp.ts +9 -0
  97. package/packages/lsp-daemon/dist/cli.js +319 -51
  98. package/packages/lsp-daemon/dist/client.js +136 -48
  99. package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -10
  100. package/packages/lsp-daemon/dist/daemon-client.js +4 -34
  101. package/packages/lsp-daemon/dist/daemon-failure-result.d.ts +3 -0
  102. package/packages/lsp-daemon/dist/daemon-failure-result.js +38 -0
  103. package/packages/lsp-daemon/dist/daemon-request-error.d.ts +14 -0
  104. package/packages/lsp-daemon/dist/daemon-request-error.js +26 -0
  105. package/packages/lsp-daemon/dist/daemon-server.js +5 -1
  106. package/packages/lsp-daemon/dist/index.js +137 -48
  107. package/packages/lsp-daemon/dist/proxy.d.ts +2 -0
  108. package/packages/lsp-daemon/dist/proxy.js +1 -0
  109. package/packages/lsp-daemon/dist/version-reap.d.ts +26 -0
  110. package/packages/lsp-daemon/dist/version-reap.js +182 -0
  111. package/packages/lsp-tools-mcp/dist/cli.js +61 -10
  112. package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -1
  113. package/packages/lsp-tools-mcp/dist/mcp.js +61 -10
  114. package/packages/lsp-tools-mcp/dist/tools.js +6 -1
  115. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  116. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +72 -12
  117. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  118. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  119. package/packages/omo-codex/plugin/components/bootstrap/src/setup.ts +22 -2
  120. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +779 -385
  121. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +302 -173
  122. package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
  123. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
  124. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +23 -42
  125. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +98 -32
  126. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +5 -0
  127. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +17 -9
  128. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +18 -25
  129. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +1 -0
  130. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +5 -0
  131. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +176 -0
  132. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +6 -1
  133. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +31 -2
  134. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +1 -1
  135. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +6 -0
  136. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +65 -1
  137. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -7
  138. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +2 -1
  139. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +57 -3
  140. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +42 -0
  141. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +122 -10
  142. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +2 -2
  143. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +101 -64
  144. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  145. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  146. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  147. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  148. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  149. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  150. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  151. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +80 -40
  152. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  153. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  154. package/packages/omo-codex/plugin/components/rules/dist/cli.js +11 -0
  155. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  156. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  157. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +11 -0
  158. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +60 -0
  159. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  160. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  161. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  162. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  163. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  164. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  165. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  166. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +2 -2
  167. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +2 -2
  168. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
  169. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-high.toml +1 -1
  170. package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-worker-medium.toml +2 -2
  171. package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +1 -1
  172. package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
  173. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +1 -1
  174. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  175. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  176. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +12 -7
  177. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +21 -2
  178. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
  179. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +1 -1
  180. package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +1 -1
  181. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +42 -0
  182. package/packages/omo-codex/plugin/components/ulw-loop/README.md +6 -4
  183. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +12 -7
  184. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.d.ts +21 -0
  185. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-continuation.js +64 -0
  186. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +15 -2
  187. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-arg-parser.js +1 -1
  188. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +2 -1
  189. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +1 -1
  190. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +3 -3
  191. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.d.ts +3 -0
  192. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-steering.js +85 -0
  193. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.d.ts +0 -1
  194. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-subcommands.js +13 -33
  195. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +998 -593
  196. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +1 -0
  197. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.d.ts +1 -1
  198. package/packages/omo-codex/plugin/components/ulw-loop/dist/constants.js +2 -0
  199. package/packages/omo-codex/plugin/components/ulw-loop/dist/domain-types.d.ts +6 -0
  200. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.d.ts +1 -0
  201. package/packages/omo-codex/plugin/components/ulw-loop/dist/goal-status.js +3 -0
  202. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.d.ts +1 -0
  203. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-crud.js +4 -0
  204. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.d.ts +1 -0
  205. package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-io.js +10 -2
  206. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +1 -1
  207. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.d.ts +15 -0
  208. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-batch.js +84 -0
  209. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.d.ts +5 -0
  210. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering-mutations.js +81 -0
  211. package/packages/omo-codex/plugin/components/ulw-loop/dist/steering.js +7 -59
  212. package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +12 -4
  213. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.d.ts +9 -0
  214. package/packages/omo-codex/plugin/components/ulw-loop/dist/validation-batch.js +122 -0
  215. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  216. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  217. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -1
  218. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +8 -6
  219. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-continuation.ts +84 -0
  220. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +13 -2
  221. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-arg-parser.ts +1 -1
  222. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +1 -1
  223. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +3 -3
  224. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-steering.ts +49 -0
  225. package/packages/omo-codex/plugin/components/ulw-loop/src/cli-subcommands.ts +13 -45
  226. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +1 -0
  227. package/packages/omo-codex/plugin/components/ulw-loop/src/constants.ts +2 -0
  228. package/packages/omo-codex/plugin/components/ulw-loop/src/domain-types.ts +7 -0
  229. package/packages/omo-codex/plugin/components/ulw-loop/src/goal-status.ts +4 -0
  230. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-crud.ts +4 -1
  231. package/packages/omo-codex/plugin/components/ulw-loop/src/plan-io.ts +20 -2
  232. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +1 -1
  233. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-batch.ts +125 -0
  234. package/packages/omo-codex/plugin/components/ulw-loop/src/steering-mutations.ts +59 -0
  235. package/packages/omo-codex/plugin/components/ulw-loop/src/steering.ts +6 -58
  236. package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +12 -4
  237. package/packages/omo-codex/plugin/components/ulw-loop/src/validation-batch.ts +122 -0
  238. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +76 -0
  239. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-checkpoint-continuation.test.ts +111 -0
  240. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-steering-batch.test.ts +67 -0
  241. package/packages/omo-codex/plugin/components/ulw-loop/test/cli-validation-batch.test.ts +57 -0
  242. package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +1 -0
  243. package/packages/omo-codex/plugin/components/ulw-loop/test/steering-batch.test.ts +152 -0
  244. package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +29 -0
  245. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch-checkpoint.test.ts +147 -0
  246. package/packages/omo-codex/plugin/components/ulw-loop/test/validation-batch.test.ts +73 -0
  247. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  248. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  249. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  250. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  251. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  252. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  253. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  254. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  255. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  256. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  257. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  258. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +2 -2
  259. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  260. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +2 -2
  261. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  262. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +2 -2
  263. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  264. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  265. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  266. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  267. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  268. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  269. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  270. package/packages/omo-codex/plugin/package-lock.json +41 -41
  271. package/packages/omo-codex/plugin/package.json +1 -1
  272. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +44 -0
  273. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
  274. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  275. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
  276. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  277. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  278. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
  279. package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  280. package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
  281. package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
  282. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
  283. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
  284. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
  285. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -1
  286. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +8 -6
  287. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +21 -2
  288. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
  289. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
  290. package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +9 -9
  291. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +26 -0
  292. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +41 -0
  293. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +22 -0
  294. package/packages/omo-codex/scripts/install-dist/install-local.mjs +49 -5
  295. package/packages/omo-codex/scripts/install-marketplace-cache.test.mjs +4 -1
  296. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
  297. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  298. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
  299. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  300. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  301. package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
  302. package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  303. package/packages/shared-skills/skills/programming/SKILL.md +11 -1
  304. package/packages/shared-skills/skills/programming/references/logging.md +6 -1
  305. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.test.ts +87 -0
  306. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +75 -11
  307. package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
  308. package/packages/shared-skills/skills/ulw-plan/SKILL.md +21 -2
  309. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
  310. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
@@ -167,16 +167,35 @@ function bufferFromChunk(chunk) {
167
167
 
168
168
  // ../mcp-stdio-core/src/server.ts
169
169
  var DEFAULT_IDLE_TIMEOUT_MS = 10 * 60000;
170
+ var DEFAULT_PARENT_POLL_INTERVAL_MS = 30000;
170
171
  var noopLog = () => {};
172
+ function isProcessAlive(pid) {
173
+ try {
174
+ process.kill(pid, 0);
175
+ return true;
176
+ } catch (error) {
177
+ return !hasErrorCode(error, "ESRCH");
178
+ }
179
+ }
171
180
  async function runJsonRpcStdioServer(config) {
172
181
  const log = config.log ?? noopLog;
173
182
  const idleTimeoutMs = config.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
174
- const idleTimer = createIdleTimer(idleTimeoutMs, log, config.onIdleTimeout);
183
+ let isClosed = false;
184
+ const idleTimer = createIdleTimer(idleTimeoutMs, log, () => {
185
+ isClosed = true;
186
+ config.onIdleTimeout?.();
187
+ });
188
+ const watchdog = createParentWatchdog(config.parentWatchdog, (parentPid, pollIntervalMs) => {
189
+ isClosed = true;
190
+ log("parent_exit", { parent_pid: parentPid, poll_interval_ms: pollIntervalMs });
191
+ config.onParentExit?.();
192
+ config.input.destroy();
193
+ });
175
194
  log("stdio_started", { cwd: process.cwd(), idle_timeout_ms: idleTimeoutMs });
176
195
  idleTimer.arm();
177
196
  try {
178
197
  for await (const message of readStdioJsonRpcMessages(config.input)) {
179
- if (idleTimer.closed())
198
+ if (isClosed)
180
199
  break;
181
200
  idleTimer.arm();
182
201
  if (message.kind === "parse_error") {
@@ -187,8 +206,12 @@ async function runJsonRpcStdioServer(config) {
187
206
  if (!await handleRequest(message, config, log))
188
207
  break;
189
208
  }
209
+ } catch (error) {
210
+ if (!(isClosed && hasErrorCode(error, "ERR_STREAM_PREMATURE_CLOSE")))
211
+ throw error;
190
212
  } finally {
191
213
  idleTimer.clear();
214
+ watchdog.clear();
192
215
  log("stdio_stopped");
193
216
  }
194
217
  }
@@ -244,9 +267,33 @@ function isTerminalOutputError(error) {
244
267
  return false;
245
268
  return error.code === "EPIPE" || error.code === "ERR_STREAM_DESTROYED" || error.code === "ERR_STREAM_WRITE_AFTER_END";
246
269
  }
247
- function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
270
+ function hasErrorCode(error, code) {
271
+ return error instanceof Error && "code" in error && error.code === code;
272
+ }
273
+ function createParentWatchdog(config, onDeadParent) {
274
+ if (config === undefined)
275
+ return { clear: () => {} };
276
+ const pollIntervalMs = config.pollIntervalMs ?? DEFAULT_PARENT_POLL_INTERVAL_MS;
277
+ if (pollIntervalMs <= 0)
278
+ return { clear: () => {} };
279
+ const parentPid = config.parentPid ?? process.ppid;
280
+ const probeAlive = config.probeAlive ?? isProcessAlive;
281
+ let fired = false;
282
+ const timer = setInterval(() => {
283
+ if (fired || probeAlive(parentPid))
284
+ return;
285
+ fired = true;
286
+ onDeadParent(parentPid, pollIntervalMs);
287
+ }, pollIntervalMs);
288
+ timer.unref();
289
+ return {
290
+ clear: () => {
291
+ clearInterval(timer);
292
+ }
293
+ };
294
+ }
295
+ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
248
296
  let timer = null;
249
- let isClosed = false;
250
297
  return {
251
298
  arm: () => {
252
299
  if (timer !== null)
@@ -254,9 +301,8 @@ function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
254
301
  if (idleTimeoutMs <= 0)
255
302
  return;
256
303
  timer = setTimeout(() => {
257
- isClosed = true;
258
304
  log("idle_timeout", { idle_timeout_ms: idleTimeoutMs });
259
- onIdleTimeout?.();
305
+ onTimeout();
260
306
  }, idleTimeoutMs);
261
307
  timer.unref();
262
308
  },
@@ -265,8 +311,7 @@ function createIdleTimer(idleTimeoutMs, log, onIdleTimeout) {
265
311
  return;
266
312
  clearTimeout(timer);
267
313
  timer = null;
268
- },
269
- closed: () => isClosed
314
+ }
270
315
  };
271
316
  }
272
317
  // ../lsp-core/src/lsp/client-wrapper.ts
@@ -3057,8 +3102,13 @@ class LspClient extends LspClientConnection {
3057
3102
  if (!pushFallbackOnly)
3058
3103
  continue;
3059
3104
  const remainingMs = deadlineAt - Date.now();
3060
- if (remainingMs <= 0)
3105
+ if (remainingMs <= 0) {
3106
+ if (!this.isDiagnosticPullSupported() && snapshot.publishGeneration === 0) {
3107
+ const cached = this.documents.getPullCache(snapshot);
3108
+ return { items: cached === null ? [] : [...cached.diagnostics] };
3109
+ }
3061
3110
  return this.freshnessTimeout(absPath);
3111
+ }
3062
3112
  const waitMs = push.status === "wait" ? Math.min(push.waitMs, remainingMs) : remainingMs;
3063
3113
  await waitForDiagnosticsActivity(this.documents.waitForDiagnosticsActivity(snapshot, waitMs), signal);
3064
3114
  }
@@ -5065,6 +5115,81 @@ import { connect } from "node:net";
5065
5115
  import { homedir as homedir3 } from "node:os";
5066
5116
  import { join as join7 } from "node:path";
5067
5117
 
5118
+ // src/daemon-request-error.ts
5119
+ class DaemonRequestError extends Error {
5120
+ requestWritten;
5121
+ constructor(message, requestWritten) {
5122
+ super(message);
5123
+ this.name = "DaemonRequestError";
5124
+ this.requestWritten = requestWritten;
5125
+ }
5126
+ }
5127
+
5128
+ class DaemonAuthenticationRejectedError extends DaemonRequestError {
5129
+ constructor() {
5130
+ super("daemon authentication failed before dispatch", true);
5131
+ this.name = "DaemonAuthenticationRejectedError";
5132
+ }
5133
+ }
5134
+
5135
+ class DaemonRequestCancelledError extends DaemonRequestError {
5136
+ constructor(requestWritten) {
5137
+ super("daemon request cancelled", requestWritten);
5138
+ this.name = "DaemonRequestCancelledError";
5139
+ }
5140
+ }
5141
+
5142
+ class DaemonRequestTimedOutError extends DaemonRequestError {
5143
+ timeoutMs;
5144
+ constructor(requestWritten, timeoutMs) {
5145
+ super("daemon request timed out", requestWritten);
5146
+ this.name = "DaemonRequestTimedOutError";
5147
+ this.timeoutMs = timeoutMs;
5148
+ }
5149
+ }
5150
+
5151
+ // src/daemon-failure-result.ts
5152
+ function daemonFailureResult(paths, error) {
5153
+ if (error instanceof DaemonRequestCancelledError)
5154
+ return daemonCancelledResult(paths);
5155
+ if (error instanceof DaemonRequestTimedOutError)
5156
+ return daemonTimedOutResult(paths, error.timeoutMs);
5157
+ return daemonUnreachableResult(paths, error);
5158
+ }
5159
+ function daemonCancelledResult(paths) {
5160
+ const text2 = [
5161
+ "LSP daemon request cancelled: the caller aborted this request (for example, the turn was interrupted).",
5162
+ "The daemon stays available; no LSP work was applied. Retry when you are ready.",
5163
+ `Socket: ${paths.socket}`
5164
+ ].join(`
5165
+ `);
5166
+ return { content: [{ type: "text", text: text2 }], isError: true };
5167
+ }
5168
+ function daemonTimedOutResult(paths, timeoutMs) {
5169
+ const text2 = [
5170
+ `LSP daemon request timed out after ${timeoutMs}ms: the daemon did not respond in time.`,
5171
+ "The daemon stays available but may be busy. Retry when you are ready.",
5172
+ `Socket: ${paths.socket}`,
5173
+ `Logs: ${paths.log}`
5174
+ ].join(`
5175
+ `);
5176
+ return { content: [{ type: "text", text: text2 }], isError: true };
5177
+ }
5178
+ function daemonUnreachableResult(paths, error) {
5179
+ const text2 = [
5180
+ `LSP daemon unreachable: ${errorText(error)}.`,
5181
+ "The MCP server is a thin proxy and never runs language servers in-process.",
5182
+ `Socket: ${paths.socket}`,
5183
+ `Logs: ${paths.log}`,
5184
+ "The daemon is auto-started on demand and will be retried on the next request."
5185
+ ].join(`
5186
+ `);
5187
+ return { content: [{ type: "text", text: text2 }], isError: true };
5188
+ }
5189
+ function errorText(error) {
5190
+ return error instanceof Error ? error.message : String(error);
5191
+ }
5192
+
5068
5193
  // src/ensure-daemon.ts
5069
5194
  import { spawn as spawn2 } from "node:child_process";
5070
5195
  import { closeSync as closeSync2, mkdirSync as mkdirSync3, openSync as openSync2 } from "node:fs";
@@ -5724,29 +5849,6 @@ function parseContext(value) {
5724
5849
  // src/daemon-client.ts
5725
5850
  var DEFAULT_REQUEST_TIMEOUT_MS = 30000;
5726
5851
  var nextProxyRequestId = 1;
5727
-
5728
- class DaemonRequestError extends Error {
5729
- requestWritten;
5730
- constructor(message, requestWritten) {
5731
- super(message);
5732
- this.name = "DaemonRequestError";
5733
- this.requestWritten = requestWritten;
5734
- }
5735
- }
5736
-
5737
- class DaemonAuthenticationRejectedError extends DaemonRequestError {
5738
- constructor() {
5739
- super("daemon authentication failed before dispatch", true);
5740
- this.name = "DaemonAuthenticationRejectedError";
5741
- }
5742
- }
5743
-
5744
- class DaemonRequestCancelledError extends DaemonRequestError {
5745
- constructor(requestWritten) {
5746
- super("daemon request cancelled", requestWritten);
5747
- this.name = "DaemonRequestCancelledError";
5748
- }
5749
- }
5750
5852
  async function callToolViaDaemon(name, args, options) {
5751
5853
  const context = requireContext(options.context);
5752
5854
  const paths = options.paths ?? daemonPaths();
@@ -5775,7 +5877,7 @@ async function callToolViaDaemon(name, args, options) {
5775
5877
  break;
5776
5878
  }
5777
5879
  }
5778
- return daemonUnreachableResult(paths, lastError);
5880
+ return daemonFailureResult(paths, lastError);
5779
5881
  }
5780
5882
  function callDiagnosticsViaDaemon(filePath, options) {
5781
5883
  return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
@@ -5820,17 +5922,6 @@ function ensureDaemonAvailable(paths, ensure, signal) {
5820
5922
  Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve9()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
5821
5923
  });
5822
5924
  }
5823
- function daemonUnreachableResult(paths, error) {
5824
- const text2 = [
5825
- `LSP daemon unreachable: ${errorText(error)}.`,
5826
- "The MCP server is a thin proxy and never runs language servers in-process.",
5827
- `Socket: ${paths.socket}`,
5828
- `Logs: ${paths.log}`,
5829
- "The daemon is auto-started on demand and will be retried on the next request."
5830
- ].join(`
5831
- `);
5832
- return { content: [{ type: "text", text: text2 }], isError: true };
5833
- }
5834
5925
  function sendToolCall(paths, token, name, args, options) {
5835
5926
  return new Promise((resolve9, reject) => {
5836
5927
  const socket = connect(paths.socket);
@@ -5870,7 +5961,7 @@ function sendToolCall(paths, token, name, args, options) {
5870
5961
  };
5871
5962
  const timer = setTimeout(() => {
5872
5963
  sendCancel();
5873
- finish(() => reject(new DaemonRequestError("daemon request timed out", requestWritten)));
5964
+ finish(() => reject(new DaemonRequestTimedOutError(requestWritten, options.timeoutMs)));
5874
5965
  }, options.timeoutMs);
5875
5966
  timer.unref();
5876
5967
  if (options.signal?.aborted) {
@@ -5929,9 +6020,6 @@ function allocateProxyRequestId() {
5929
6020
  function isRetryableTool(name) {
5930
6021
  return name !== "rename" && name !== "lsp_rename";
5931
6022
  }
5932
- function errorText(error) {
5933
- return error instanceof Error ? error.message : String(error);
5934
- }
5935
6023
 
5936
6024
  // src/proxy.ts
5937
6025
  var DEFAULT_STARTUP_TIMEOUT_MS = 1e4;
@@ -5988,6 +6076,7 @@ async function runMcpStdioProxy(options = {}) {
5988
6076
  input,
5989
6077
  output,
5990
6078
  idleTimeoutMs: 0,
6079
+ parentWatchdog: options.parentWatchdog ?? {},
5991
6080
  handler: (request, requestOptions) => {
5992
6081
  clearStartupWatchdog();
5993
6082
  return runWithRequestContext(context, () => handleProxyRequest(request, requestOptions));
@@ -6081,7 +6170,7 @@ import { dirname as dirname11 } from "node:path";
6081
6170
  // src/lock.ts
6082
6171
  import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeSync as writeSync2 } from "node:fs";
6083
6172
  import { dirname as dirname10 } from "node:path";
6084
- function isProcessAlive(pid) {
6173
+ function isProcessAlive2(pid) {
6085
6174
  if (!Number.isInteger(pid) || pid <= 0)
6086
6175
  return false;
6087
6176
  try {
@@ -6127,7 +6216,7 @@ function writeLockFile(lockPath, ownerPid) {
6127
6216
  }
6128
6217
  function reapStaleLock(lockPath) {
6129
6218
  const pid = readLockPid(lockPath);
6130
- if (pid !== null && isProcessAlive(pid))
6219
+ if (pid !== null && isProcessAlive2(pid))
6131
6220
  return false;
6132
6221
  unlinkQuietly(lockPath);
6133
6222
  return true;
@@ -6249,7 +6338,7 @@ async function validateExistingOwner(paths, pingOwner) {
6249
6338
  }
6250
6339
  if (ping)
6251
6340
  continue;
6252
- if (isProcessAlive(owner.pid))
6341
+ if (isProcessAlive2(owner.pid))
6253
6342
  throw new DaemonStartupDeferredError("owner_pid_live_unreachable");
6254
6343
  const reread = readDaemonOwner(paths);
6255
6344
  const endpoint = endpointIdentity(owner.endpoint.path);
@@ -6311,6 +6400,184 @@ function parseEndpoint(value) {
6311
6400
  return null;
6312
6401
  }
6313
6402
 
6403
+ // src/version-reap.ts
6404
+ import { execFile } from "node:child_process";
6405
+ import { readdir, readFile, rm } from "node:fs/promises";
6406
+ import { basename as basename4, dirname as dirname12, join as join8 } from "node:path";
6407
+ var TERM_GRACE_MS = 5000;
6408
+ var KILL_GRACE_MS = 1000;
6409
+ var VERSION_ENTRY_PATTERN = /^v([A-Za-z0-9][A-Za-z0-9._+-]{0,127})$/;
6410
+ async function attestDaemonCliProcess(pid, platform, deps = {}) {
6411
+ if (platform === "win32")
6412
+ return false;
6413
+ if (platform === "linux") {
6414
+ const readProcFile = deps.readProcFile ?? defaultReadProcFile;
6415
+ const cmdline = await readProcFile(`/proc/${pid}/cmdline`).catch(() => null);
6416
+ if (cmdline === null)
6417
+ return false;
6418
+ return isNodeCliDaemonArgv(splitCmdline(cmdline));
6419
+ }
6420
+ const executeForStdout = deps.executeForStdout ?? defaultExecuteForStdout;
6421
+ const command = await executeForStdout("/bin/ps", ["-p", String(pid), "-o", "command="]);
6422
+ if (command === null)
6423
+ return false;
6424
+ return isNodeCliDaemonCommand(command.trim());
6425
+ }
6426
+ async function reapStaleDaemonVersions(ownPaths, deps = {}) {
6427
+ const baseDir = dirname12(ownPaths.dir);
6428
+ const platform = deps.platform ?? process.platform;
6429
+ const isAlive = deps.isAlive ?? isProcessAlive2;
6430
+ const attest = deps.attest ?? ((pid) => attestDaemonCliProcess(pid, platform));
6431
+ const sendSignal = deps.sendSignal ?? defaultSendSignal;
6432
+ const waitForExit = deps.waitForExit ?? defaultWaitForExit;
6433
+ const removeDir = deps.removeDir ?? ((path2) => rm(path2, { recursive: true, force: true }));
6434
+ const readOwner = deps.readOwner ?? readDaemonOwner;
6435
+ const log = deps.log ?? defaultLog;
6436
+ const termGraceMs = deps.termGraceMs ?? TERM_GRACE_MS;
6437
+ const killGraceMs = deps.killGraceMs ?? KILL_GRACE_MS;
6438
+ const entries = await readdir(baseDir, { withFileTypes: true }).catch(() => []);
6439
+ const results = [];
6440
+ for (const entry of [...entries].sort((left, right) => left.name.localeCompare(right.name))) {
6441
+ if (entry.name === `v${ownPaths.version}`)
6442
+ continue;
6443
+ const version = parseVersionEntry(entry.name);
6444
+ if (version === null || !entry.isDirectory())
6445
+ continue;
6446
+ const versionDir = join8(baseDir, entry.name);
6447
+ const siblingPaths = daemonPaths({ [OMO_LSP_DAEMON_DIR]: baseDir }, { cliPath: ownPaths.cliPath, version });
6448
+ results.push(await reapOneVersion({
6449
+ version,
6450
+ versionDir,
6451
+ siblingPaths,
6452
+ platform,
6453
+ isAlive,
6454
+ attest,
6455
+ sendSignal,
6456
+ waitForExit,
6457
+ removeDir,
6458
+ readOwner,
6459
+ log,
6460
+ termGraceMs,
6461
+ killGraceMs
6462
+ }));
6463
+ }
6464
+ return results;
6465
+ }
6466
+ async function reapOneVersion(context) {
6467
+ const { version, versionDir } = context;
6468
+ const owner = context.readOwner(context.siblingPaths);
6469
+ if (!owner) {
6470
+ const lockPid = readLockPid(join8(versionDir, "daemon.lock"));
6471
+ if (lockPid !== null && context.isAlive(lockPid)) {
6472
+ context.log(`reap: sparing v${version}: owner metadata missing but daemon.lock is held by live pid ${lockPid}`);
6473
+ return { version, status: "spared", reason: `owner metadata missing but lock held by live pid ${lockPid}` };
6474
+ }
6475
+ await context.removeDir(versionDir);
6476
+ return { version, status: "removed", reason: "removed stale version dir without readable owner metadata" };
6477
+ }
6478
+ if (!context.isAlive(owner.pid)) {
6479
+ await context.removeDir(versionDir);
6480
+ return { version, status: "removed", reason: `removed stale version dir for dead owner pid ${owner.pid}` };
6481
+ }
6482
+ if (context.platform === "win32") {
6483
+ context.log(`reap: deferring v${version}: Windows cannot prove pid ownership safely (named-pipe policy)`);
6484
+ return {
6485
+ version,
6486
+ status: "deferred",
6487
+ reason: "Windows cannot prove pid ownership safely; named-pipe reap deferred"
6488
+ };
6489
+ }
6490
+ if (!await context.attest(owner.pid, context.platform)) {
6491
+ context.log(`reap: sparing v${version}: pid ${owner.pid} is alive but cmdline attestation failed (possible recycled pid)`);
6492
+ return {
6493
+ version,
6494
+ status: "spared",
6495
+ reason: `pid ${owner.pid} attestation failed; possible recycled pid`
6496
+ };
6497
+ }
6498
+ return await terminateAttestedOwner(context, owner.pid);
6499
+ }
6500
+ async function terminateAttestedOwner(context, pid) {
6501
+ const { version, versionDir } = context;
6502
+ if (!context.sendSignal(pid, "SIGTERM")) {
6503
+ await context.removeDir(versionDir);
6504
+ return {
6505
+ version,
6506
+ status: "removed",
6507
+ reason: `owner pid ${pid} exited before SIGTERM; removed stale version dir`
6508
+ };
6509
+ }
6510
+ if (await context.waitForExit(pid, context.termGraceMs)) {
6511
+ await context.removeDir(versionDir);
6512
+ return { version, status: "terminated", reason: `terminated attested older daemon pid ${pid} with SIGTERM` };
6513
+ }
6514
+ context.log(`reap: v${version} pid ${pid} survived SIGTERM; escalating to SIGKILL`);
6515
+ if (!context.sendSignal(pid, "SIGKILL") || !await context.waitForExit(pid, context.killGraceMs)) {
6516
+ context.log(`reap: deferring v${version}: pid ${pid} survived SIGKILL`);
6517
+ return { version, status: "deferred", reason: `attested daemon pid ${pid} survived SIGKILL; dir kept` };
6518
+ }
6519
+ await context.removeDir(versionDir);
6520
+ return {
6521
+ version,
6522
+ status: "terminated",
6523
+ reason: `terminated attested older daemon pid ${pid} after SIGKILL escalation`
6524
+ };
6525
+ }
6526
+ function parseVersionEntry(entryName) {
6527
+ const match = VERSION_ENTRY_PATTERN.exec(entryName);
6528
+ return match?.[1] ?? null;
6529
+ }
6530
+ function splitCmdline(buffer) {
6531
+ return buffer.toString("utf8").split("\x00").filter((value) => value.length > 0);
6532
+ }
6533
+ function isNodeCliDaemonArgv(argv) {
6534
+ if (argv.length < 2 || !argv.includes("daemon"))
6535
+ return false;
6536
+ const executable = basename4(argv[0] ?? "");
6537
+ if (!/^node(?:\.exe)?$/i.test(executable))
6538
+ return false;
6539
+ return argv.some((value) => value === "cli.js" || value.endsWith("/cli.js") || value.endsWith("\\cli.js"));
6540
+ }
6541
+ function isNodeCliDaemonCommand(command) {
6542
+ return /\bnode(?:\.exe)?\b/i.test(command) && /\bcli\.js\b/.test(command) && /\bdaemon\b/.test(command);
6543
+ }
6544
+ function defaultReadProcFile(path2) {
6545
+ return readFile(path2);
6546
+ }
6547
+ function defaultExecuteForStdout(file, args) {
6548
+ return new Promise((resolve9) => {
6549
+ execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000 }, (error, stdout) => {
6550
+ if (error !== null) {
6551
+ resolve9(null);
6552
+ return;
6553
+ }
6554
+ resolve9(stdout);
6555
+ });
6556
+ });
6557
+ }
6558
+ function defaultSendSignal(pid, signal) {
6559
+ try {
6560
+ process.kill(pid, signal);
6561
+ return true;
6562
+ } catch {
6563
+ return false;
6564
+ }
6565
+ }
6566
+ async function defaultWaitForExit(pid, timeoutMs) {
6567
+ const deadline = Date.now() + timeoutMs;
6568
+ for (;; ) {
6569
+ if (!isProcessAlive2(pid))
6570
+ return true;
6571
+ if (Date.now() >= deadline)
6572
+ return false;
6573
+ await new Promise((resolve9) => setTimeout(resolve9, 100));
6574
+ }
6575
+ }
6576
+ function defaultLog(message) {
6577
+ process.stderr.write(`[lsp-daemon] ${message}
6578
+ `);
6579
+ }
6580
+
6314
6581
  // src/daemon-server.ts
6315
6582
  var DEFAULT_IDLE_SHUTDOWN_MS = 30 * 60000;
6316
6583
  var DEFAULT_IDLE_CHECK_INTERVAL_MS = 60000;
@@ -6357,6 +6624,7 @@ async function startDaemonServer(paths, options = {}) {
6357
6624
  throw error;
6358
6625
  }
6359
6626
  lease.lock.release();
6627
+ reapStaleDaemonVersions(paths).catch((error) => logServerError(error));
6360
6628
  let closed = false;
6361
6629
  const close = async () => {
6362
6630
  if (closed)