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,104 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { mkdtempSync, rmSync, utimesSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
-
6
- import {
7
- clearSessionStartCooldown,
8
- readSessionStartCooldown,
9
- recordSessionStartFailure,
10
- } from "../src/session-start-cooldown.ts";
11
- import {
12
- acquireSessionStartLock,
13
- releaseSessionStartLock,
14
- } from "../src/session-start-lock.ts";
15
-
16
- describe("CodeGraph SessionStart lock", () => {
17
- it("#given a live project lock #when a second hook acquires it #then the second hook is deduplicated", () => {
18
- // given
19
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-lock-home-"));
20
- const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-lock-project-"));
21
- try {
22
- const first = acquireSessionStartLock({ homeDir, nowMs: 10_000, projectRoot, staleMs: 60_000 });
23
- expect(first.kind).toBe("acquired");
24
-
25
- // when
26
- const second = acquireSessionStartLock({ homeDir, nowMs: 10_001, projectRoot, staleMs: 60_000 });
27
-
28
- // then
29
- expect(second).toEqual({ kind: "locked" });
30
- if (first.kind === "acquired") releaseSessionStartLock(first.lock);
31
- } finally {
32
- rmSync(homeDir, { recursive: true, force: true });
33
- rmSync(projectRoot, { recursive: true, force: true });
34
- }
35
- });
36
-
37
- it("#given a project lock older than the stale threshold #when another hook acquires it #then the stale lock is recovered", () => {
38
- // given
39
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-stale-home-"));
40
- const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-stale-project-"));
41
- try {
42
- const first = acquireSessionStartLock({ homeDir, nowMs: 1_000, projectRoot, staleMs: 500 });
43
- expect(first.kind).toBe("acquired");
44
- if (first.kind !== "acquired") return;
45
- const staleDate = new Date(1_000);
46
- utimesSync(first.lock.path, staleDate, staleDate);
47
-
48
- // when
49
- const second = acquireSessionStartLock({ homeDir, nowMs: 2_000, projectRoot, staleMs: 500 });
50
-
51
- // then
52
- expect(second.kind).toBe("acquired");
53
- if (second.kind === "acquired") {
54
- expect(second.recoveredStale).toBe(true);
55
- releaseSessionStartLock(second.lock);
56
- }
57
- } finally {
58
- rmSync(homeDir, { recursive: true, force: true });
59
- rmSync(projectRoot, { recursive: true, force: true });
60
- }
61
- });
62
- });
63
-
64
- describe("CodeGraph SessionStart cooldown", () => {
65
- it("#given a failed worker outcome #when the cooldown is checked #then retries are suppressed until expiry and the next failure backs off", () => {
66
- // given
67
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-cooldown-home-"));
68
- const projectRoot = mkdtempSync(join(tmpdir(), "omo-codegraph-cooldown-project-"));
69
- try {
70
- const first = recordSessionStartFailure({
71
- action: "failed",
72
- baseCooldownMs: 1_000,
73
- homeDir,
74
- nowMs: 1_000,
75
- projectRoot,
76
- });
77
-
78
- // when
79
- const active = readSessionStartCooldown({ baseCooldownMs: 1_000, homeDir, nowMs: 1_999, projectRoot });
80
- const expired = readSessionStartCooldown({ baseCooldownMs: 1_000, homeDir, nowMs: 2_000, projectRoot });
81
- const second = recordSessionStartFailure({
82
- action: "skipped-status",
83
- baseCooldownMs: 1_000,
84
- homeDir,
85
- nowMs: 2_000,
86
- projectRoot,
87
- });
88
-
89
- // then
90
- expect(first).toMatchObject({ cooldownUntil: 2_000, failureCount: 1 });
91
- expect(active).toMatchObject({ cooldownUntil: 2_000, failureCount: 1, kind: "active" });
92
- expect(expired).toEqual({ failureCount: 1, kind: "inactive" });
93
- expect(second).toMatchObject({ cooldownUntil: 4_000, failureCount: 2 });
94
- clearSessionStartCooldown({ homeDir, projectRoot });
95
- expect(readSessionStartCooldown({ baseCooldownMs: 1_000, homeDir, nowMs: 2_001, projectRoot })).toEqual({
96
- failureCount: 0,
97
- kind: "inactive",
98
- });
99
- } finally {
100
- rmSync(homeDir, { recursive: true, force: true });
101
- rmSync(projectRoot, { recursive: true, force: true });
102
- }
103
- });
104
- });
@@ -1,65 +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 { runCodegraphSessionStartWorker } from "../src/hook.ts";
7
-
8
- describe("CodeGraph SessionStart trust boundary", () => {
9
- it("#given project config sets install_dir #when worker provisions CodeGraph #then it uses the trusted home install root", async () => {
10
- // given
11
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-untrusted-project-"));
12
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-untrusted-project-home-"));
13
- const attackerInstallDir = join(workspace, "attacker-install");
14
- const trustedInstallDir = join(homeDir, ".omo", "codegraph");
15
- const calls: Array<{ readonly env: Record<string, string>; readonly installDir?: string; readonly lockDir?: string }> = [];
16
- try {
17
- mkdirSync(join(workspace, ".omo"), { recursive: true });
18
- writeFileSync(join(workspace, ".omo", "omo.jsonc"), JSON.stringify({ codegraph: { enabled: true, install_dir: attackerInstallDir } }));
19
-
20
- // when
21
- const result = await runCodegraphSessionStartWorker({
22
- cwd: workspace,
23
- env: { HOME: homeDir },
24
- nodeVersion: "22.14.0",
25
- deps: {
26
- ensureGitignored: () => true,
27
- ensureProvisioned: (options) => {
28
- calls.push({
29
- env: {},
30
- ...(options.installDir === undefined ? {} : { installDir: options.installDir }),
31
- ...(options.lockDir === undefined ? {} : { lockDir: options.lockDir }),
32
- });
33
- return Promise.resolve({ binPath: join(trustedInstallDir, "bin", "codegraph"), provisioned: true });
34
- },
35
- prepareWorkspace: () => ({
36
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
37
- dataRoot: join(homeDir, ".omo/codegraph"),
38
- linked: true,
39
- mode: "global-linked",
40
- projectLink: join(workspace, ".codegraph"),
41
- }),
42
- resolveCommand: (options) => {
43
- expect(options?.provisioned?.()).toBe(null);
44
- return { argsPrefix: [], command: "missing-codegraph", exists: false, source: "path" };
45
- },
46
- runCommand: (_projectRoot, _command, _args, options) => {
47
- calls.push({ env: options.env });
48
- mkdirSync(join(workspace, ".codegraph"), { recursive: true });
49
- writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
50
- return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
51
- },
52
- },
53
- });
54
-
55
- // then
56
- expect(result).toEqual({ action: "initialized" });
57
- expect(calls[0]).toEqual({ env: {}, installDir: trustedInstallDir, lockDir: join(trustedInstallDir, ".locks") });
58
- expect(calls[1]?.env["CODEGRAPH_INSTALL_DIR"]).toBe(trustedInstallDir);
59
- expect(calls[1]?.env["CODEGRAPH_INSTALL_DIR"]).not.toBe(attackerInstallDir);
60
- } finally {
61
- rmSync(workspace, { recursive: true, force: true });
62
- rmSync(homeDir, { recursive: true, force: true });
63
- }
64
- });
65
- });
@@ -1,106 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { existsSync, mkdtempSync, rmSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
-
6
- import { runCodegraphSessionStartWorker } from "../src/hook.ts";
7
-
8
- describe("CodeGraph SessionStart worker availability", () => {
9
- it("#given CodeGraph cannot be resolved or provisioned #when worker runs #then it logs a graceful skip", async () => {
10
- // given
11
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-"));
12
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-home-"));
13
- const outcomes: unknown[] = [];
14
- const calls: string[] = [];
15
-
16
- try {
17
- // when
18
- const result = await runCodegraphSessionStartWorker({
19
- cwd: workspace,
20
- env: { HOME: homeDir },
21
- nodeVersion: "22.14.0",
22
- logOutcome: (outcome) => outcomes.push(outcome),
23
- deps: {
24
- ensureGitignored: () => {
25
- calls.push("ensureGitignored");
26
- return true;
27
- },
28
- ensureProvisioned: () => Promise.resolve({ error: "offline", provisioned: false }),
29
- prepareWorkspace: () => {
30
- calls.push("prepareWorkspace");
31
- return {
32
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
33
- dataRoot: join(homeDir, ".omo/codegraph"),
34
- linked: true,
35
- mode: "global-linked",
36
- projectLink: join(workspace, ".codegraph"),
37
- };
38
- },
39
- resolveCommand: () => ({ argsPrefix: [], command: "codegraph", exists: false, source: "path" }),
40
- runCommand: () => {
41
- calls.push("runCommand");
42
- return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
43
- },
44
- },
45
- });
46
-
47
- // then
48
- expect(result).toEqual({ action: "skipped-unavailable" });
49
- expect(calls).toEqual([]);
50
- expect(outcomes).toEqual([
51
- {
52
- action: "skipped-unavailable",
53
- error: "offline",
54
- projectRoot: workspace,
55
- source: "path",
56
- },
57
- ]);
58
- } finally {
59
- rmSync(workspace, { recursive: true, force: true });
60
- rmSync(homeDir, { recursive: true, force: true });
61
- }
62
- });
63
-
64
- it("#given CodeGraph is unavailable and auto provisioning is disabled #when worker runs #then it leaves the project untouched", async () => {
65
- // given
66
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-unavailable-"));
67
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-unavailable-home-"));
68
- const outcomes: unknown[] = [];
69
-
70
- try {
71
- // when
72
- const result = await runCodegraphSessionStartWorker({
73
- config: { codegraph: { auto_provision: false, enabled: true }, sources: [], warnings: [] },
74
- nodeVersion: "22.14.0",
75
- cwd: workspace,
76
- env: { HOME: homeDir },
77
- logOutcome: (outcome) => outcomes.push(outcome),
78
- deps: {
79
- ensureProvisioned: () => {
80
- throw new Error("auto provision should not run");
81
- },
82
- resolveCommand: () => ({ argsPrefix: [], command: "missing-codegraph", exists: false, source: "path" }),
83
- runCommand: () => {
84
- throw new Error("codegraph command should not run");
85
- },
86
- },
87
- });
88
-
89
- // then
90
- expect(result).toEqual({ action: "skipped-unavailable" });
91
- expect(existsSync(join(workspace, ".codegraph"))).toBe(false);
92
- expect(existsSync(join(workspace, ".git", "info", "exclude"))).toBe(false);
93
- expect(outcomes).toEqual([
94
- {
95
- action: "skipped-unavailable",
96
- error: "codegraph binary unavailable and auto_provision is disabled",
97
- projectRoot: workspace,
98
- source: "path",
99
- },
100
- ]);
101
- } finally {
102
- rmSync(workspace, { recursive: true, force: true });
103
- rmSync(homeDir, { recursive: true, force: true });
104
- }
105
- });
106
- });
@@ -1,116 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { mkdtempSync, rmSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
-
6
- import type { CodegraphSessionStartOutcome } from "../src/hook.ts";
7
- import { runCodegraphSessionStartWorker } from "../src/hook.ts";
8
- import { readSessionStartCooldown } from "../src/session-start-cooldown.ts";
9
-
10
- describe("CodeGraph SessionStart worker cooldown", () => {
11
- it("#given codegraph init times out #when the worker finishes #then it records a failed outcome and cooldown", async () => {
12
- // given
13
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-timeout-"));
14
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-timeout-home-"));
15
- const outcomes: CodegraphSessionStartOutcome[] = [];
16
- try {
17
- // when
18
- const result = await runCodegraphSessionStartWorker({
19
- config: { codegraph: { enabled: true, session_start_cooldown_ms: 60_000 }, sources: [], warnings: [] },
20
- cwd: workspace,
21
- env: { HOME: homeDir },
22
- logOutcome: (outcome) => outcomes.push(outcome),
23
- nodeVersion: "22.14.0",
24
- nowMs: 1_000,
25
- projectProbe: () => ({ kind: "uninitialized" }),
26
- deps: {
27
- ensureGitignored: () => true,
28
- ensureProvisioned: () => Promise.resolve({ binPath: "/tmp/codegraph", provisioned: true }),
29
- prepareWorkspace: () => ({
30
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
31
- dataRoot: join(homeDir, ".omo/codegraph"),
32
- linked: true,
33
- mode: "global-linked",
34
- projectLink: join(workspace, ".codegraph"),
35
- }),
36
- resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
37
- runCommand: () => Promise.resolve({ exitCode: 1, stdout: "", timedOut: true }),
38
- },
39
- });
40
- const cooldown = readSessionStartCooldown({
41
- baseCooldownMs: 60_000,
42
- homeDir,
43
- nowMs: 2_000,
44
- projectRoot: workspace,
45
- });
46
-
47
- // then
48
- expect(result).toEqual({ action: "failed" });
49
- expect(outcomes).toEqual([{
50
- action: "failed",
51
- error: "codegraph init timed out",
52
- exitCode: 1,
53
- projectRoot: workspace,
54
- source: "path",
55
- timedOut: true,
56
- }]);
57
- expect(cooldown).toEqual({ cooldownUntil: 61_000, failureCount: 1, kind: "active" });
58
- } finally {
59
- rmSync(homeDir, { recursive: true, force: true });
60
- rmSync(workspace, { recursive: true, force: true });
61
- }
62
- });
63
-
64
- it("#given codegraph init exits zero without an exact database #when the worker verifies the result #then it records a failure cooldown", async () => {
65
- // given
66
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-no-db-"));
67
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-no-db-home-"));
68
- const outcomes: CodegraphSessionStartOutcome[] = [];
69
- try {
70
- // when
71
- const result = await runCodegraphSessionStartWorker({
72
- config: { codegraph: { enabled: true, session_start_cooldown_ms: 60_000 }, sources: [], warnings: [] },
73
- cwd: workspace,
74
- env: { HOME: homeDir },
75
- logOutcome: (outcome) => outcomes.push(outcome),
76
- nodeVersion: "22.14.0",
77
- nowMs: 1_000,
78
- projectProbe: () => ({ kind: "uninitialized" }),
79
- deps: {
80
- ensureGitignored: () => true,
81
- ensureProvisioned: () => Promise.resolve({ binPath: "/tmp/codegraph", provisioned: true }),
82
- prepareWorkspace: () => ({
83
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
84
- dataRoot: join(homeDir, ".omo/codegraph"),
85
- linked: true,
86
- mode: "global-linked",
87
- projectLink: join(workspace, ".codegraph"),
88
- }),
89
- resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
90
- runCommand: () => Promise.resolve({ exitCode: 0, stdout: "", timedOut: false }),
91
- },
92
- });
93
- const cooldown = readSessionStartCooldown({
94
- baseCooldownMs: 60_000,
95
- homeDir,
96
- nowMs: 2_000,
97
- projectRoot: workspace,
98
- });
99
-
100
- // then
101
- expect(result).toEqual({ action: "failed" });
102
- expect(outcomes).toEqual([{
103
- action: "failed",
104
- error: "codegraph init completed without creating an exact project database",
105
- exitCode: 0,
106
- projectRoot: workspace,
107
- source: "path",
108
- timedOut: false,
109
- }]);
110
- expect(cooldown).toEqual({ cooldownUntil: 61_000, failureCount: 1, kind: "active" });
111
- } finally {
112
- rmSync(homeDir, { recursive: true, force: true });
113
- rmSync(workspace, { recursive: true, force: true });
114
- }
115
- });
116
- });
@@ -1,258 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { mkdirSync, mkdtempSync, readFileSync, 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 { resolveCodegraphCommandInvocation, runCodegraphSessionStartWorker } from "../src/hook.ts";
8
-
9
- function writeProjectDatabase(workspace: string): void {
10
- mkdirSync(join(workspace, ".codegraph"), { recursive: true });
11
- writeFileSync(join(workspace, ".codegraph", "codegraph.db"), "fixture");
12
- }
13
-
14
- describe("CodeGraph SessionStart worker flow", () => {
15
- it("#given install_dir has the pinned platform binary #when worker resolves provisioned CodeGraph #then it uses that launcher", async () => {
16
- // given
17
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-platform-"));
18
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-platform-home-"));
19
- const installDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-platform-install-"));
20
- const binPath = join(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
21
- const calls: { readonly args: readonly string[]; readonly command: string; readonly env: Record<string, string> }[] = [];
22
- const outcomes: unknown[] = [];
23
- try {
24
- mkdirSync(join(installDir, "bin"), { recursive: true });
25
- mkdirSync(join(installDir, ".provisioned"), { recursive: true });
26
- writeFileSync(binPath, "");
27
- writeFileSync(
28
- join(installDir, ".provisioned", `codegraph-${CODEGRAPH_PINNED_VERSION}.json`),
29
- `${JSON.stringify({ binPath, version: CODEGRAPH_PINNED_VERSION })}\n`,
30
- );
31
-
32
- // when
33
- const result = await runCodegraphSessionStartWorker({
34
- config: { codegraph: { enabled: true, install_dir: installDir }, sources: [], trustedCodegraphInstallDir: installDir, warnings: [] },
35
- nodeVersion: "22.14.0",
36
- cwd: workspace,
37
- env: { HOME: homeDir },
38
- logOutcome: (outcome) => outcomes.push(outcome),
39
- deps: {
40
- ensureGitignored: () => true,
41
- ensureProvisioned: () => {
42
- throw new Error("provisioning should not run when install_dir binary exists");
43
- },
44
- prepareWorkspace: () => ({
45
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
46
- dataRoot: join(homeDir, ".omo/codegraph"),
47
- linked: true,
48
- mode: "global-linked",
49
- projectLink: join(workspace, ".codegraph"),
50
- }),
51
- resolveCommand: (options) => {
52
- const provisioned = options?.provisioned?.() ?? null;
53
- return { argsPrefix: [], command: provisioned ?? "missing-codegraph", exists: provisioned !== null, source: provisioned === null ? "path" : "provisioned" };
54
- },
55
- resolveManagedBin: () => binPath,
56
- runCommand: (_projectRoot, command, args, options) => {
57
- calls.push({ args, command, env: options.env });
58
- writeProjectDatabase(workspace);
59
- return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
60
- },
61
- },
62
- });
63
-
64
- // then
65
- expect(result).toEqual({ action: "initialized" });
66
- expect(calls.map((call) => ({ args: [...call.args], command: call.command }))).toEqual([
67
- { args: ["init"], command: binPath },
68
- ]);
69
- expect(calls[0]?.env["CODEGRAPH_INSTALL_DIR"]).toBe(installDir);
70
- expect(outcomes).toEqual([{ action: "initialized", exitCode: 0, projectRoot: workspace, source: "provisioned", timedOut: false }]);
71
- } finally {
72
- rmSync(workspace, { recursive: true, force: true });
73
- rmSync(homeDir, { recursive: true, force: true });
74
- rmSync(installDir, { recursive: true, force: true });
75
- }
76
- });
77
-
78
- it("#given Windows codegraph.cmd #when default worker runner builds invocation #then it runs through cmd.exe", () => {
79
- // given
80
- const command = "C:\\Users\\test\\.omo\\codegraph\\bin\\codegraph.cmd";
81
-
82
- // when
83
- const invocation = resolveCodegraphCommandInvocation(command, ["init"], "win32");
84
-
85
- // then
86
- expect(invocation).toEqual({
87
- args: ["/d", "/s", "/c", command, "init"],
88
- command: "cmd.exe",
89
- });
90
- });
91
-
92
- it("#given Windows CodeGraph resolves to a Node script #when default worker runner builds invocation #then Node executes it", () => {
93
- // given
94
- const command = "C:\\Users\\test\\.omo\\codegraph\\bin\\codegraph.cjs";
95
-
96
- // when
97
- const invocation = resolveCodegraphCommandInvocation(command, ["init"], "win32");
98
-
99
- // then
100
- expect(invocation).toEqual({
101
- args: [command, "init"],
102
- command: process.execPath,
103
- });
104
- });
105
-
106
- it("#given non-Windows codegraph command #when default worker runner builds invocation #then it executes directly", () => {
107
- // given
108
- const command = "/home/test/.omo/codegraph/bin/codegraph";
109
-
110
- // when
111
- const invocation = resolveCodegraphCommandInvocation(command, ["sync"], "linux");
112
-
113
- // then
114
- expect(invocation).toEqual({ args: ["sync"], command });
115
- });
116
-
117
- it("#given an uninitialized exact project #when worker runs #then it invokes init directly without a status command", async () => {
118
- // given
119
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-init-direct-"));
120
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-init-direct-home-"));
121
- const calls: { readonly args: readonly string[]; readonly env: Record<string, string> }[] = [];
122
- const outcomes: unknown[] = [];
123
- try {
124
- // when
125
- const result = await runCodegraphSessionStartWorker({
126
- config: { codegraph: { enabled: true, install_dir: "/tmp/codegraph-install" }, sources: [], trustedCodegraphInstallDir: "/tmp/codegraph-install", warnings: [] },
127
- nodeVersion: "22.14.0",
128
- cwd: workspace,
129
- env: { HOME: homeDir },
130
- logOutcome: (outcome) => outcomes.push(outcome),
131
- deps: {
132
- ensureGitignored: () => true,
133
- ensureProvisioned: () => Promise.resolve({ binPath: "/tmp/codegraph", provisioned: true }),
134
- prepareWorkspace: () => ({
135
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
136
- dataRoot: join(homeDir, ".omo/codegraph"),
137
- linked: true,
138
- mode: "global-linked",
139
- projectLink: join(workspace, ".codegraph"),
140
- }),
141
- resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
142
- runCommand: (_projectRoot, _command, args, options) => {
143
- calls.push({ args, env: options.env });
144
- writeProjectDatabase(workspace);
145
- return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
146
- },
147
- },
148
- });
149
-
150
- // then
151
- expect(result).toEqual({ action: "initialized" });
152
- expect(calls.map((call) => [...call.args])).toEqual([["init"]]);
153
- expect(calls[0]?.env["CODEGRAPH_INSTALL_DIR"]).toBe("/tmp/codegraph-install");
154
- expect(outcomes).toEqual([{ action: "initialized", exitCode: 0, projectRoot: workspace, source: "path", timedOut: false }]);
155
- } finally {
156
- rmSync(workspace, { recursive: true, force: true });
157
- rmSync(homeDir, { recursive: true, force: true });
158
- }
159
- });
160
-
161
- it("#given codegraph.daemon=true #when the indexing worker runs #then its env stays daemon-less with CODEGRAPH_NO_DAEMON=1", async () => {
162
- // given
163
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-daemon-"));
164
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-daemon-home-"));
165
- const calls: { readonly args: readonly string[]; readonly command: string; readonly env: Record<string, string> }[] = [];
166
- try {
167
- // when
168
- const result = await runCodegraphSessionStartWorker({
169
- config: { codegraph: { daemon: true, enabled: true, install_dir: "/tmp/codegraph-install" }, sources: [], trustedCodegraphInstallDir: "/tmp/codegraph-install", warnings: [] },
170
- nodeVersion: "22.14.0",
171
- cwd: workspace,
172
- env: { HOME: homeDir },
173
- logOutcome: () => undefined,
174
- deps: {
175
- ensureGitignored: () => true,
176
- ensureProvisioned: () => Promise.resolve({ binPath: "/tmp/codegraph", provisioned: true }),
177
- prepareWorkspace: () => ({
178
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
179
- dataRoot: join(homeDir, ".omo/codegraph"),
180
- linked: true,
181
- mode: "global-linked",
182
- projectLink: join(workspace, ".codegraph"),
183
- }),
184
- resolveCommand: () => ({ argsPrefix: [], command: "/tmp/codegraph", exists: true, source: "path" }),
185
- runCommand: (_projectRoot, command, args, options) => {
186
- calls.push({ args, command, env: options.env });
187
- writeProjectDatabase(workspace);
188
- return Promise.resolve({ exitCode: 0, stdout: "", timedOut: false });
189
- },
190
- },
191
- });
192
-
193
- // then
194
- expect(result).toEqual({ action: "initialized" });
195
- expect(calls.length).toBeGreaterThan(0);
196
- for (const call of calls) {
197
- expect(call.env["CODEGRAPH_NO_DAEMON"]).toBe("1");
198
- }
199
- } finally {
200
- rmSync(workspace, { recursive: true, force: true });
201
- rmSync(homeDir, { recursive: true, force: true });
202
- }
203
- });
204
-
205
- it("#given ambient provider tokens #when default worker runner spawns CodeGraph #then child env only gets safe and controlled variables", async () => {
206
- // given
207
- const workspace = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-env-"));
208
- const homeDir = mkdtempSync(join(tmpdir(), "omo-codegraph-worker-env-home-"));
209
- const logPath = join(homeDir, "child-env.jsonl");
210
- const originalOpenAiKey = process.env["OPENAI_API_KEY"];
211
- process.env["OPENAI_API_KEY"] = "sk-test-secret";
212
-
213
- try {
214
- const fakeCodegraphScript = [
215
- "const fs = require('node:fs');",
216
- `fs.appendFileSync(${JSON.stringify(logPath)}, JSON.stringify({install:process.env.CODEGRAPH_INSTALL_DIR,openai:process.env.OPENAI_API_KEY}) + '\\n');`,
217
- "fs.mkdirSync('.codegraph', { recursive: true });",
218
- "fs.writeFileSync('.codegraph/codegraph.db', 'fixture');",
219
- ].join("");
220
-
221
- // when
222
- const result = await runCodegraphSessionStartWorker({
223
- config: { codegraph: { enabled: true }, sources: [], warnings: [] },
224
- cwd: workspace,
225
- env: { HOME: homeDir },
226
- logOutcome: () => undefined,
227
- nodeVersion: "22.14.0",
228
- deps: {
229
- ensureGitignored: () => true,
230
- ensureProvisioned: () => {
231
- throw new Error("provisioning should not run when command is resolved");
232
- },
233
- prepareWorkspace: () => ({
234
- dataDir: join(homeDir, ".omo/codegraph/projects/test"),
235
- dataRoot: join(homeDir, ".omo/codegraph"),
236
- linked: true,
237
- mode: "global-linked",
238
- projectLink: join(workspace, ".codegraph"),
239
- }),
240
- resolveCommand: () => ({ argsPrefix: ["-e", fakeCodegraphScript], command: process.execPath, exists: true, source: "bundled" }),
241
- },
242
- });
243
-
244
- // then
245
- expect(result).toEqual({ action: "initialized" });
246
- const captured = readFileSync(logPath, "utf8")
247
- .trim()
248
- .split("\n")
249
- .map((line) => JSON.parse(line));
250
- expect(captured).toEqual([{ install: join(homeDir, ".omo", "codegraph") }]);
251
- } finally {
252
- if (originalOpenAiKey === undefined) delete process.env["OPENAI_API_KEY"];
253
- else process.env["OPENAI_API_KEY"] = originalOpenAiKey;
254
- rmSync(workspace, { recursive: true, force: true });
255
- rmSync(homeDir, { recursive: true, force: true });
256
- }
257
- });
258
- });