oh-my-opencode 5.0.0-beta.33 → 5.0.0-beta.35

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 (221) hide show
  1. package/.agents/skills/codex-qa/scripts/lsp-e2e.sh +1 -3
  2. package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +1 -1
  3. package/.agents/skills/tech-debt-audit/SKILL.md +6 -76
  4. package/README.ja.md +1 -1
  5. package/README.ko.md +1 -1
  6. package/README.md +1 -1
  7. package/README.ru.md +1 -1
  8. package/README.zh-cn.md +1 -1
  9. package/THIRD-PARTY-NOTICES.md +27 -99
  10. package/dist/cli/index.js +48350 -48559
  11. package/dist/cli-node/index.js +48480 -48689
  12. package/dist/config/index.d.ts +1 -1
  13. package/dist/config/schema/hooks.d.ts +0 -1
  14. package/dist/config/schema/oh-my-opencode-config.d.ts +0 -10
  15. package/dist/config/schema.d.ts +0 -1
  16. package/dist/create-hooks.d.ts +0 -1
  17. package/dist/hooks/index.d.ts +0 -1
  18. package/dist/index.js +11675 -13742
  19. package/dist/mcp/index.d.ts +0 -4
  20. package/dist/mcp/types.d.ts +0 -1
  21. package/dist/oh-my-opencode.schema.json +1 -45
  22. package/dist/plugin/hooks/create-core-hooks.d.ts +0 -1
  23. package/dist/plugin/hooks/create-session-hooks.d.ts +1 -2
  24. package/dist/shared/omo-process-sweep.d.ts +2 -4
  25. package/dist/skills/init-deep/SKILL.md +13 -13
  26. package/dist/skills/ulw-plan/SKILL.md +0 -1
  27. package/dist/tui.js +44809 -44910
  28. package/package.json +16 -18
  29. package/packages/omo-codex/THIRD-PARTY-NOTICES.md +0 -17
  30. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -3
  31. package/packages/omo-codex/plugin/.mcp.json +0 -6
  32. package/packages/omo-codex/plugin/AGENTS.md +5 -5
  33. package/packages/omo-codex/plugin/README.md +1 -1
  34. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +1 -15
  35. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  36. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  37. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  38. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  39. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  40. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  41. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  42. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  43. package/packages/omo-codex/plugin/components/lcx/skills/lcx-doctor/SKILL.md +1 -1
  44. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  45. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  46. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  48. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  49. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  50. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  51. package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +1 -1
  52. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  53. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  54. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +2 -2
  55. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  56. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +0 -1
  58. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  59. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  60. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/ulw-loop/README.md +11 -1
  62. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +2 -2
  63. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +12 -0
  64. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +45 -0
  65. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +1 -0
  66. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +5 -0
  67. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +10 -3
  68. package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +35 -38
  69. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +278 -193
  70. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +5 -0
  71. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +7 -51
  72. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +39 -22
  73. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
  74. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +64 -8
  75. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -1
  76. package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +37 -18
  77. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  78. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  79. package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -1
  80. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +81 -0
  81. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +6 -0
  82. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +10 -3
  83. package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +32 -63
  84. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +7 -53
  85. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +50 -31
  86. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +67 -14
  87. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
  88. package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +36 -17
  89. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +26 -0
  90. package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +47 -2
  91. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
  92. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
  93. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
  94. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -0
  95. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  96. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  97. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  98. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  99. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  100. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  101. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  102. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  103. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  104. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  105. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  106. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  107. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  108. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  109. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  110. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  111. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  112. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  113. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  114. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  115. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  116. package/packages/omo-codex/plugin/package-lock.json +12 -146
  117. package/packages/omo-codex/plugin/package.json +1 -2
  118. package/packages/omo-codex/plugin/scripts/AGENTS.md +0 -1
  119. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +0 -1
  120. package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
  121. package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
  122. package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
  123. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +2 -8
  124. package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
  125. package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
  126. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
  127. package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +13 -13
  128. package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
  129. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +2 -2
  130. package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -1
  131. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +0 -1
  132. package/packages/omo-codex/plugin/test/AGENTS.md +2 -2
  133. package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +2 -21
  134. package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -2
  135. package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
  136. package/packages/omo-codex/plugin/test/auto-update.test.mjs +0 -25
  137. package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
  138. package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
  139. package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +0 -50
  140. package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +0 -1
  141. package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
  142. package/packages/omo-codex/scripts/install-cache-copy.test.mjs +27 -1
  143. package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +0 -23
  144. package/packages/omo-codex/scripts/install-dist/install-local.mjs +238 -431
  145. package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +1 -25
  146. package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +0 -36
  147. package/packages/shared-skills/skills/init-deep/SKILL.md +13 -13
  148. package/packages/shared-skills/skills/ulw-plan/SKILL.md +0 -1
  149. package/dist/config/schema/codegraph.d.ts +0 -12
  150. package/dist/hooks/codegraph-bootstrap/command-runner.d.ts +0 -17
  151. package/dist/hooks/codegraph-bootstrap/hook.d.ts +0 -35
  152. package/dist/hooks/codegraph-bootstrap/index.d.ts +0 -1
  153. package/dist/hooks/codegraph-bootstrap/project-root.d.ts +0 -1
  154. package/dist/hooks/codegraph-bootstrap/status.d.ts +0 -11
  155. package/dist/mcp/codegraph.d.ts +0 -16
  156. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
  157. package/packages/omo-codex/plugin/components/codegraph/LICENSE +0 -21
  158. package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
  159. package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
  160. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12326
  161. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9908
  162. package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
  163. package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
  164. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
  165. package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
  166. package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
  167. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
  168. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
  169. package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -310
  170. package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -92
  171. package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
  172. package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
  173. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
  174. package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
  175. package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
  176. package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -22
  177. package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
  178. package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
  179. package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
  180. package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
  181. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
  182. package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
  183. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
  184. package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
  185. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
  186. package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
  187. package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
  188. package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
  189. package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
  190. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
  191. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
  192. package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
  193. package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
  194. package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
  195. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
  196. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
  197. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
  198. package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
  199. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
  200. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +0 -47
  201. package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
  202. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
  203. package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
  204. package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
  205. package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
  206. package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
  207. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
  208. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
  209. package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
  210. package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
  211. package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
  212. package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
  213. package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate.test.ts +0 -101
  214. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
  215. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
  216. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
  217. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
  218. package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
  219. package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
  220. package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
  221. package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
