oh-my-opencode 4.19.1 → 4.19.3

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 (268) hide show
  1. package/.agents/command/publish.md +95 -28
  2. package/.agents/skills/publish/SKILL.md +20 -6
  3. package/.opencode/command/publish.md +95 -28
  4. package/README.ja.md +2 -2
  5. package/README.ko.md +2 -2
  6. package/README.md +2 -2
  7. package/README.ru.md +2 -2
  8. package/README.zh-cn.md +2 -2
  9. package/THIRD-PARTY-NOTICES.md +7 -7
  10. package/dist/agents/atlas/agent.d.ts +4 -2
  11. package/dist/agents/explore.d.ts +4 -2
  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/index.d.ts +2 -0
  20. package/dist/agents/sisyphus-agent-factory.d.ts +5 -2
  21. package/dist/agents/sisyphus-junior/agent.d.ts +4 -1
  22. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +1 -1
  23. package/dist/agents/types.d.ts +2 -2
  24. package/dist/cli/config-migrate.d.ts +8 -0
  25. package/dist/cli/doctor/checks/legacy-config-leftovers.d.ts +10 -0
  26. package/dist/cli/doctor/checks/model-resolution-config.d.ts +1 -1
  27. package/dist/cli/doctor/checks/tools-lsp.d.ts +1 -1
  28. package/dist/cli/doctor/framework/constants.d.ts +1 -1
  29. package/dist/cli/index.js +95391 -88524
  30. package/dist/cli-node/index.js +95504 -88637
  31. package/dist/config/schema/agent-names.d.ts +26 -26
  32. package/dist/config/schema/agent-overrides.d.ts +400 -400
  33. package/dist/config/schema/browser-automation.d.ts +2 -2
  34. package/dist/config/schema/categories.d.ts +36 -36
  35. package/dist/config/schema/commands.d.ts +2 -2
  36. package/dist/config/schema/dynamic-context-pruning.d.ts +1 -1
  37. package/dist/config/schema/experimental.d.ts +1 -1
  38. package/dist/config/schema/fallback-models.d.ts +25 -25
  39. package/dist/config/schema/hooks.d.ts +43 -43
  40. package/dist/config/schema/internal/permission.d.ts +9 -9
  41. package/dist/config/schema/keyword-detector.d.ts +6 -6
  42. package/dist/config/schema/oh-my-opencode-config.d.ts +402 -402
  43. package/dist/config/schema/tmux.d.ts +6 -6
  44. package/dist/config/validate.d.ts +2 -1
  45. package/dist/config-migration/deep-diff.d.ts +1 -0
  46. package/dist/config-migration/discovery-paths.d.ts +11 -0
  47. package/dist/config-migration/discovery-roots.d.ts +7 -0
  48. package/dist/config-migration/discovery.d.ts +4 -0
  49. package/dist/config-migration/index.d.ts +9 -0
  50. package/dist/config-migration/legacy-history.d.ts +3 -0
  51. package/dist/config-migration/migration-executor.d.ts +4 -0
  52. package/dist/config-migration/migration-plans.d.ts +14 -0
  53. package/dist/config-migration/record-values.d.ts +4 -0
  54. package/dist/config-migration/schema-url.d.ts +1 -0
  55. package/dist/config-migration/transform-config-jsonc.d.ts +2 -0
  56. package/dist/config-migration/transform-opencode.d.ts +2 -0
  57. package/dist/config-migration/transform-types.d.ts +24 -0
  58. package/dist/config-migration/types.d.ts +39 -0
  59. package/dist/create-hooks.d.ts +35 -35
  60. package/dist/features/background-agent/spawner/tmux-callback-invoker.d.ts +11 -0
  61. package/dist/features/builtin-commands/templates/hyperplan.d.ts +1 -1
  62. package/dist/features/builtin-commands/templates/start-work.d.ts +1 -1
  63. package/dist/features/claude-tasks/types.d.ts +4 -4
  64. package/dist/features/team-mode/team-runtime/shutdown-helpers.d.ts +1 -1
  65. package/dist/features/team-mode/team-runtime/shutdown-test-fixtures.d.ts +4 -4
  66. package/dist/features/team-mode/tools/lifecycle-test-fixture.d.ts +42 -42
  67. package/dist/features/tmux-subagent/environment-eligibility.d.ts +2 -0
  68. package/dist/features/tmux-subagent/index.d.ts +1 -0
  69. package/dist/features/tmux-subagent/tracked-session-state.d.ts +1 -0
  70. package/dist/features/tui-sidebar/snapshot-schema.d.ts +6 -6
  71. package/dist/help/schema/acp.d.ts +3 -3
  72. package/dist/help/schema/doctor.d.ts +4 -4
  73. package/dist/help/schema/status.d.ts +3 -3
  74. package/dist/hooks/auto-update-checker/constants.d.ts +3 -3
  75. package/dist/hooks/goal/types.d.ts +5 -5
  76. package/dist/hooks/non-interactive-env/constants.d.ts +4 -1
  77. package/dist/hooks/start-work/parse-user-request.d.ts +2 -0
  78. package/dist/hooks/start-work/worktree-block.d.ts +5 -0
  79. package/dist/index.js +35450 -28257
  80. package/dist/mcp/types.d.ts +3 -3
  81. package/dist/oh-my-opencode.schema.json +1 -1
  82. package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
  83. package/dist/plugin/command-execute-before.d.ts +3 -3
  84. package/dist/plugin/hooks/create-core-hooks.d.ts +25 -25
  85. package/dist/plugin-config/omo-config-chain.d.ts +14 -0
  86. package/dist/plugin-config/unknown-key-diagnostics.d.ts +5 -0
  87. package/dist/plugin-config.d.ts +2 -2
  88. package/dist/shared/agent-display-names.d.ts +1 -1
  89. package/dist/shared/jsonc-parser.d.ts +1 -1
  90. package/dist/shared/migration.d.ts +5 -1
  91. package/dist/shared/opencode-config-dir-types.d.ts +0 -1
  92. package/dist/shared/plugin-identity.d.ts +6 -8
  93. package/dist/shared/project-discovery-dirs.d.ts +0 -1
  94. package/dist/shared/tmux/tmux-utils/environment.d.ts +1 -1
  95. package/dist/shared/tmux/tmux-utils.d.ts +1 -1
  96. package/dist/shared/typescript-native-source-parser.d.ts +7 -0
  97. package/dist/skills/coding-agent-sessions/SKILL.md +5 -2
  98. package/dist/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  99. package/dist/skills/coding-agent-sessions/references/senpi.md +15 -5
  100. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  101. package/dist/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  102. package/dist/skills/debugging/SKILL.md +2 -1
  103. package/dist/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  104. package/dist/skills/frontend/ATTRIBUTION.md +7 -0
  105. package/dist/skills/frontend/SKILL.md +4 -1
  106. package/dist/skills/frontend/references/design/README.md +8 -0
  107. package/dist/skills/frontend/references/design/_INDEX.md +14 -1
  108. package/dist/skills/frontend/references/design/interaction-skill.md +144 -0
  109. package/dist/skills/programming/SKILL.md +11 -1
  110. package/dist/skills/programming/references/logging.md +6 -1
  111. package/dist/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  112. package/dist/skills/start-work/SKILL.md +12 -2
  113. package/dist/skills/ulw-plan/SKILL.md +1 -1
  114. package/dist/skills/ulw-plan/references/full-workflow.md +12 -1
  115. package/dist/skills/ulw-plan/references/intent-clear.md +1 -1
  116. package/dist/startup-migration.d.ts +28 -0
  117. package/dist/testing/create-plugin-module.d.ts +4 -0
  118. package/dist/tools/task/types.d.ts +10 -10
  119. package/dist/tui.js +31812 -26849
  120. package/package.json +14 -14
  121. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +21 -5
  122. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +11 -2
  123. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +2 -2
  124. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  125. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +8 -4
  126. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  127. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  128. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +11 -5
  129. package/packages/omo-codex/plugin/components/codegraph/NOTICE +1 -1
  130. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +10272 -2600
  131. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +7341 -562
  132. package/packages/omo-codex/plugin/components/codegraph/package.json +2 -2
  133. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +33 -0
  134. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +36 -10
  135. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +170 -186
  136. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +34 -0
  137. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +22 -5
  138. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +106 -0
  139. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +145 -0
  140. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +21 -0
  141. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +139 -0
  142. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +15 -0
  143. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +32 -0
  144. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +109 -0
  145. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +148 -0
  146. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +126 -186
  147. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +9 -4
  148. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +160 -0
  149. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +12 -110
  150. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +29 -20
  151. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +3 -3
  152. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +2 -2
  153. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +11 -5
  154. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +3 -3
  155. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +2 -1
  156. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +50 -5
  157. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +3 -2
  158. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +24 -13
  159. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +70 -13
  160. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +58 -0
  161. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +104 -0
  162. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +4 -2
  163. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +116 -0
  164. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +114 -119
  165. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  166. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  167. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  168. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  169. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  170. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  171. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  172. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  173. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  174. package/packages/omo-codex/plugin/components/rules/dist/cli.js +31 -14
  175. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  176. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  177. package/packages/omo-codex/plugin/components/start-work-continuation/directive.md +1 -1
  178. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  179. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  180. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  181. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  182. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  183. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  184. package/packages/omo-codex/plugin/components/ultrawork/directive.md +12 -7
  185. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  186. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  187. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +12 -7
  188. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +1 -1
  189. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +12 -1
  190. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +1 -1
  191. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +12 -7
  192. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  193. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  194. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +19 -1
  195. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  196. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  197. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  198. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  199. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  200. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  201. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  202. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  203. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  204. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  205. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  206. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  207. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  208. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  209. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  210. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  211. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  212. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  213. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  214. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  215. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  216. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  217. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  218. package/packages/omo-codex/plugin/package-lock.json +42 -41
  219. package/packages/omo-codex/plugin/package.json +1 -1
  220. package/packages/omo-codex/plugin/shared/src/config-loader.ts +165 -16
  221. package/packages/omo-codex/plugin/shared/src/config-migration.ts +162 -0
  222. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +196 -18
  223. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +5 -2
  224. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  225. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +15 -5
  226. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  227. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  228. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -1
  229. package/packages/omo-codex/plugin/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  230. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +7 -0
  231. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +4 -1
  232. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +8 -0
  233. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +14 -1
  234. package/packages/omo-codex/plugin/skills/frontend/references/design/interaction-skill.md +144 -0
  235. package/packages/omo-codex/plugin/skills/programming/SKILL.md +11 -1
  236. package/packages/omo-codex/plugin/skills/programming/references/logging.md +6 -1
  237. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  238. package/packages/omo-codex/plugin/skills/start-work/SKILL.md +12 -2
  239. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +12 -7
  240. package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +19 -1
  241. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +1 -1
  242. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +12 -1
  243. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +1 -1
  244. package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +22 -0
  245. package/packages/omo-codex/scripts/install-dist/install-local.mjs +1 -1
  246. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +5 -2
  247. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +3 -1
  248. package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +15 -5
  249. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +46 -0
  250. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/scanners.py +19 -10
  251. package/packages/shared-skills/skills/debugging/SKILL.md +2 -1
  252. package/packages/shared-skills/skills/debugging/references/methodology/03-flaky-triage.md +47 -0
  253. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +7 -0
  254. package/packages/shared-skills/skills/frontend/SKILL.md +4 -1
  255. package/packages/shared-skills/skills/frontend/references/design/README.md +8 -0
  256. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +14 -1
  257. package/packages/shared-skills/skills/frontend/references/design/interaction-skill.md +144 -0
  258. package/packages/shared-skills/skills/programming/SKILL.md +11 -1
  259. package/packages/shared-skills/skills/programming/references/logging.md +6 -1
  260. package/packages/shared-skills/skills/programming/scripts/typescript/check-no-excuse-rules.ts +51 -17
  261. package/packages/shared-skills/skills/start-work/SKILL.md +12 -2
  262. package/packages/shared-skills/skills/ulw-plan/SKILL.md +1 -1
  263. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +12 -1
  264. package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +1 -1
  265. package/dist/plugin-config/layered-config-loader.d.ts +0 -2
  266. package/dist/plugin-config/single-config-loader.d.ts +0 -4
  267. package/dist/shared/migrate-legacy-config-file.d.ts +0 -1
  268. package/dist/shared/migration/config-migration.d.ts +0 -1
