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
@@ -0,0 +1,176 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join, resolve } from "node:path";
5
+ import { Readable } from "node:stream";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ import { executeCodegraphSessionStartHook, type WorkerSpawnInvocation } from "../src/hook.ts";
9
+
10
+ const pluginRoot = resolve(fileURLToPath(new URL("../../..", import.meta.url)));
11
+
12
+ // Observed verbatim from a REAL codegraph 1.4.1 binary running `status --json` (exit 0)
13
+ // against a project store built by a REAL codegraph 1.0.1 binary
14
+ // (see .omo/evidence/codegraph-daemon-process-hygiene/task-2-store-upgrade.txt).
15
+ const MIGRATED_1_0_1_STORE_STATUS_JSON = JSON.stringify({
16
+ initialized: true,
17
+ version: "1.4.1",
18
+ projectPath: "/private/tmp/cg-task2/fixture",
19
+ indexPath: "/private/tmp/cg-task2/fixture/.codegraph",
20
+ lastIndexed: "2026-07-21T04:28:09.593Z",
21
+ fileCount: 2,
22
+ nodeCount: 5,
23
+ edgeCount: 4,
24
+ dbSizeBytes: 159744,
25
+ backend: "node-sqlite",
26
+ journalMode: "wal",
27
+ nodesByKind: { file: 2, function: 3 },
28
+ languages: ["typescript"],
29
+ pendingChanges: { added: 0, modified: 0, removed: 0 },
30
+ worktreeMismatch: null,
31
+ index: {
32
+ builtWithVersion: "1.0.1",
33
+ builtWithExtractionVersion: 24,
34
+ currentExtractionVersion: 24,
35
+ reindexRecommended: false,
36
+ state: null,
37
+ pendingRefs: 0,
38
+ },
39
+ });
40
+
41
+ function createAllowedWorkspace(prefix: string): string {
42
+ return mkdtempSync(join(pluginRoot, `.tmp-${prefix}-`));
43
+ }
44
+
45
+ // On win32 execFile cannot run a #!/bin/sh script, so emit a codegraph.cmd batch file instead;
46
+ // resolveCodegraphCommandInvocation wraps .cmd in `cmd.exe /d /s /c`, exactly like the real codegraph.cmd.
47
+ function createFakeCodegraphBin(scripts: {
48
+ readonly posix: string;
49
+ readonly win32: string;
50
+ readonly win32Sidecar?: string;
51
+ }): { readonly binPath: string; readonly dir: string } {
52
+ const dir = mkdtempSync(join(tmpdir(), "omo-codegraph-fake-bin-"));
53
+ if (process.platform === "win32") {
54
+ const binPath = join(dir, "codegraph.cmd");
55
+ writeFileSync(binPath, scripts.win32);
56
+ if (scripts.win32Sidecar !== undefined) writeFileSync(join(dir, "hang.cjs"), scripts.win32Sidecar);
57
+ return { binPath, dir };
58
+ }
59
+ const binPath = join(dir, "codegraph");
60
+ writeFileSync(binPath, scripts.posix, { mode: 0o755 });
61
+ chmodSync(binPath, 0o755);
62
+ return { binPath, dir };
63
+ }
64
+
65
+ // Keep the probe hermetic on POSIX but viable on win32: resolveCodegraphCommandInvocation wraps
66
+ // the fake .cmd in `cmd.exe /d /s /c`, and Windows can only resolve cmd.exe when the child env
67
+ // carries the real system PATH (System32) plus SystemRoot (both whitelisted in SAFE_AMBIENT_ENV_KEYS).
68
+ // A POSIX-only PATH makes the probe spawn fail, so the hook reports not-initialized and spawns.
69
+ function probeEnv(homeDir: string, binPath: string): Record<string, string> {
70
+ if (process.platform === "win32") {
71
+ const env: Record<string, string> = {
72
+ HOME: homeDir,
73
+ OMO_CODEGRAPH_BIN: binPath,
74
+ };
75
+ if (process.env["PATH"] !== undefined) env["PATH"] = process.env["PATH"];
76
+ if (process.env["SystemRoot"] !== undefined) env["SystemRoot"] = process.env["SystemRoot"];
77
+ return env;
78
+ }
79
+ return { HOME: homeDir, OMO_CODEGRAPH_BIN: binPath, PATH: "/usr/bin:/bin" };
80
+ }
81
+
82
+ function isProcessAlive(pid: number): boolean {
83
+ try {
84
+ process.kill(pid, 0);
85
+ return true;
86
+ } catch {
87
+ return false;
88
+ }
89
+ }
90
+
91
+ describe("CodeGraph SessionStart hook with a 1.0.1-era project store under the 1.4.1 binary", () => {
92
+ it("#given a real 1.4.1 status payload for a migrated 1.0.1 store #when SessionStart probes via the default probe #then it stays silent without spawning a re-init worker", async () => {
93
+ // given
94
+ const stdout: string[] = [];
95
+ const spawned: WorkerSpawnInvocation[] = [];
96
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-upgrade-home-"));
97
+ // The payload is a single JSON line with no cmd metacharacters (% ^ & < > |), so a plain echo is safe.
98
+ const fake = createFakeCodegraphBin({
99
+ posix: `#!/bin/sh\nprintf '%s\\n' '${MIGRATED_1_0_1_STORE_STATUS_JSON}'\n`,
100
+ win32: `@echo off\r\n@echo ${MIGRATED_1_0_1_STORE_STATUS_JSON}\r\n`,
101
+ });
102
+ const workspace = createAllowedWorkspace("codegraph-upgrade-workspace");
103
+ mkdirSync(join(workspace, ".codegraph"), { recursive: true });
104
+
105
+ try {
106
+ // when
107
+ const result = await executeCodegraphSessionStartHook({
108
+ config: { codegraph: { enabled: true }, sources: [], warnings: [] },
109
+ cwd: workspace,
110
+ env: probeEnv(homeDir, fake.binPath),
111
+ stdin: Readable.from(["{}"]),
112
+ stdout: { write: (chunk) => stdout.push(chunk) },
113
+ spawnWorker: (invocation) => spawned.push(invocation),
114
+ });
115
+
116
+ // then
117
+ expect(result).toEqual({ action: "skipped-initialized", exitCode: 0 });
118
+ expect(spawned).toEqual([]);
119
+ expect(stdout.join("")).toBe("");
120
+ } finally {
121
+ rmSync(homeDir, { recursive: true, force: true });
122
+ rmSync(fake.dir, { recursive: true, force: true });
123
+ rmSync(workspace, { recursive: true, force: true, maxRetries: 10, retryDelay: 500 });
124
+ }
125
+ });
126
+
127
+ it("#given the status probe spawns a hanging descendant #when SessionStart times out #then it exits promptly and reaps the descendant", async () => {
128
+ // given
129
+ const stdout: string[] = [];
130
+ const spawned: WorkerSpawnInvocation[] = [];
131
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-slow-home-"));
132
+ const survivorPidPath = join(homeDir, "survivor.pid");
133
+ const fake = createFakeCodegraphBin({
134
+ posix: "#!/bin/sh\nsleep 30 &\necho \"$!\" > \"$HOME/survivor.pid\"\nwait\n",
135
+ win32: '@echo off\r\nnode "%~dp0hang.cjs"\r\n',
136
+ win32Sidecar: [
137
+ 'const { spawn } = require("node:child_process");',
138
+ 'const { writeFileSync } = require("node:fs");',
139
+ 'const { join } = require("node:path");',
140
+ 'const child = spawn(process.execPath, ["-e", "setInterval(() => {}, 1000)"], { stdio: "ignore" });',
141
+ 'writeFileSync(join(process.env.HOME, "survivor.pid"), String(child.pid));',
142
+ "setInterval(() => {}, 1000);",
143
+ "",
144
+ ].join("\n"),
145
+ });
146
+ const workspace = createAllowedWorkspace("codegraph-slow-probe-workspace");
147
+ let descendantPid: number | undefined;
148
+
149
+ try {
150
+ // when
151
+ const startedAt = Date.now();
152
+ const result = await executeCodegraphSessionStartHook({
153
+ config: { codegraph: { enabled: true }, sources: [], warnings: [] },
154
+ cwd: workspace,
155
+ env: probeEnv(homeDir, fake.binPath),
156
+ stdin: Readable.from(["{}"]),
157
+ stdout: { write: (chunk) => stdout.push(chunk) },
158
+ spawnWorker: (invocation) => spawned.push(invocation),
159
+ });
160
+ const elapsedMs = Date.now() - startedAt;
161
+ descendantPid = Number.parseInt(readFileSync(survivorPidPath, "utf8").trim(), 10);
162
+
163
+ // then
164
+ expect(result.exitCode).toBe(0);
165
+ expect(result.action).toBe("spawned");
166
+ expect(spawned).toHaveLength(1);
167
+ expect(elapsedMs).toBeLessThan(15_000);
168
+ expect(isProcessAlive(descendantPid)).toBeFalse();
169
+ } finally {
170
+ if (descendantPid !== undefined && isProcessAlive(descendantPid)) process.kill(descendantPid, "SIGKILL");
171
+ rmSync(homeDir, { recursive: true, force: true });
172
+ rmSync(fake.dir, { recursive: true, force: true });
173
+ rmSync(workspace, { recursive: true, force: true, maxRetries: 10, retryDelay: 500 });
174
+ }
175
+ });
176
+ });
@@ -215,6 +215,7 @@ describe("CodeGraph SessionStart hook", () => {
215
215
  // given
216
216
  const stdout: string[] = [];
217
217
  const spawned: WorkerSpawnInvocation[] = [];
218
+ const statusProbeDaemonValues: boolean[] = [];
218
219
  const workspace = createAllowedWorkspace("codegraph-workspace");
219
220
 
220
221
  try {
@@ -226,12 +227,16 @@ describe("CodeGraph SessionStart hook", () => {
226
227
  stdin: Readable.from(["{}"]),
227
228
  stdout: { write: (chunk) => stdout.push(chunk) },
228
229
  spawnWorker: (invocation) => spawned.push(invocation),
229
- statusProbe: () => Promise.resolve(false),
230
+ statusProbe: (options) => {
231
+ statusProbeDaemonValues.push(options.daemon);
232
+ return Promise.resolve(false);
233
+ },
230
234
  workerCliPath: "/plugin/components/codegraph/dist/cli.js",
231
235
  });
232
236
 
233
237
  // then
234
238
  expect(result).toEqual({ action: "spawned", exitCode: 0 });
239
+ expect(statusProbeDaemonValues).toEqual([true]);
235
240
  expect(spawned).toEqual([
236
241
  {
237
242
  args: ["/plugin/components/codegraph/dist/cli.js", "hook", "session-start-worker"],
@@ -1,5 +1,34 @@
1
1
  import { chmodSync, writeFileSync } from "node:fs";
2
2
 
3
+ export const CODEGRAPH_141_DEFAULT_TOOLS: readonly Record<string, unknown>[] = [
4
+ {
5
+ name: "codegraph_explore",
6
+ description:
7
+ "PRIMARY TOOL — call FIRST for almost any question OR before an edit: how does X work, architecture, a bug, where/what is X, surveying an area, or the symbols you are about to change. Returns the verbatim source of the relevant symbols grouped by file in ONE capped call (Read-equivalent — treat the shown source as already Read; do NOT re-open those files), plus the call path among them. Query can be a natural-language question OR a bag of symbol/file names. Usually the ONLY call you need — more accurate context, in far fewer tokens and round-trips than a search/Read/Grep loop.",
8
+ inputSchema: {
9
+ type: "object",
10
+ properties: {
11
+ query: {
12
+ type: "string",
13
+ description:
14
+ 'Symbol names, file names, or short code terms to explore (e.g., "AuthService loginUser session-manager", "GraphTraverser BFS impact traversal.ts"). For a flow question, name the symbols spanning the flow (e.g. "mutateElement renderScene"). A natural-language question works too — no prior codegraph_search needed.',
15
+ },
16
+ maxFiles: {
17
+ type: "number",
18
+ description: "Maximum number of files to include source code from (default: 12)",
19
+ default: 12,
20
+ },
21
+ projectPath: {
22
+ type: "string",
23
+ description:
24
+ "Absolute path to the project to query (or any directory inside it) — codegraph uses the nearest .codegraph/ index at or above that path. Omit to use this session's default project. Pass it to query a second codebase, or when the server root has no index of its own (e.g. a monorepo where only sub-projects are indexed, so there is no default project).",
25
+ },
26
+ },
27
+ required: ["query"],
28
+ },
29
+ },
30
+ ];
31
+
3
32
  export function writeFakeNewlineCodegraph(filePath: string): void {
4
33
  writeFileSync(
5
34
  filePath,
@@ -12,10 +41,10 @@ export function writeFakeNewlineCodegraph(filePath: string): void {
12
41
  "rl.on('line', (line) => {",
13
42
  " const request = JSON.parse(line);",
14
43
  " if (request.method === 'initialize') {",
15
- " process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { capabilities: { tools: { listChanged: false } }, protocolVersion: request.params.protocolVersion, serverInfo: { name: 'codegraph', version: '1.0.1' } } }) + '\\n');",
44
+ " process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { capabilities: { tools: { listChanged: false } }, protocolVersion: request.params.protocolVersion, serverInfo: { name: 'codegraph', version: '1.4.1' } } }) + '\\n');",
16
45
  " }",
17
46
  " if (request.method === 'tools/list') {",
18
- " process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { tools: [{ name: 'codegraph_search' }, { name: 'codegraph_node' }, { name: 'codegraph_explore' }, { name: 'codegraph_callers' }] } }) + '\\n');",
47
+ ` process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { tools: ${JSON.stringify(CODEGRAPH_141_DEFAULT_TOOLS)} } }) + '\\n');`,
19
48
  " }",
20
49
  "});",
21
50
  ].join("\n"),
@@ -43,7 +43,7 @@ describe("CodeGraph component runtime package metadata", () => {
43
43
  const files = packageJson.files ?? [];
44
44
 
45
45
  // then
46
- expect(optionalDependencies["@colbymchenry/codegraph"]).toBe("1.0.1");
46
+ expect(optionalDependencies["@colbymchenry/codegraph"]).toBe("1.4.1");
47
47
  expect(files).toContain("LICENSE");
48
48
  expect(files).toContain("NODE-RUNTIME-LICENSES.md");
49
49
  expect(files).toContain("NOTICE");
@@ -3,6 +3,7 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
 
6
+ import { CODEGRAPH_PINNED_VERSION } from "../../../../../utils/src/codegraph/manifest.ts";
6
7
  import { runCodegraphSessionStartWorker } from "../src/hook.ts";
7
8
  import { runCodegraphServe } from "../src/serve.ts";
8
9
 
@@ -41,7 +42,12 @@ describe("CodeGraph provisioned launcher Node guard", () => {
41
42
 
42
43
  try {
43
44
  mkdirSync(join(installDir, "bin"), { recursive: true });
45
+ mkdirSync(join(installDir, ".provisioned"), { recursive: true });
44
46
  writeFileSync(binPath, "");
47
+ writeFileSync(
48
+ join(installDir, ".provisioned", `codegraph-${CODEGRAPH_PINNED_VERSION}.json`),
49
+ `${JSON.stringify({ binPath, version: CODEGRAPH_PINNED_VERSION })}\n`,
50
+ );
45
51
 
46
52
  // when
47
53
  const result = await runCodegraphSessionStartWorker({
@@ -1,13 +1,15 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { mkdirSync, mkdtempSync, realpathSync, rmSync } from "node:fs";
2
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { PassThrough, Writable } from "node:stream";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
+ import { isProcessAlive } from "../../../../../mcp-stdio-core/src/index.ts";
7
8
  import { runCodegraphServe } from "../src/serve.ts";
8
9
  import {
9
10
  frameMcpRequest,
10
11
  writeFakeExitingCodegraph,
12
+ writeFakeHeldOpenCodegraph,
11
13
  } from "./mcp-bridge-fixtures.ts";
12
14
 
13
15
  const componentRoot = realpathSync(
@@ -66,4 +68,66 @@ describe("runCodegraphServe MCP bridge lifecycle", () => {
66
68
  rmSync(tempRoot, { recursive: true, force: true });
67
69
  }
68
70
  });
71
+
72
+ it("#given a held-open Codegraph child and a dead parent #when the bridge watchdog polls #then the child is terminated and the bridge settles through the child-exit path", async () => {
73
+ // given
74
+ const tempRoot = mkdtempSync(
75
+ join(componentRoot, ".tmp-codegraph-orphan-"),
76
+ );
77
+ const projectRoot = join(tempRoot, "project");
78
+ const fakeCodegraph = join(tempRoot, "codegraph-held-open.cjs");
79
+ const childPidFile = join(tempRoot, "child.pid");
80
+ // Client stdio is held open and never sees EOF, so the parent-liveness
81
+ // watchdog is the only settle path. The probe reports the parent alive
82
+ // until the child has started, making the poll fire deterministically.
83
+ const input = new PassThrough();
84
+ const output = new PassThrough();
85
+ output.resume();
86
+ let childPid: number | undefined;
87
+
88
+ try {
89
+ mkdirSync(projectRoot, { recursive: true });
90
+ writeFakeHeldOpenCodegraph(fakeCodegraph);
91
+ const run = runCodegraphServe({
92
+ cwd: tempRoot,
93
+ env: {
94
+ CODEGRAPH_ALLOW_UNSAFE_NODE: "1",
95
+ CODEGRAPH_FAKE_LOG: childPidFile,
96
+ OMO_CODEGRAPH_BIN: fakeCodegraph,
97
+ OMO_CODEGRAPH_PROJECT_CWD: projectRoot,
98
+ PATH: process.env["PATH"],
99
+ },
100
+ nodeVersion: "22.14.0",
101
+ buildEnv: () => ({}),
102
+ resolve: () => ({
103
+ argsPrefix: [],
104
+ command: fakeCodegraph,
105
+ exists: true,
106
+ source: "env",
107
+ }),
108
+ stderr: { write: () => undefined },
109
+ stdin: input,
110
+ stdout: output,
111
+ parentWatchdog: {
112
+ pollIntervalMs: 10,
113
+ probeAlive: () => !existsSync(childPidFile),
114
+ },
115
+ });
116
+
117
+ // when
118
+ const exitCode = await run;
119
+
120
+ // then
121
+ expect(exitCode).not.toBe(0);
122
+ childPid = Number(readFileSync(childPidFile, "utf8"));
123
+ expect(isProcessAlive(childPid)).toBe(false);
124
+ } finally {
125
+ if (childPid !== undefined && isProcessAlive(childPid)) {
126
+ process.kill(childPid, "SIGKILL");
127
+ }
128
+ input.destroy();
129
+ output.destroy();
130
+ rmSync(tempRoot, { recursive: true, force: true });
131
+ }
132
+ });
69
133
  });
@@ -7,6 +7,7 @@ import { fileURLToPath } from "node:url";
7
7
  import { runCodegraphServe } from "../src/serve.ts";
8
8
  import {
9
9
  arrayProperty,
10
+ CODEGRAPH_141_DEFAULT_TOOLS,
10
11
  findTool,
11
12
  frameMcpRequest,
12
13
  parseMcpBodies,
@@ -86,19 +87,14 @@ describe("runCodegraphServe MCP protocol bridge", () => {
86
87
  result: {
87
88
  capabilities: { tools: { listChanged: false } },
88
89
  protocolVersion: "2025-06-18",
89
- serverInfo: { name: "codegraph", version: "1.0.1" },
90
+ serverInfo: { name: "codegraph", version: "1.4.1" },
90
91
  },
91
92
  },
92
93
  {
93
94
  id: 2,
94
95
  jsonrpc: "2.0",
95
96
  result: {
96
- tools: [
97
- { name: "codegraph_search" },
98
- { name: "codegraph_node" },
99
- { name: "codegraph_explore" },
100
- { name: "codegraph_callers" },
101
- ],
97
+ tools: CODEGRAPH_141_DEFAULT_TOOLS,
102
98
  },
103
99
  },
104
100
  ]);
@@ -17,6 +17,7 @@ describe("runCodegraphServe MCP unavailable facade", () => {
17
17
  const run = runCodegraphServe({
18
18
  config: { codegraph: { auto_provision: false, enabled: true }, sources: [], warnings: [] },
19
19
  env: { PATH: "/bin" },
20
+ nodeVersion: "22.14.0",
20
21
  buildEnv: () => ({}),
21
22
  resolve: () => ({ argsPrefix: [], command: "codegraph", exists: false, source: "path" }),
22
23
  stderr: { write: (chunk: string) => stderr.push(chunk) },
@@ -47,7 +48,7 @@ describe("runCodegraphServe MCP unavailable facade", () => {
47
48
  result: {
48
49
  capabilities: { tools: { listChanged: false } },
49
50
  protocolVersion: "2025-06-18",
50
- serverInfo: { name: "codegraph", version: "1.0.1" },
51
+ serverInfo: { name: "codegraph", version: "1.4.1" },
51
52
  },
52
53
  });
53
54
  });
@@ -4,7 +4,7 @@ import { join } from "node:path";
4
4
  import { runCodegraphServe } from "../src/serve.ts";
5
5
 
6
6
  describe("runCodegraphServe provisioning", () => {
7
- it("#given CodeGraph is unresolved #when serving MCP #then provisions CodeGraph before spawning", async () => {
7
+ it("#given CodeGraph is unresolved and daemon is omitted #when serving MCP #then provisions CodeGraph with daemon-on", async () => {
8
8
  // given
9
9
  const binPath = join("/tmp/home/.omo/codegraph", "bin", "codegraph");
10
10
  const calls: Array<{
@@ -20,7 +20,6 @@ describe("runCodegraphServe provisioning", () => {
20
20
  env: { PATH: "/bin" },
21
21
  homeDir: "/tmp/home",
22
22
  nodeVersion: "22.14.0",
23
- buildEnv: () => ({}),
24
23
  resolve: () => ({ argsPrefix: [], command: "codegraph", exists: false, source: "path" }),
25
24
  ensureProvisioned: (options) =>
26
25
  Promise.resolve({
@@ -41,8 +40,63 @@ describe("runCodegraphServe provisioning", () => {
41
40
  {
42
41
  args: ["serve", "--mcp"],
43
42
  command: binPath,
44
- env: { CODEGRAPH_NO_DAEMON: "1", PATH: "/bin" },
43
+ env: {
44
+ CODEGRAPH_INSTALL_DIR: join("/tmp/home", ".omo", "codegraph"),
45
+ CODEGRAPH_NO_DOWNLOAD: "1",
46
+ CODEGRAPH_TELEMETRY: "0",
47
+ DO_NOT_TRACK: "1",
48
+ PATH: "/bin",
49
+ },
45
50
  },
46
51
  ]);
47
52
  });
53
+
54
+ it("#given CodeGraph is unresolved and codegraph.daemon=false #when serving MCP #then provisions CodeGraph with daemon-off", async () => {
55
+ // given
56
+ const binPath = join("/tmp/home/.omo/codegraph", "bin", "codegraph");
57
+ const calls: Array<{
58
+ readonly args: readonly string[];
59
+ readonly command: string;
60
+ readonly env: Record<string, string | undefined>;
61
+ }> = [];
62
+ const stderr: string[] = [];
63
+
64
+ // when
65
+ const exitCode = await runCodegraphServe({
66
+ config: { codegraph: { daemon: false, enabled: true }, sources: [], warnings: [] },
67
+ env: { PATH: "/bin" },
68
+ homeDir: "/tmp/home",
69
+ nodeVersion: "22.14.0",
70
+ resolve: () => ({ argsPrefix: [], command: "codegraph", exists: false, source: "path" }),
71
+ ensureProvisioned: (options) =>
72
+ Promise.resolve({
73
+ binPath: join(options.installDir ?? "/tmp/home/.omo/codegraph", "bin", "codegraph"),
74
+ provisioned: true,
75
+ }),
76
+ runProcess: (command, args, options) => {
77
+ calls.push({ args, command, env: options.env });
78
+ return Promise.resolve(0);
79
+ },
80
+ stderr: { write: (chunk: string) => stderr.push(chunk) },
81
+ });
82
+
83
+ // then
84
+ expect(exitCode).toBe(0);
85
+ expect(stderr).toEqual([]);
86
+ expect(calls).toEqual([
87
+ {
88
+ args: ["serve", "--mcp"],
89
+ command: binPath,
90
+ env: {
91
+ CODEGRAPH_INSTALL_DIR: join("/tmp/home", ".omo", "codegraph"),
92
+ CODEGRAPH_NO_DAEMON: "1",
93
+ CODEGRAPH_NO_DOWNLOAD: "1",
94
+ CODEGRAPH_TELEMETRY: "0",
95
+ DO_NOT_TRACK: "1",
96
+ PATH: "/bin",
97
+ },
98
+ },
99
+ ]);
100
+ expect(calls[0]?.env["CODEGRAPH_NO_DAEMON"]).toBe("1");
101
+ });
48
102
  });
@@ -17,6 +17,7 @@ describe("runCodegraphServe unavailable CodeGraph paths", () => {
17
17
  ...closedMcpStdio(),
18
18
  config: { codegraph: { auto_provision: false, enabled: true }, sources: [], warnings: [] },
19
19
  env: { PATH: "/bin" },
20
+ nodeVersion: "22.14.0",
20
21
  buildEnv: () => ({}),
21
22
  resolve: () => ({ argsPrefix: [], command: "codegraph", exists: false, source: "path" }),
22
23
  runProcess: (command: string) => {
@@ -122,6 +123,47 @@ describe("runCodegraphServe unavailable CodeGraph paths", () => {
122
123
  rmSync(workspace, { recursive: true, force: true });
123
124
  }
124
125
  });
126
+
127
+ it("#given the unavailable facade with held-open stdio and a dead parent #when the watchdog polls #then the placeholder server settles without waiting for stdin EOF", async () => {
128
+ // given
129
+ // win32: the real-timer watchdog + PassThrough.destroy() teardown race leaves
130
+ // the read loop's async iterator pending on Windows, so this held-open-stdin
131
+ // case cannot settle under bun:test (which has no fake timers). The watchdog
132
+ // settle path IS covered deterministically by mcp-stdio-core's fake-timer test
133
+ // (passes on win32) and by real-process QA (task-13-*); production settles via
134
+ // stdin EOF, exercised by the other tests in this file that run on win32.
135
+ if (process.platform === "win32") return;
136
+ // Client stdio is held open and never sees EOF, so the parent-liveness
137
+ // watchdog is the only settle path for the placeholder server.
138
+ const stdin = new PassThrough();
139
+ const stdout = new PassThrough();
140
+ stdout.resume();
141
+ const stderr: string[] = [];
142
+
143
+ try {
144
+ // when
145
+ const exitCode = await runCodegraphServe({
146
+ config: { codegraph: { enabled: false }, sources: [], warnings: [] },
147
+ env: {},
148
+ stdin,
149
+ stdout,
150
+ stderr: { write: (chunk: string) => stderr.push(chunk) },
151
+ parentWatchdog: { pollIntervalMs: 10, probeAlive: () => false },
152
+ });
153
+
154
+ // then
155
+ expect(exitCode).toBe(0);
156
+ expect(stderr).toEqual([
157
+ "CodeGraph MCP skipped: disabled by OMO SOT config. Set [codex].codegraph.enabled=true to enable it.\n",
158
+ ]);
159
+ } finally {
160
+ // The held-open streams are never ended by the test; destroy them so the
161
+ // bun test runner's event loop can drain and exit (an undestroyed
162
+ // PassThrough keeps the process alive on win32 and hangs the suite).
163
+ stdin.destroy();
164
+ stdout.destroy();
165
+ }
166
+ });
125
167
  });
126
168
 
127
169
  function closedMcpStdio(): { readonly stdin: PassThrough; readonly stdout: PassThrough } {