@@ -1,320 +0,0 @@
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 { runCodegraphCli } from "../src/cli.ts";
9
- import {
10
- executeCodegraphSessionStartHook,
11
- runCodegraphPostToolUseHook,
12
- type WorkerSpawnInvocation,
13
- } from "../src/hook.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
- function expectOmoCodegraphProjectStoreGuidance(context: string): void {
22
- expect(context).toContain(".omo");
23
- expect(context).toContain("codegraph");
24
- expect(context).toContain("projects");
25
- expect(context).toContain("project-");
26
- }
27
-
28
- describe("CodeGraph SessionStart hook", () => {
29
- it("#given hook session-start cli args #when invoked with empty JSON input #then it emits valid JSON and exits zero", async () => {
30
- // given
31
- const stdout: string[] = [];
32
- const spawned: WorkerSpawnInvocation[] = [];
33
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-hook-home-"));
34
- try {
35
- // when
36
- const exitCode = await runCodegraphCli({
37
- argv: ["node", "cli.js", "hook", "session-start"],
38
- cwd: createAllowedWorkspace("codegraph-hook-workspace"),
39
- env: { HOME: homeDir },
40
- stdin: Readable.from(["{}"]),
41
- stdout: { write: (chunk) => stdout.push(chunk) },
42
- ancestorProbe: () => ({ kind: "uninitialized" }),
43
- spawnWorker: (invocation) => spawned.push(invocation),
44
- sweepZombies: () => undefined,
45
- });
46
-
47
- // then
48
- expect(exitCode).toBe(0);
49
- expect(spawned).toHaveLength(1);
50
- const parsed = JSON.parse(stdout.join(""));
51
- expect(parsed).toEqual({
52
- hookSpecificOutput: {
53
- hookEventName: "SessionStart",
54
- additionalContext: "LazyCodex CodeGraph bootstrap scheduled in background",
55
- },
56
- });
57
- } finally {
58
- rmSync(homeDir, { recursive: true, force: true });
59
- }
60
- });
61
-
62
- it("#given CodeGraph MCP reports an uninitialized project #when PostToolUse fires #then it emits OMO global-store init guidance", async () => {
63
- // given
64
- const output = runCodegraphPostToolUseHook(
65
- {
66
- cwd: "/Users/me/project",
67
- tool_name: "codegraph.codegraph_status",
68
- tool_response: {
69
- error: [
70
- "Tool execution failed: CodeGraph not initialized in /Users/me/project.",
71
- "Run 'codegraph init' in that project first.",
72
- ].join(" "),
73
- },
74
- },
75
- { homeDir: "/Users/me" },
76
- );
77
-
78
- // when
79
- const parsed = JSON.parse(output);
80
-
81
- // then
82
- expect(parsed.hookSpecificOutput.hookEventName).toBe("PostToolUse");
83
- expect(parsed.hookSpecificOutput.additionalContext).toContain('CodeGraph is not initialized for "/Users/me/project"');
84
- expectOmoCodegraphProjectStoreGuidance(parsed.hookSpecificOutput.additionalContext);
85
- expect(parsed.hookSpecificOutput.additionalContext).toContain('run `codegraph init` from "/Users/me/project"');
86
- });
87
-
88
- it("#given real CodeGraph status output has no MCP path phrase #when PostToolUse fires #then it emits OMO global-store init guidance", async () => {
89
- // given
90
- const output = runCodegraphPostToolUseHook(
91
- {
92
- cwd: "/Users/me/project",
93
- tool_name: "mcp__codegraph__codegraph_status",
94
- tool_response: ['Project: /Users/me/project', "Not initialized", 'Run "codegraph init" to initialize'].join("\n"),
95
- },
96
- { homeDir: "/Users/me" },
97
- );
98
-
99
- // when
100
- const parsed = JSON.parse(output);
101
-
102
- // then
103
- expect(parsed.hookSpecificOutput.additionalContext).toContain('CodeGraph is not initialized for "/Users/me/project"');
104
- expectOmoCodegraphProjectStoreGuidance(parsed.hookSpecificOutput.additionalContext);
105
- });
106
-
107
- it("#given CodeGraph is disabled by Codex SOT config #when SessionStart fires #then it skips without spawning", async () => {
108
- // given
109
- const stdout: string[] = [];
110
- const spawned: WorkerSpawnInvocation[] = [];
111
-
112
- // when
113
- const result = await executeCodegraphSessionStartHook({
114
- config: { codegraph: { enabled: false }, sources: [], warnings: [] },
115
- env: {},
116
- stdin: Readable.from(["{}"]),
117
- stdout: { write: (chunk) => stdout.push(chunk) },
118
- sweepZombies: () => undefined,
119
- spawnWorker: (invocation) => spawned.push(invocation),
120
- });
121
-
122
- // then
123
- expect(result).toEqual({ action: "skipped-disabled", exitCode: 0 });
124
- expect(spawned).toEqual([]);
125
- expect(stdout.join("")).toBe("");
126
- });
127
-
128
- it("#given HOME OMO config disables Codex CodeGraph #when SessionStart fires #then it skips without spawning", async () => {
129
- // given
130
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-sot-home-"));
131
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-sot-workspace-"));
132
- const stdout: string[] = [];
133
- const spawned: WorkerSpawnInvocation[] = [];
134
- try {
135
- mkdirSync(join(homeDir, ".omo"), { recursive: true });
136
- writeFileSync(
137
- join(homeDir, ".omo", "omo.jsonc"),
138
- '{ "codegraph": { "enabled": true }, "[codex]": { "codegraph": { "enabled": false } } }\n',
139
- );
140
-
141
- // when
142
- const result = await executeCodegraphSessionStartHook({
143
- cwd: workspace,
144
- env: { HOME: homeDir },
145
- stdin: Readable.from(["{}"]),
146
- stdout: { write: (chunk) => stdout.push(chunk) },
147
- sweepZombies: () => undefined,
148
- spawnWorker: (invocation) => spawned.push(invocation),
149
- });
150
-
151
- // then
152
- expect(result).toEqual({ action: "skipped-disabled", exitCode: 0 });
153
- expect(spawned).toEqual([]);
154
- expect(stdout.join("")).toBe("");
155
- } finally {
156
- rmSync(homeDir, { recursive: true, force: true });
157
- rmSync(workspace, { recursive: true, force: true });
158
- }
159
- });
160
-
161
- it("#given project Codex SOT disables global CodeGraph enablement #when SessionStart fires #then project config wins", async () => {
162
- // given
163
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-project-sot-home-"));
164
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-project-sot-workspace-"));
165
- const stdout: string[] = [];
166
- const spawned: WorkerSpawnInvocation[] = [];
167
- try {
168
- mkdirSync(join(homeDir, ".omo"), { recursive: true });
169
- mkdirSync(join(workspace, ".omo"), { recursive: true });
170
- writeFileSync(join(homeDir, ".omo", "omo.jsonc"), '{ "codegraph": { "enabled": true } }\n');
171
- writeFileSync(join(workspace, ".omo", "omo.jsonc"), '{ "[codex]": { "codegraph": { "enabled": false } } }\n');
172
-
173
- // when
174
- const result = await executeCodegraphSessionStartHook({
175
- cwd: workspace,
176
- env: { HOME: homeDir },
177
- stdin: Readable.from(["{}"]),
178
- stdout: { write: (chunk) => stdout.push(chunk) },
179
- sweepZombies: () => undefined,
180
- spawnWorker: (invocation) => spawned.push(invocation),
181
- });
182
-
183
- // then
184
- expect(result).toEqual({ action: "skipped-disabled", exitCode: 0 });
185
- expect(spawned).toEqual([]);
186
- expect(stdout.join("")).toBe("");
187
- } finally {
188
- rmSync(homeDir, { recursive: true, force: true });
189
- rmSync(workspace, { recursive: true, force: true });
190
- }
191
- });
192
-
193
- it("#given env disables CodeGraph over SOT enablement #when SessionStart fires #then it skips without spawning", async () => {
194
- // given
195
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-env-home-"));
196
- const stdout: string[] = [];
197
- const spawned: WorkerSpawnInvocation[] = [];
198
- try {
199
- mkdirSync(join(homeDir, ".omo"), { recursive: true });
200
- writeFileSync(join(homeDir, ".omo", "omo.jsonc"), '{ "codegraph": { "enabled": true } }\n');
201
-
202
- // when
203
- const result = await executeCodegraphSessionStartHook({
204
- env: { CODEX_CODEGRAPH_ENABLED: "0", HOME: homeDir },
205
- stdin: Readable.from(["{}"]),
206
- stdout: { write: (chunk) => stdout.push(chunk) },
207
- sweepZombies: () => undefined,
208
- spawnWorker: (invocation) => spawned.push(invocation),
209
- });
210
-
211
- // then
212
- expect(result).toEqual({ action: "skipped-disabled", exitCode: 0 });
213
- expect(spawned).toEqual([]);
214
- } finally {
215
- rmSync(homeDir, { recursive: true, force: true });
216
- }
217
- });
218
-
219
- it("#given CodeGraph is enabled #when SessionStart fires #then it detaches a background worker immediately", async () => {
220
- // given
221
- const stdout: string[] = [];
222
- const spawned: WorkerSpawnInvocation[] = [];
223
- const workspace = createAllowedWorkspace("codegraph-workspace");
224
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-spawn-home-"));
225
-
226
- try {
227
- // when
228
- const result = await executeCodegraphSessionStartHook({
229
- ancestorProbe: () => ({ kind: "uninitialized" }),
230
- config: { codegraph: { enabled: true }, sources: [], warnings: [] },
231
- cwd: workspace,
232
- env: { HOME: homeDir, KEEP: "1", OPENAI_API_KEY: "sk-test-secret" },
233
- stdin: Readable.from(["{}"]),
234
- stdout: { write: (chunk) => stdout.push(chunk) },
235
- spawnWorker: (invocation) => {
236
- spawned.push(invocation);
237
- },
238
- sweepZombies: () => undefined,
239
- workerCliPath: "/plugin/components/codegraph/dist/cli.js",
240
- });
241
-
242
- // then
243
- expect(result).toEqual({ action: "spawned", exitCode: 0 });
244
- expect(spawned).toHaveLength(1);
245
- expect(spawned[0]?.args).toEqual(["/plugin/components/codegraph/dist/cli.js", "hook", "session-start-worker"]);
246
- expect(spawned[0]?.command).toBe(process.execPath);
247
- expect(spawned[0]?.env["HOME"]).toBe(homeDir);
248
- expect(spawned[0]?.env["OMO_CODEGRAPH_SESSION_START_CWD"]).toBe(workspace);
249
- expect(spawned[0]?.env["OMO_CODEGRAPH_SESSION_START_LOCK_TOKEN"]).toMatch(/^[0-9a-f-]{36}$/);
250
- expect(spawned[0]?.env["OPENAI_API_KEY"]).toBeUndefined();
251
- expect(spawned[0]?.env["KEEP"]).toBeUndefined();
252
- expect(JSON.parse(stdout.join(""))).toEqual({
253
- hookSpecificOutput: {
254
- additionalContext: "LazyCodex CodeGraph bootstrap scheduled in background",
255
- hookEventName: "SessionStart",
256
- },
257
- });
258
- } finally {
259
- rmSync(homeDir, { recursive: true, force: true });
260
- rmSync(workspace, { recursive: true, force: true });
261
- }
262
- });
263
-
264
- it("#given CodeGraph is already initialized #when SessionStart fires #then it stays silent without spawning", async () => {
265
- // given
266
- const stdout: string[] = [];
267
- const spawned: WorkerSpawnInvocation[] = [];
268
- const workspace = createAllowedWorkspace("codegraph-initialized-workspace");
269
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-initialized-home-"));
270
-
271
- try {
272
- mkdirSync(join(workspace, ".codegraph"), { recursive: true });
273
- writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
274
-
275
- // when
276
- const result = await executeCodegraphSessionStartHook({
277
- ancestorProbe: () => {
278
- throw new Error("an initialized exact root must not invoke any fallback probe");
279
- },
280
- config: { codegraph: { enabled: true }, sources: [], warnings: [] },
281
- cwd: workspace,
282
- env: { HOME: homeDir, KEEP: "1" },
283
- stdin: Readable.from(["{}"]),
284
- stdout: { write: (chunk) => stdout.push(chunk) },
285
- sweepZombies: () => undefined,
286
- spawnWorker: (invocation) => spawned.push(invocation),
287
- });
288
-
289
- // then
290
- expect(result).toEqual({ action: "skipped-initialized", exitCode: 0 });
291
- expect(spawned).toEqual([]);
292
- expect(stdout.join("")).toBe("");
293
- } finally {
294
- rmSync(homeDir, { recursive: true, force: true });
295
- rmSync(workspace, { recursive: true, force: true });
296
- }
297
- });
298
-
299
- it("#given malformed hook input with CodeGraph disabled #when SessionStart fires #then it stays silent and exits zero", async () => {
300
- // given
301
- const stdout: string[] = [];
302
- const spawned: WorkerSpawnInvocation[] = [];
303
-
304
- // when
305
- const result = await executeCodegraphSessionStartHook({
306
- config: { codegraph: { enabled: false }, sources: [], warnings: [] },
307
- env: {},
308
- stdin: Readable.from(["{not-json"]),
309
- stdout: { write: (chunk) => stdout.push(chunk) },
310
- sweepZombies: () => undefined,
311
- spawnWorker: (invocation) => spawned.push(invocation),
312
- });
313
-
314
- // then
315
- expect(result.exitCode).toBe(0);
316
- expect(spawned).toEqual([]);
317
- expect(stdout.join("")).toBe("");
318
- });
319
-
320
- });
@@ -1,172 +0,0 @@
1
- import { chmodSync, writeFileSync } from "node:fs";
2
-
3
- export const CODEGRAPH_150_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
-
32
- export function writeFakeNewlineCodegraph(filePath: string): void {
33
- writeFileSync(
34
- filePath,
35
- [
36
- "#!/usr/bin/env node",
37
- "const fs = require('node:fs');",
38
- "const readline = require('node:readline');",
39
- "fs.writeFileSync(process.env.CODEGRAPH_FAKE_LOG, `cwd=${process.cwd()}\\n`);",
40
- "const rl = readline.createInterface({ input: process.stdin });",
41
- "rl.on('line', (line) => {",
42
- " const request = JSON.parse(line);",
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.5.0' } } }) + '\\n');",
45
- " }",
46
- " if (request.method === 'tools/list') {",
47
- ` process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { tools: ${JSON.stringify(CODEGRAPH_150_DEFAULT_TOOLS)} } }) + '\\n');`,
48
- " }",
49
- "});",
50
- ].join("\n"),
51
- );
52
- chmodSync(filePath, 0o755);
53
- }
54
-
55
- export function writeFakeContractCodegraph(filePath: string): void {
56
- writeFileSync(
57
- filePath,
58
- [
59
- "#!/usr/bin/env node",
60
- "const fs = require('node:fs');",
61
- "const readline = require('node:readline');",
62
- "fs.writeFileSync(process.env.CODEGRAPH_FAKE_LOG, `cwd=${process.cwd()}\\n`);",
63
- "const rl = readline.createInterface({ input: process.stdin });",
64
- "rl.on('line', (line) => {",
65
- " const request = JSON.parse(line);",
66
- " if (request.method === 'tools/list') {",
67
- " process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { tools: [",
68
- " { name: 'codegraph_search', description: 'search stays unchanged' },",
69
- " { name: 'codegraph_node', description: 'ONE SYMBOL you can name - its location, signature, verbatim source (includeCode=true) and caller/callee trail in one call', inputSchema: { type: 'object', properties: { includeCode: { type: 'boolean', description: \"Symbol mode: include the symbol's full body (default: false).\" }, symbol: { type: 'string' } } } }",
70
- " ] } }) + '\\n');",
71
- " }",
72
- " if (request.method === 'tools/call') {",
73
- " process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { content: [{ type: 'text', text: 'JsonlMCP\\nMembers (7)\\nStructural outline only. For full source, use the Read tool on this file or request a member.' }] } }) + '\\n');",
74
- " }",
75
- "});",
76
- ].join("\n"),
77
- );
78
- chmodSync(filePath, 0o755);
79
- }
80
-
81
- export function writeFakeHeldOpenCodegraph(filePath: string): void {
82
- writeFileSync(
83
- filePath,
84
- [
85
- "#!/usr/bin/env node",
86
- "const fs = require('node:fs');",
87
- "const readline = require('node:readline');",
88
- "fs.writeFileSync(process.env.CODEGRAPH_FAKE_LOG, String(process.pid));",
89
- "const rl = readline.createInterface({ input: process.stdin });",
90
- "rl.once('line', (line) => {",
91
- " const request = JSON.parse(line);",
92
- " process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { ok: true } }) + '\\n');",
93
- "});",
94
- "setInterval(() => {}, 1000);",
95
- ].join("\n"),
96
- );
97
- chmodSync(filePath, 0o755);
98
- }
99
-
100
- export function writeFakeExitingCodegraph(filePath: string): void {
101
- writeFileSync(
102
- filePath,
103
- [
104
- "#!/usr/bin/env node",
105
- "const readline = require('node:readline');",
106
- "const rl = readline.createInterface({ input: process.stdin });",
107
- "rl.once('line', (line) => {",
108
- " const request = JSON.parse(line);",
109
- " process.stdout.write(JSON.stringify({ jsonrpc: '2.0', id: request.id, result: { ok: true } }) + '\\n', () => process.exit(0));",
110
- "});",
111
- ].join("\n"),
112
- );
113
- chmodSync(filePath, 0o755);
114
- }
115
-
116
- export function frameMcpRequest(request: {
117
- readonly id: number;
118
- readonly method: string;
119
- readonly params: Record<string, unknown>;
120
- }): string {
121
- const body = JSON.stringify({ jsonrpc: "2.0", ...request });
122
- return `Content-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`;
123
- }
124
-
125
- export function parseMcpBodies(transcript: string): readonly unknown[] {
126
- const bodies: unknown[] = [];
127
- let cursor = 0;
128
- while (cursor < transcript.length) {
129
- const headerEnd = transcript.indexOf("\r\n\r\n", cursor);
130
- if (headerEnd === -1) break;
131
- const header = transcript.slice(cursor, headerEnd);
132
- const match = /^Content-Length: (?<length>\d+)$/m.exec(header);
133
- if (match?.groups?.["length"] === undefined) break;
134
- const length = Number.parseInt(match.groups["length"], 10);
135
- const bodyStart = headerEnd + 4;
136
- const body = transcript.slice(bodyStart, bodyStart + length);
137
- bodies.push(JSON.parse(body));
138
- cursor = bodyStart + length;
139
- }
140
- return bodies;
141
- }
142
-
143
- export function findTool(tools: readonly unknown[], name: string): Record<string, unknown> {
144
- for (const tool of tools) {
145
- const record = recordValue(tool);
146
- if (record["name"] === name) return record;
147
- }
148
- throw new Error(`Missing tool ${name}`);
149
- }
150
-
151
- export function arrayProperty(record: Record<string, unknown>, key: string): readonly unknown[] {
152
- const value = record[key];
153
- if (!Array.isArray(value)) throw new Error(`Expected ${key} to be an array`);
154
- return value;
155
- }
156
-
157
- export function recordProperty(record: Record<string, unknown>, key: string): Record<string, unknown> {
158
- return recordValue(record[key]);
159
- }
160
-
161
- export function stringProperty(record: Record<string, unknown>, key: string): string {
162
- const value = record[key];
163
- if (typeof value !== "string") throw new Error(`Expected ${key} to be a string`);
164
- return value;
165
- }
166
-
167
- export function recordValue(value: unknown): Record<string, unknown> {
168
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
169
- throw new Error("Expected record value");
170
- }
171
- return value as Record<string, unknown>;
172
- }
@@ -1,91 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { existsSync, readFileSync } from "node:fs";
3
- import { dirname, resolve } from "node:path";
4
- import { fileURLToPath } from "node:url";
5
-
6
- type CodegraphPackageJson = {
7
- readonly files?: readonly string[];
8
- readonly optionalDependencies?: Readonly<Record<string, string>>;
9
- };
10
-
11
- const componentRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
12
- const repoRoot = resolve(componentRoot, "../../../../..");
13
-
14
- function readCodegraphPackageJson(): CodegraphPackageJson {
15
- const parsed: unknown = JSON.parse(readFileSync(resolve(componentRoot, "package.json"), "utf8"));
16
- if (!isCodegraphPackageJson(parsed)) throw new TypeError("Invalid CodeGraph package metadata");
17
- return parsed;
18
- }
19
-
20
- function isCodegraphPackageJson(value: unknown): value is CodegraphPackageJson {
21
- return isRecord(value) && maybeStringArray(value["files"]) && maybeStringRecord(value["optionalDependencies"]);
22
- }
23
-
24
- function maybeStringArray(value: unknown): value is readonly string[] | undefined {
25
- return value === undefined || (Array.isArray(value) && value.every((item) => typeof item === "string"));
26
- }
27
-
28
- function maybeStringRecord(value: unknown): value is Readonly<Record<string, string>> | undefined {
29
- return value === undefined || (isRecord(value) && Object.values(value).every((item) => typeof item === "string"));
30
- }
31
-
32
- function isRecord(value: unknown): value is Record<string, unknown> {
33
- return typeof value === "object" && value !== null && !Array.isArray(value);
34
- }
35
-
36
- describe("CodeGraph component runtime package metadata", () => {
37
- it("#given the CodeGraph component package #when validating runtime distribution metadata #then upstream CodeGraph installs optionally with shipped legal files", () => {
38
- // given
39
- const packageJson = readCodegraphPackageJson();
40
-
41
- // when
42
- const optionalDependencies = packageJson.optionalDependencies ?? {};
43
- const files = packageJson.files ?? [];
44
-
45
- // then
46
- expect(optionalDependencies["@colbymchenry/codegraph"]).toBe("1.5.0");
47
- expect(files).toContain("LICENSE");
48
- expect(files).toContain("NODE-RUNTIME-LICENSES.md");
49
- expect(files).toContain("NOTICE");
50
- expect(existsSync(resolve(componentRoot, "LICENSE"))).toBe(true);
51
- expect(existsSync(resolve(componentRoot, "NODE-RUNTIME-LICENSES.md"))).toBe(true);
52
- expect(existsSync(resolve(componentRoot, "NOTICE"))).toBe(true);
53
- expect(existsSync(resolve(componentRoot, "dist", "cli.d.ts"))).toBe(false);
54
- expect(existsSync(resolve(componentRoot, "dist", "serve.d.ts"))).toBe(false);
55
- });
56
-
57
- it("#given marketplace payload includes only the plugin tree #when reading CodeGraph NOTICE #then it is self-contained", () => {
58
- // given
59
- const notice = readFileSync(resolve(componentRoot, "NOTICE"), "utf8");
60
-
61
- expect(notice).toContain("@colbymchenry/codegraph@1.5.0");
62
- expect(notice).toContain("MIT license");
63
- expect(notice).toContain("Node.js v24.16.0 runtime");
64
- expect(notice).toContain("NODE-RUNTIME-LICENSES.md");
65
- expect(notice).not.toContain("packages/omo-codex/THIRD-PARTY-NOTICES.md");
66
- });
67
-
68
- it("#given CodeGraph platform bundles include Node #when reading runtime licenses #then Node license text ships with the component", () => {
69
- // given
70
- const licenseText = readFileSync(resolve(componentRoot, "NODE-RUNTIME-LICENSES.md"), "utf8");
71
-
72
- // then
73
- expect(licenseText).toContain("Node.js v24.16.0 LICENSE text");
74
- expect(licenseText).toContain("Copyright Node.js contributors");
75
- expect(licenseText).toContain("The externally maintained libraries used by Node.js are:");
76
- });
77
-
78
- it("#given third-party notices #when validating CodeGraph component notices #then aggregate Codex notices list CodeGraph as shipped", () => {
79
- // given
80
- const codexNotice = readFileSync(resolve(repoRoot, "packages/omo-codex/THIRD-PARTY-NOTICES.md"), "utf8");
81
-
82
- // when
83
- const listsCodegraphComponent = codexNotice.includes("@sisyphuslabs/codex-codegraph");
84
- const listsUpstreamRuntime = codexNotice.includes("@colbymchenry/codegraph");
85
-
86
- // then
87
- expect(listsCodegraphComponent).toBe(true);
88
- expect(listsUpstreamRuntime).toBe(true);
89
- expect(codexNotice).not.toContain("not currently an omo-codex plugin component");
90
- });
91
- });
@@ -1,100 +0,0 @@
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 } from "node:path";
5
-
6
- import { CODEGRAPH_PINNED_VERSION } from "../../../../../utils/src/codegraph/manifest.ts";
7
- import { runCodegraphSessionStartWorker } from "../src/hook.ts";
8
- import { runCodegraphServe } from "../src/serve.ts";
9
-
10
- describe("CodeGraph provisioned launcher Node guard", () => {
11
- it("#given provisioned CodeGraph binary #when serve runs under unsupported local Node #then it trusts the launcher", async () => {
12
- // given
13
- const commandPath = "/home/test/.omo/codegraph/bin/codegraph";
14
- const spawned: Array<{ readonly args: readonly string[]; readonly command: string }> = [];
15
-
16
- // when
17
- const exitCode = await runCodegraphServe({
18
- env: {},
19
- nodeVersion: "26.3.0",
20
- buildEnv: () => ({}),
21
- resolve: () => ({ argsPrefix: [], command: commandPath, exists: true, source: "provisioned" }),
22
- runProcess: (command, args) => {
23
- spawned.push({ args, command });
24
- return Promise.resolve(0);
25
- },
26
- stderr: { write: () => undefined },
27
- });
28
-
29
- // then
30
- expect(exitCode).toBe(0);
31
- expect(spawned).toEqual([{ args: ["serve", "--mcp"], command: commandPath }]);
32
- });
33
-
34
- it("#given provisioned CodeGraph exists #when SessionStart worker runs under unsupported local Node #then it bootstraps through the launcher", async () => {
35
- // given
36
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-node25-"));
37
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-node25-home-"));
38
- const installDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-node25-install-"));
39
- const binPath = join(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
40
- const calls: Array<{ readonly args: readonly string[]; readonly command: string }> = [];
41
- const outcomes: unknown[] = [];
42
-
43
- try {
44
- mkdirSync(join(installDir, "bin"), { recursive: true });
45
- mkdirSync(join(installDir, ".provisioned"), { recursive: true });
46
- writeFileSync(binPath, "");
47
- writeFileSync(
48
- join(installDir, ".provisioned", `codegraph-${CODEGRAPH_PINNED_VERSION}.json`),
49
- `${JSON.stringify({ binPath, version: CODEGRAPH_PINNED_VERSION })}\n`,
50
- );
51
-
52
- // when
53
- const result = await runCodegraphSessionStartWorker({
54
- config: { codegraph: { enabled: true, install_dir: installDir }, sources: [], trustedCodegraphInstallDir: installDir, warnings: [] },
55
- nodeVersion: "26.3.0",
56
- cwd: workspace,
57
- env: { HOME: homeDir },
58
- logOutcome: (outcome) => outcomes.push(outcome),
59
- deps: {
60
- ensureGitignored: () => true,
61
- ensureProvisioned: () => {
62
- throw new Error("provisioning should not run when install_dir binary exists");
63
- },
64
- prepareWorkspace: () => ({
65
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
66
- dataRoot: join(homeDir, ".omo/codegraph"),
67
- linked: true,
68
- mode: "global-linked",
69
- projectLink: join(workspace, ".codegraph"),
70
- }),
71
- resolveCommand: (options) => {
72
- const provisioned = options?.provisioned?.() ?? null;
73
- return {
74
- argsPrefix: [],
75
- command: provisioned ?? "missing-codegraph",
76
- exists: provisioned !== null,
77
- source: provisioned === null ? "path" : "provisioned",
78
- };
79
- },
80
- resolveManagedBin: () => binPath,
81
- runCommand: (_projectRoot, command, args) => {
82
- calls.push({ args, command });
83
- mkdirSync(join(workspace, ".codegraph"), { recursive: true });
84
- writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
85
- return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
86
- },
87
- },
88
- });
89
-
90
- // then
91
- expect(result).toEqual({ action: "initialized" });
92
- expect(calls).toEqual([{ args: ["init"], command: binPath }]);
93
- expect(outcomes).toEqual([{ action: "initialized", exitCode: 0, projectRoot: workspace, source: "provisioned", timedOut: false }]);
94
- } finally {
95
- rmSync(workspace, { recursive: true, force: true });
96
- rmSync(homeDir, { recursive: true, force: true });
97
- rmSync(installDir, { recursive: true, force: true });
98
- }
99
- });
100
- });