@@ -0,0 +1,160 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { mkdirSync, mkdtempSync, 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 {
9
+ executeCodegraphSessionStartHook,
10
+ type CodegraphSessionStartOutcome,
11
+ type WorkerSpawnInvocation,
12
+ } from "../src/hook.ts";
13
+ import { recordSessionStartFailure } from "../src/session-start-cooldown.ts";
14
+
15
+ const pluginRoot = resolve(fileURLToPath(new URL("../../..", import.meta.url)));
16
+
17
+ function createAllowedWorkspace(prefix: string): string {
18
+ return mkdtempSync(join(pluginRoot, `.tmp-${prefix}-`));
19
+ }
20
+
21
+ describe("CodeGraph SessionStart spawn guards", () => {
22
+ it("#given an inconclusive probe timeout #when SessionStart runs #then timeout is not treated as uninitialized", async () => {
23
+ // given
24
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-timeout-home-"));
25
+ const workspace = createAllowedWorkspace("codegraph-timeout-workspace");
26
+ const spawned: WorkerSpawnInvocation[] = [];
27
+ try {
28
+ // when
29
+ const result = await executeCodegraphSessionStartHook({
30
+ ancestorProbe: () => ({ kind: "inconclusive", reason: "status timed out" }),
31
+ config: { codegraph: { enabled: true }, sources: [], warnings: [] },
32
+ cwd: workspace,
33
+ env: { HOME: homeDir },
34
+ spawnWorker: (invocation) => spawned.push(invocation),
35
+ stdin: Readable.from(["{}"]),
36
+ sweepZombies: () => undefined,
37
+ });
38
+
39
+ // then
40
+ expect(result).toEqual({ action: "skipped-inconclusive", exitCode: 0 });
41
+ expect(spawned).toEqual([]);
42
+ } finally {
43
+ rmSync(homeDir, { recursive: true, force: true });
44
+ rmSync(workspace, { recursive: true, force: true });
45
+ }
46
+ });
47
+
48
+ it("#given one hook already owns the project lock #when a second SessionStart runs #then it records skipped-locked without spawning", async () => {
49
+ // given
50
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-dedup-home-"));
51
+ const workspace = createAllowedWorkspace("codegraph-dedup-workspace");
52
+ const outcomes: CodegraphSessionStartOutcome[] = [];
53
+ const spawned: WorkerSpawnInvocation[] = [];
54
+ const options = {
55
+ ancestorProbe: () => ({ kind: "uninitialized" } as const),
56
+ config: { codegraph: { enabled: true }, sources: [], warnings: [] },
57
+ cwd: workspace,
58
+ env: { HOME: homeDir },
59
+ logOutcome: (outcome: CodegraphSessionStartOutcome) => outcomes.push(outcome),
60
+ spawnWorker: (invocation: WorkerSpawnInvocation) => {
61
+ spawned.push(invocation);
62
+ },
63
+ stdin: Readable.from(["{}"]),
64
+ sweepZombies: () => undefined,
65
+ };
66
+ try {
67
+ await executeCodegraphSessionStartHook(options);
68
+
69
+ // when
70
+ const second = await executeCodegraphSessionStartHook({ ...options, stdin: Readable.from(["{}"]) });
71
+
72
+ // then
73
+ expect(second).toEqual({ action: "skipped-locked", exitCode: 0 });
74
+ expect(spawned).toHaveLength(1);
75
+ expect(outcomes).toContainEqual({ action: "skipped-locked", projectRoot: workspace });
76
+ } finally {
77
+ rmSync(homeDir, { recursive: true, force: true });
78
+ rmSync(workspace, { recursive: true, force: true });
79
+ }
80
+ });
81
+
82
+ it("#given a failed worker cooldown #when SessionStart retries before and after expiry #then only the expired retry spawns", async () => {
83
+ // given
84
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-cooldown-hook-home-"));
85
+ const workspace = createAllowedWorkspace("codegraph-cooldown-hook-workspace");
86
+ const outcomes: CodegraphSessionStartOutcome[] = [];
87
+ const spawned: WorkerSpawnInvocation[] = [];
88
+ try {
89
+ recordSessionStartFailure({
90
+ action: "failed",
91
+ baseCooldownMs: 60_000,
92
+ homeDir,
93
+ nowMs: 1_000,
94
+ projectRoot: workspace,
95
+ });
96
+ const baseOptions = {
97
+ ancestorProbe: () => ({ kind: "uninitialized" } as const),
98
+ config: { codegraph: { enabled: true, session_start_cooldown_ms: 60_000 }, sources: [], warnings: [] },
99
+ cwd: workspace,
100
+ env: { HOME: homeDir },
101
+ logOutcome: (outcome: CodegraphSessionStartOutcome) => outcomes.push(outcome),
102
+ spawnWorker: (invocation: WorkerSpawnInvocation) => {
103
+ spawned.push(invocation);
104
+ },
105
+ sweepZombies: () => undefined,
106
+ };
107
+
108
+ // when
109
+ const suppressed = await executeCodegraphSessionStartHook({ ...baseOptions, nowMs: 60_999, stdin: Readable.from(["{}"]) });
110
+ const expired = await executeCodegraphSessionStartHook({ ...baseOptions, nowMs: 61_000, stdin: Readable.from(["{}"]) });
111
+
112
+ // then
113
+ expect(suppressed).toEqual({ action: "skipped-cooldown", exitCode: 0 });
114
+ expect(expired).toEqual({ action: "spawned", exitCode: 0 });
115
+ expect(spawned).toHaveLength(1);
116
+ expect(outcomes).toContainEqual({
117
+ action: "skipped-cooldown",
118
+ cooldownUntil: 61_000,
119
+ failureCount: 1,
120
+ projectRoot: workspace,
121
+ });
122
+ } finally {
123
+ rmSync(homeDir, { recursive: true, force: true });
124
+ rmSync(workspace, { recursive: true, force: true });
125
+ }
126
+ });
127
+
128
+ it("#given an ancestor has a CodeGraph database #when SessionStart runs in a nested project #then it records skipped-nested-root", async () => {
129
+ // given
130
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-nested-home-"));
131
+ const ancestorRoot = createAllowedWorkspace("codegraph-nested-ancestor");
132
+ const workspace = join(ancestorRoot, "apps", "server");
133
+ const outcomes: CodegraphSessionStartOutcome[] = [];
134
+ const spawned: WorkerSpawnInvocation[] = [];
135
+ try {
136
+ mkdirSync(join(ancestorRoot, ".codegraph"), { recursive: true });
137
+ mkdirSync(workspace, { recursive: true });
138
+ writeFileSync(join(ancestorRoot, ".codegraph", "codegraph.db"), "fixture");
139
+
140
+ // when
141
+ const result = await executeCodegraphSessionStartHook({
142
+ config: { codegraph: { enabled: true }, sources: [], warnings: [] },
143
+ cwd: workspace,
144
+ env: { HOME: homeDir },
145
+ logOutcome: (outcome) => outcomes.push(outcome),
146
+ spawnWorker: (invocation) => spawned.push(invocation),
147
+ stdin: Readable.from(["{}"]),
148
+ sweepZombies: () => undefined,
149
+ });
150
+
151
+ // then
152
+ expect(result).toEqual({ action: "skipped-nested-root", exitCode: 0 });
153
+ expect(spawned).toEqual([]);
154
+ expect(outcomes).toContainEqual({ action: "skipped-nested-root", ancestorRoot, projectRoot: workspace });
155
+ } finally {
156
+ rmSync(homeDir, { recursive: true, force: true });
157
+ rmSync(ancestorRoot, { recursive: true, force: true });
158
+ }
159
+ });
160
+ });
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join, resolve } from "node:path";
5
5
  import { Readable } from "node:stream";
@@ -9,94 +9,33 @@ import { executeCodegraphSessionStartHook, type WorkerSpawnInvocation } from "..
9
9
 
10
10
  const pluginRoot = resolve(fileURLToPath(new URL("../../..", import.meta.url)));
11
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
12
  function createAllowedWorkspace(prefix: string): string {
42
13
  return mkdtempSync(join(pluginRoot, `.tmp-${prefix}-`));
43
14
  }
44
15
 
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: { readonly posix: string; readonly win32: string }): { readonly binPath: string; readonly dir: string } {
48
- const dir = mkdtempSync(join(tmpdir(), "omo-codegraph-fake-bin-"));
49
- if (process.platform === "win32") {
50
- const binPath = join(dir, "codegraph.cmd");
51
- writeFileSync(binPath, scripts.win32);
52
- return { binPath, dir };
53
- }
54
- const binPath = join(dir, "codegraph");
55
- writeFileSync(binPath, scripts.posix, { mode: 0o755 });
56
- chmodSync(binPath, 0o755);
57
- return { binPath, dir };
58
- }
59
-
60
- // Keep the probe hermetic on POSIX but viable on win32: resolveCodegraphCommandInvocation wraps
61
- // the fake .cmd in `cmd.exe /d /s /c`, and Windows can only resolve cmd.exe when the child env
62
- // carries the real system PATH (System32) plus SystemRoot (both whitelisted in SAFE_AMBIENT_ENV_KEYS).
63
- // A POSIX-only PATH makes the probe spawn fail, so the hook reports not-initialized and spawns.
64
- function probeEnv(homeDir: string, binPath: string): Record<string, string> {
65
- if (process.platform === "win32") {
66
- const env: Record<string, string> = {
67
- HOME: homeDir,
68
- OMO_CODEGRAPH_BIN: binPath,
69
- };
70
- if (process.env["PATH"] !== undefined) env["PATH"] = process.env["PATH"];
71
- if (process.env["SystemRoot"] !== undefined) env["SystemRoot"] = process.env["SystemRoot"];
72
- return env;
73
- }
74
- return { HOME: homeDir, OMO_CODEGRAPH_BIN: binPath, PATH: "/usr/bin:/bin" };
75
- }
76
-
77
- describe("CodeGraph SessionStart hook with a 1.0.1-era project store under the 1.4.1 binary", () => {
78
- 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 () => {
16
+ describe("CodeGraph SessionStart hook with a migrated 1.0.1 project store under CodeGraph 1.5.0", () => {
17
+ it("#given the migrated store has an exact database #when SessionStart runs #then it never invokes the CodeGraph CLI", async () => {
79
18
  // given
80
19
  const stdout: string[] = [];
81
20
  const spawned: WorkerSpawnInvocation[] = [];
82
21
  const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-upgrade-home-"));
83
- // The payload is a single JSON line with no cmd metacharacters (% ^ & < > |), so a plain echo is safe.
84
- const fake = createFakeCodegraphBin({
85
- posix: `#!/bin/sh\nprintf '%s\\n' '${MIGRATED_1_0_1_STORE_STATUS_JSON}'\n`,
86
- win32: `@echo off\r\n@echo ${MIGRATED_1_0_1_STORE_STATUS_JSON}\r\n`,
87
- });
88
22
  const workspace = createAllowedWorkspace("codegraph-upgrade-workspace");
89
- mkdirSync(join(workspace, ".codegraph"), { recursive: true });
90
-
91
23
  try {
24
+ mkdirSync(join(workspace, ".codegraph"), { recursive: true });
25
+ writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "migrated-store");
26
+
92
27
  // when
93
28
  const result = await executeCodegraphSessionStartHook({
29
+ ancestorProbe: () => {
30
+ throw new Error("the exact database check must be the complete fast path");
31
+ },
94
32
  config: { codegraph: { enabled: true }, sources: [], warnings: [] },
95
33
  cwd: workspace,
96
- env: probeEnv(homeDir, fake.binPath),
34
+ env: { HOME: homeDir },
97
35
  stdin: Readable.from(["{}"]),
98
36
  stdout: { write: (chunk) => stdout.push(chunk) },
99
37
  spawnWorker: (invocation) => spawned.push(invocation),
38
+ sweepZombies: () => undefined,
100
39
  });
101
40
 
102
41
  // then
@@ -105,44 +44,7 @@ describe("CodeGraph SessionStart hook with a 1.0.1-era project store under the 1
105
44
  expect(stdout.join("")).toBe("");
106
45
  } finally {
107
46
  rmSync(homeDir, { recursive: true, force: true });
108
- rmSync(fake.dir, { recursive: true, force: true });
109
- rmSync(workspace, { recursive: true, force: true, maxRetries: 10, retryDelay: 500 });
110
- }
111
- });
112
-
113
- it("#given the status probe hangs past its 2s timeout #when SessionStart fires #then it exits zero promptly and spawns at most one bounded worker", async () => {
114
- // given
115
- const stdout: string[] = [];
116
- const spawned: WorkerSpawnInvocation[] = [];
117
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-slow-home-"));
118
- const fake = createFakeCodegraphBin({
119
- posix: "#!/bin/sh\nsleep 30\n",
120
- win32: "@echo off\r\nset /p _probe_hang=\r\n",
121
- });
122
- const workspace = createAllowedWorkspace("codegraph-slow-probe-workspace");
123
-
124
- try {
125
- // when
126
- const startedAt = Date.now();
127
- const result = await executeCodegraphSessionStartHook({
128
- config: { codegraph: { enabled: true }, sources: [], warnings: [] },
129
- cwd: workspace,
130
- env: probeEnv(homeDir, fake.binPath),
131
- stdin: Readable.from(["{}"]),
132
- stdout: { write: (chunk) => stdout.push(chunk) },
133
- spawnWorker: (invocation) => spawned.push(invocation),
134
- });
135
- const elapsedMs = Date.now() - startedAt;
136
-
137
- // then
138
- expect(result.exitCode).toBe(0);
139
- expect(result.action).toBe("spawned");
140
- expect(spawned).toHaveLength(1);
141
- expect(elapsedMs).toBeLessThan(15_000);
142
- } finally {
143
- rmSync(homeDir, { recursive: true, force: true });
144
- rmSync(fake.dir, { recursive: true, force: true });
145
- rmSync(workspace, { recursive: true, force: true, maxRetries: 10, retryDelay: 500 });
47
+ rmSync(workspace, { recursive: true, force: true });
146
48
  }
147
49
  });
148
50
  });
@@ -39,8 +39,9 @@ describe("CodeGraph SessionStart hook", () => {
39
39
  env: { HOME: homeDir },
40
40
  stdin: Readable.from(["{}"]),
41
41
  stdout: { write: (chunk) => stdout.push(chunk) },
42
+ ancestorProbe: () => ({ kind: "uninitialized" }),
42
43
  spawnWorker: (invocation) => spawned.push(invocation),
43
- statusProbe: () => Promise.resolve(false),
44
+ sweepZombies: () => undefined,
44
45
  });
45
46
 
46
47
  // then
@@ -132,7 +133,7 @@ describe("CodeGraph SessionStart hook", () => {
132
133
  try {
133
134
  mkdirSync(join(homeDir, ".omo"), { recursive: true });
134
135
  writeFileSync(
135
- join(homeDir, ".omo", "config.jsonc"),
136
+ join(homeDir, ".omo", "omo.jsonc"),
136
137
  '{ "codegraph": { "enabled": true }, "[codex]": { "codegraph": { "enabled": false } } }\n',
137
138
  );
138
139
 
@@ -164,8 +165,8 @@ describe("CodeGraph SessionStart hook", () => {
164
165
  try {
165
166
  mkdirSync(join(homeDir, ".omo"), { recursive: true });
166
167
  mkdirSync(join(workspace, ".omo"), { recursive: true });
167
- writeFileSync(join(homeDir, ".omo", "config.jsonc"), '{ "codegraph": { "enabled": true } }\n');
168
- writeFileSync(join(workspace, ".omo", "config.jsonc"), '{ "[codex]": { "codegraph": { "enabled": false } } }\n');
168
+ writeFileSync(join(homeDir, ".omo", "omo.jsonc"), '{ "codegraph": { "enabled": true } }\n');
169
+ writeFileSync(join(workspace, ".omo", "omo.jsonc"), '{ "[codex]": { "codegraph": { "enabled": false } } }\n');
169
170
 
170
171
  // when
171
172
  const result = await executeCodegraphSessionStartHook({
@@ -193,7 +194,7 @@ describe("CodeGraph SessionStart hook", () => {
193
194
  const spawned: WorkerSpawnInvocation[] = [];
194
195
  try {
195
196
  mkdirSync(join(homeDir, ".omo"), { recursive: true });
196
- writeFileSync(join(homeDir, ".omo", "config.jsonc"), '{ "codegraph": { "enabled": true } }\n');
197
+ writeFileSync(join(homeDir, ".omo", "omo.jsonc"), '{ "codegraph": { "enabled": true } }\n');
197
198
 
198
199
  // when
199
200
  const result = await executeCodegraphSessionStartHook({
@@ -216,32 +217,32 @@ describe("CodeGraph SessionStart hook", () => {
216
217
  const stdout: string[] = [];
217
218
  const spawned: WorkerSpawnInvocation[] = [];
218
219
  const workspace = createAllowedWorkspace("codegraph-workspace");
220
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-spawn-home-"));
219
221
 
220
222
  try {
221
223
  // when
222
224
  const result = await executeCodegraphSessionStartHook({
225
+ ancestorProbe: () => ({ kind: "uninitialized" }),
223
226
  config: { codegraph: { enabled: true }, sources: [], warnings: [] },
224
227
  cwd: workspace,
225
- env: { HOME: "/tmp/home", KEEP: "1", OPENAI_API_KEY: "sk-test-secret" },
228
+ env: { HOME: homeDir, KEEP: "1", OPENAI_API_KEY: "sk-test-secret" },
226
229
  stdin: Readable.from(["{}"]),
227
230
  stdout: { write: (chunk) => stdout.push(chunk) },
228
- spawnWorker: (invocation) => spawned.push(invocation),
229
- statusProbe: () => Promise.resolve(false),
231
+ spawnWorker: (invocation) => {
232
+ spawned.push(invocation);
233
+ },
234
+ sweepZombies: () => undefined,
230
235
  workerCliPath: "/plugin/components/codegraph/dist/cli.js",
231
236
  });
232
237
 
233
238
  // then
234
239
  expect(result).toEqual({ action: "spawned", exitCode: 0 });
235
- expect(spawned).toEqual([
236
- {
237
- args: ["/plugin/components/codegraph/dist/cli.js", "hook", "session-start-worker"],
238
- command: process.execPath,
239
- env: {
240
- HOME: "/tmp/home",
241
- OMO_CODEGRAPH_SESSION_START_CWD: workspace,
242
- },
243
- },
244
- ]);
240
+ expect(spawned).toHaveLength(1);
241
+ expect(spawned[0]?.args).toEqual(["/plugin/components/codegraph/dist/cli.js", "hook", "session-start-worker"]);
242
+ expect(spawned[0]?.command).toBe(process.execPath);
243
+ expect(spawned[0]?.env["HOME"]).toBe(homeDir);
244
+ expect(spawned[0]?.env["OMO_CODEGRAPH_SESSION_START_CWD"]).toBe(workspace);
245
+ expect(spawned[0]?.env["OMO_CODEGRAPH_SESSION_START_LOCK_TOKEN"]).toMatch(/^[0-9a-f-]{36}$/);
245
246
  expect(spawned[0]?.env["OPENAI_API_KEY"]).toBeUndefined();
246
247
  expect(spawned[0]?.env["KEEP"]).toBeUndefined();
247
248
  expect(JSON.parse(stdout.join(""))).toEqual({
@@ -251,6 +252,7 @@ describe("CodeGraph SessionStart hook", () => {
251
252
  },
252
253
  });
253
254
  } finally {
255
+ rmSync(homeDir, { recursive: true, force: true });
254
256
  rmSync(workspace, { recursive: true, force: true });
255
257
  }
256
258
  });
@@ -260,17 +262,23 @@ describe("CodeGraph SessionStart hook", () => {
260
262
  const stdout: string[] = [];
261
263
  const spawned: WorkerSpawnInvocation[] = [];
262
264
  const workspace = createAllowedWorkspace("codegraph-initialized-workspace");
265
+ const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-initialized-home-"));
263
266
 
264
267
  try {
268
+ mkdirSync(join(workspace, ".codegraph"), { recursive: true });
269
+ writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
270
+
265
271
  // when
266
272
  const result = await executeCodegraphSessionStartHook({
273
+ ancestorProbe: () => {
274
+ throw new Error("an initialized exact root must not invoke any fallback probe");
275
+ },
267
276
  config: { codegraph: { enabled: true }, sources: [], warnings: [] },
268
277
  cwd: workspace,
269
- env: { HOME: "/tmp/home", KEEP: "1" },
278
+ env: { HOME: homeDir, KEEP: "1" },
270
279
  stdin: Readable.from(["{}"]),
271
280
  stdout: { write: (chunk) => stdout.push(chunk) },
272
281
  spawnWorker: (invocation) => spawned.push(invocation),
273
- statusProbe: () => Promise.resolve(true),
274
282
  });
275
283
 
276
284
  // then
@@ -278,6 +286,7 @@ describe("CodeGraph SessionStart hook", () => {
278
286
  expect(spawned).toEqual([]);
279
287
  expect(stdout.join("")).toBe("");
280
288
  } finally {
289
+ rmSync(homeDir, { recursive: true, force: true });
281
290
  rmSync(workspace, { recursive: true, force: true });
282
291
  }
283
292
  });
@@ -1,6 +1,6 @@
1
1
  import { chmodSync, writeFileSync } from "node:fs";
2
2
 
3
- export const CODEGRAPH_141_DEFAULT_TOOLS: readonly Record<string, unknown>[] = [
3
+ export const CODEGRAPH_150_DEFAULT_TOOLS: readonly Record<string, unknown>[] = [
4
4
  {
5
5
  name: "codegraph_explore",
6
6
  description:
@@ -41,10 +41,10 @@ export function writeFakeNewlineCodegraph(filePath: string): void {
41
41
  "rl.on('line', (line) => {",
42
42
  " const request = JSON.parse(line);",
43
43
  " if (request.method === 'initialize') {",
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');",
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.5.0' } } }) + '\\n');",
45
45
  " }",
46
46
  " if (request.method === 'tools/list') {",
47
- ` process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { tools: ${JSON.stringify(CODEGRAPH_141_DEFAULT_TOOLS)} } }) + '\\n');`,
47
+ ` process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { tools: ${JSON.stringify(CODEGRAPH_150_DEFAULT_TOOLS)} } }) + '\\n');`,
48
48
  " }",
49
49
  "});",
50
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.4.1");
46
+ expect(optionalDependencies["@colbymchenry/codegraph"]).toBe("1.5.0");
47
47
  expect(files).toContain("LICENSE");
48
48
  expect(files).toContain("NODE-RUNTIME-LICENSES.md");
49
49
  expect(files).toContain("NOTICE");
@@ -58,7 +58,7 @@ describe("CodeGraph component runtime package metadata", () => {
58
58
  // given
59
59
  const notice = readFileSync(resolve(componentRoot, "NOTICE"), "utf8");
60
60
 
61
- expect(notice).toContain("@colbymchenry/codegraph@1.0.1");
61
+ expect(notice).toContain("@colbymchenry/codegraph@1.5.0");
62
62
  expect(notice).toContain("MIT license");
63
63
  expect(notice).toContain("Node.js v24.16.0 runtime");
64
64
  expect(notice).toContain("NODE-RUNTIME-LICENSES.md");
@@ -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({
@@ -71,19 +77,19 @@ describe("CodeGraph provisioned launcher Node guard", () => {
71
77
  source: provisioned === null ? "path" : "provisioned",
72
78
  };
73
79
  },
80
+ resolveManagedBin: () => binPath,
74
81
  runCommand: (_projectRoot, command, args) => {
75
82
  calls.push({ args, command });
76
- return Promise.resolve({ exitCode: 0, stdout: calls.length === 1 ? '{"initialized":false}' : "", timedOut: false });
83
+ mkdirSync(join(workspace, ".codegraph"), { recursive: true });
84
+ writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
85
+ return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
77
86
  },
78
87
  },
79
88
  });
80
89
 
81
90
  // then
82
91
  expect(result).toEqual({ action: "initialized" });
83
- expect(calls).toEqual([
84
- { args: ["status", "--json"], command: binPath },
85
- { args: ["init"], command: binPath },
86
- ]);
92
+ expect(calls).toEqual([{ args: ["init"], command: binPath }]);
87
93
  expect(outcomes).toEqual([{ action: "initialized", exitCode: 0, projectRoot: workspace, source: "provisioned", timedOut: false }]);
88
94
  } finally {
89
95
  rmSync(workspace, { recursive: true, force: true });
@@ -7,7 +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
+ CODEGRAPH_150_DEFAULT_TOOLS,
11
11
  findTool,
12
12
  frameMcpRequest,
13
13
  parseMcpBodies,
@@ -87,14 +87,14 @@ describe("runCodegraphServe MCP protocol bridge", () => {
87
87
  result: {
88
88
  capabilities: { tools: { listChanged: false } },
89
89
  protocolVersion: "2025-06-18",
90
- serverInfo: { name: "codegraph", version: "1.4.1" },
90
+ serverInfo: { name: "codegraph", version: "1.5.0" },
91
91
  },
92
92
  },
93
93
  {
94
94
  id: 2,
95
95
  jsonrpc: "2.0",
96
96
  result: {
97
- tools: CODEGRAPH_141_DEFAULT_TOOLS,
97
+ tools: CODEGRAPH_150_DEFAULT_TOOLS,
98
98
  },
99
99
  },
100
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.4.1" },
51
+ serverInfo: { name: "codegraph", version: "1.5.0" },
51
52
  },
52
53
  });
53
54
  });