oh-my-opencode 4.15.1 → 4.16.0

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 (142) hide show
  1. package/dist/cli/doctor/checks/tui-plugin-config.d.ts +4 -4
  2. package/dist/cli/index.js +673 -678
  3. package/dist/cli/install-senpi/index.d.ts +1 -0
  4. package/dist/cli/run/poll-for-completion.d.ts +4 -0
  5. package/dist/cli/run/session-resolver.d.ts +1 -0
  6. package/dist/cli/senpi-platform-flag.d.ts +4 -0
  7. package/dist/cli/types.d.ts +2 -1
  8. package/dist/cli-node/index.js +673 -678
  9. package/dist/features/background-agent/manager.d.ts +16 -0
  10. package/dist/hooks/anthropic-context-window-limit-recovery/aggressive-truncation-strategy.d.ts +1 -0
  11. package/dist/index.js +1334 -1146
  12. package/dist/skills/debugging/references/methodology/06-fix.md +6 -0
  13. package/dist/skills/frontend/ATTRIBUTION.md +10 -1
  14. package/dist/skills/frontend/SKILL.md +8 -3
  15. package/dist/skills/frontend/references/design/README.md +1 -1
  16. package/dist/skills/frontend/references/design/_INDEX.md +1 -1
  17. package/dist/skills/frontend/references/design/lazyweb.md +77 -0
  18. package/dist/skills/frontend/references/design/stitch-design-example.md +121 -0
  19. package/dist/skills/programming/SKILL.md +10 -1
  20. package/dist/skills/programming/references/logging.md +91 -0
  21. package/dist/skills/ulw-plan/SKILL.md +5 -5
  22. package/dist/skills/ulw-plan/references/full-workflow.md +7 -7
  23. package/dist/skills/ulw-plan/references/intent-unclear.md +3 -3
  24. package/dist/skills/ulw-research/ATTRIBUTION.md +2 -2
  25. package/dist/skills/ulw-research/SKILL.md +28 -7
  26. package/dist/tools/skill/description-formatter.d.ts +1 -0
  27. package/dist/tools/skill/description-formatter.test-support.d.ts +9 -0
  28. package/dist/tools/skill/zauc-mocks-skill-tools/test-support.d.ts +25 -0
  29. package/dist/tui.js +121 -419
  30. package/package.json +32 -15
  31. package/packages/git-bash-mcp/dist/cli.js +2 -2
  32. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  33. package/packages/omo-codex/plugin/components/bootstrap/AGENTS.md +55 -0
  34. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +19 -16
  35. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  36. package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +51 -0
  37. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +936 -248
  38. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +233 -135
  39. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  40. package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +29 -0
  41. package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +13 -0
  42. package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +25 -0
  43. package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +3 -1
  44. package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +30 -1
  45. package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +16 -2
  46. package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +80 -0
  47. package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +34 -0
  48. package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +107 -0
  49. package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +26 -0
  50. package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +29 -0
  51. package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +8 -21
  52. package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +108 -0
  53. package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +76 -0
  54. package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +17 -111
  55. package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +1 -1
  56. package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +45 -67
  57. package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +56 -0
  58. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  59. package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +31 -0
  60. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/AGENTS.md +45 -0
  62. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  63. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  64. package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus.md +37 -102
  65. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  66. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  67. package/packages/omo-codex/plugin/components/teammode/AGENTS.md +46 -0
  68. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  69. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +6 -0
  70. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +6 -0
  71. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  72. package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -2
  73. package/packages/omo-codex/plugin/components/ultrawork/CHANGELOG.md +2 -0
  74. package/packages/omo-codex/plugin/components/ultrawork/README.md +3 -3
  75. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +51 -2
  76. package/packages/omo-codex/plugin/components/ultrawork/package.json +2 -1
  77. package/packages/omo-codex/plugin/components/ultrawork/scripts/sync-directive.mjs +14 -1
  78. package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +380 -0
  79. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +5 -2
  80. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +4 -4
  81. package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +2 -2
  82. package/packages/omo-codex/plugin/components/ultrawork/src/codex-hook.ts +5 -3
  83. package/packages/omo-codex/plugin/components/ultrawork/src/skill-pointer.ts +56 -0
  84. package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +4 -4
  85. package/packages/omo-codex/plugin/components/ultrawork/test/directive-source.test.ts +12 -0
  86. package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +1 -0
  87. package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +82 -0
  88. package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -0
  89. package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +56 -5
  90. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.d.ts +1 -0
  91. package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-hook.js +5 -1
  92. package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-directive.d.ts +2 -1
  93. package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-directive.js +5 -3
  94. package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-skill-pointer.d.ts +7 -0
  95. package/packages/omo-codex/plugin/components/ulw-loop/dist/ultrawork-skill-pointer.js +46 -0
  96. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  97. package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +5 -1
  98. package/packages/omo-codex/plugin/components/ulw-loop/src/ultrawork-directive.ts +9 -3
  99. package/packages/omo-codex/plugin/components/ulw-loop/src/ultrawork-skill-pointer.ts +55 -0
  100. package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +49 -0
  101. package/packages/omo-codex/plugin/package-lock.json +13 -13
  102. package/packages/omo-codex/plugin/package.json +1 -1
  103. package/packages/omo-codex/plugin/scripts/build-components.mjs +63 -17
  104. package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +10 -3
  105. package/packages/omo-codex/plugin/scripts/sync-skills.mjs +1 -0
  106. package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +18 -0
  107. package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +6 -0
  108. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +10 -1
  109. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +8 -3
  110. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +1 -1
  111. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -1
  112. package/packages/omo-codex/plugin/skills/frontend/references/design/lazyweb.md +77 -0
  113. package/packages/omo-codex/plugin/skills/frontend/references/design/stitch-design-example.md +121 -0
  114. package/packages/omo-codex/plugin/skills/programming/SKILL.md +10 -1
  115. package/packages/omo-codex/plugin/skills/programming/references/logging.md +91 -0
  116. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +380 -0
  117. package/packages/omo-codex/plugin/skills/ultrawork/agents/openai.yaml +2 -0
  118. package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +5 -2
  119. package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +4 -4
  120. package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +2 -2
  121. package/packages/omo-codex/plugin/skills/ulw-research/ATTRIBUTION.md +2 -2
  122. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +28 -7
  123. package/packages/omo-codex/plugin/test/install-time-build-runtime.test.mjs +1 -1
  124. package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +2 -0
  125. package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +56 -0
  126. package/packages/omo-codex/plugin/test/ulw-research-epistemic-contract.test.mjs +98 -0
  127. package/packages/omo-codex/plugin/test/ulw-research-skill-contract.test.mjs +6 -6
  128. package/packages/omo-codex/scripts/install-dist/install-local.mjs +259 -3954
  129. package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +6 -0
  130. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +10 -1
  131. package/packages/shared-skills/skills/frontend/SKILL.md +8 -3
  132. package/packages/shared-skills/skills/frontend/references/design/README.md +1 -1
  133. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -1
  134. package/packages/shared-skills/skills/frontend/references/design/lazyweb.md +77 -0
  135. package/packages/shared-skills/skills/frontend/references/design/stitch-design-example.md +121 -0
  136. package/packages/shared-skills/skills/programming/SKILL.md +10 -1
  137. package/packages/shared-skills/skills/programming/references/logging.md +91 -0
  138. package/packages/shared-skills/skills/ulw-plan/SKILL.md +5 -5
  139. package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +7 -7
  140. package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +3 -3
  141. package/packages/shared-skills/skills/ulw-research/ATTRIBUTION.md +2 -2
  142. package/packages/shared-skills/skills/ulw-research/SKILL.md +28 -7
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/serve.ts
4
- import { existsSync as existsSync5, realpathSync } from "node:fs";
5
- import { homedir as homedir6 } from "node:os";
6
- import { basename as basename3, join as join6, resolve as resolve2 } from "node:path";
4
+ import { existsSync as existsSync5, realpathSync as realpathSync2 } from "node:fs";
5
+ import { homedir as homedir7 } from "node:os";
6
+ import { basename as basename3, join as join7, resolve as resolve3 } from "node:path";
7
7
  import {
8
8
  cwd as processCwd,
9
9
  env as processEnv,
@@ -17,6 +17,7 @@ import { fileURLToPath } from "node:url";
17
17
  import { homedir } from "node:os";
18
18
  import { join } from "node:path";
19
19
  var CODEGRAPH_INSTALL_DIR_ENV = "CODEGRAPH_INSTALL_DIR";
20
+ var CODEGRAPH_NO_DAEMON_ENV = "CODEGRAPH_NO_DAEMON";
20
21
  var CODEGRAPH_NO_DOWNLOAD_ENV = "CODEGRAPH_NO_DOWNLOAD";
21
22
  var CODEGRAPH_TELEMETRY_ENV = "CODEGRAPH_TELEMETRY";
22
23
  var DO_NOT_TRACK_ENV = "DO_NOT_TRACK";
@@ -50,6 +51,7 @@ var SAFE_CODEGRAPH_RUNTIME_ENV_KEYS = new Set([
50
51
  "CODEGRAPH_ALLOW_UNSAFE_NODE",
51
52
  "CODEGRAPH_BIN",
52
53
  "CODEGRAPH_FAKE_LOG",
54
+ "CODEGRAPH_NO_DAEMON",
53
55
  "CODEGRAPH_NODE_BIN",
54
56
  "OMO_CODEGRAPH_BIN",
55
57
  "OMO_CODEGRAPH_PROJECT_CWD",
@@ -59,6 +61,7 @@ function buildCodegraphEnv(options = {}) {
59
61
  const homeDir = options.homeDir ?? homedir();
60
62
  return {
61
63
  [CODEGRAPH_INSTALL_DIR_ENV]: join(homeDir, ".omo", "codegraph"),
64
+ [CODEGRAPH_NO_DAEMON_ENV]: "1",
62
65
  [CODEGRAPH_NO_DOWNLOAD_ENV]: "1",
63
66
  [CODEGRAPH_TELEMETRY_ENV]: "0",
64
67
  [DO_NOT_TRACK_ENV]: "1"
@@ -537,12 +540,80 @@ function resolveCodegraphCommand(options = {}) {
537
540
  };
538
541
  }
539
542
 
543
+ // ../../../../utils/src/codegraph/exclusion.ts
544
+ import { realpathSync } from "node:fs";
545
+ import { homedir as homedir4, tmpdir as osTmpdir } from "node:os";
546
+ import { isAbsolute, join as join5, resolve } from "node:path";
547
+ var POSIX_DEFAULT_EXCLUDED_ROOTS = ["/tmp", "/private/tmp"];
548
+ function expandHome(path, homeDir) {
549
+ if (path === "~")
550
+ return homeDir;
551
+ if (path.startsWith("~/") || path.startsWith("~\\"))
552
+ return join5(homeDir, path.slice(2));
553
+ return path;
554
+ }
555
+ function realpathIfPossible(path) {
556
+ try {
557
+ return realpathSync(path);
558
+ } catch (error) {
559
+ if (error instanceof Error)
560
+ return resolve(path);
561
+ throw error;
562
+ }
563
+ }
564
+ function resolveConfiguredRoot(path, homeDir) {
565
+ const expanded = expandHome(path, homeDir);
566
+ return realpathIfPossible(isAbsolute(expanded) ? expanded : join5(homeDir, expanded));
567
+ }
568
+ function normalizeForComparison(path, platform) {
569
+ const normalized = path.replaceAll("\\", "/").replace(/\/+$/, "");
570
+ return platform === "win32" ? normalized.toLowerCase() : normalized;
571
+ }
572
+ function pathIsWithin(path, root, platform) {
573
+ const candidate = normalizeForComparison(path, platform);
574
+ const normalizedRoot = normalizeForComparison(root, platform);
575
+ return candidate === normalizedRoot || candidate.startsWith(`${normalizedRoot}/`);
576
+ }
577
+ function hasOmoPathSegment(path) {
578
+ return path.split(/[\\/]+/).includes(".omo");
579
+ }
580
+ function defaultExcludedRoots(platform, tmpdir) {
581
+ return platform === "win32" ? [tmpdir] : [...POSIX_DEFAULT_EXCLUDED_ROOTS, tmpdir];
582
+ }
583
+ function shouldExcludeCodegraphProject(workspace, options = {}) {
584
+ const platform = options.platform ?? process.platform;
585
+ const homeDir = options.homeDir ?? homedir4();
586
+ const tmpdir = options.tmpdir ?? osTmpdir();
587
+ const resolvedWorkspace = realpathIfPossible(resolve(workspace));
588
+ if (hasOmoPathSegment(resolvedWorkspace)) {
589
+ return { excluded: true, matchedRoot: ".omo", reason: "omo-state" };
590
+ }
591
+ for (const root of defaultExcludedRoots(platform, tmpdir)) {
592
+ const resolvedRoot = realpathIfPossible(resolve(root));
593
+ if (pathIsWithin(resolvedWorkspace, resolvedRoot, platform)) {
594
+ return { excluded: true, matchedRoot: root, reason: "tmp-root" };
595
+ }
596
+ }
597
+ for (const root of options.excludedRoots ?? []) {
598
+ const trimmedRoot = root.trim();
599
+ if (trimmedRoot.length === 0)
600
+ continue;
601
+ const resolvedRoot = resolveConfiguredRoot(trimmedRoot, homeDir);
602
+ if (pathIsWithin(resolvedWorkspace, resolvedRoot, platform)) {
603
+ return { excluded: true, matchedRoot: root, reason: "custom-root" };
604
+ }
605
+ }
606
+ return { excluded: false };
607
+ }
540
608
  // ../../shared/src/config-loader.ts
541
- import { homedir as homedir5 } from "node:os";
609
+ import { homedir as homedir6 } from "node:os";
542
610
 
543
611
  // ../../../../utils/src/omo-config/loader.ts
544
- import { existsSync as existsSync4, readFileSync } from "node:fs";
545
- import { homedir as homedir4 } from "node:os";
612
+ import { existsSync as existsSync4 } from "node:fs";
613
+ import { homedir as homedir5 } from "node:os";
614
+
615
+ // ../../../../utils/src/omo-config/body.ts
616
+ import { readFileSync } from "node:fs";
546
617
 
547
618
  // ../../../../utils/src/deep-merge.ts
548
619
  var DANGEROUS_KEYS = new Set(["__proto__", "constructor", "prototype"]);
@@ -1420,127 +1491,13 @@ var HARNESS_IDS = ["codex", "opencode", "omo"];
1420
1491
  var SETTING_HARNESS_SUPPORT = {
1421
1492
  "codegraph.auto_provision": HARNESS_IDS,
1422
1493
  "codegraph.enabled": HARNESS_IDS,
1494
+ "codegraph.excluded_roots": ["codex"],
1423
1495
  "codegraph.install_dir": HARNESS_IDS,
1424
1496
  "codegraph.telemetry": HARNESS_IDS,
1425
1497
  "codegraph.watch_debounce_ms": ["opencode", "omo"]
1426
1498
  };
1427
1499
 
1428
- // ../../../../utils/src/omo-config/env-overrides.ts
1429
- var CODEGRAPH_ENV_KEYS = [
1430
- ["auto_provision", "AUTO_PROVISION", "boolean"],
1431
- ["enabled", "ENABLED", "boolean"],
1432
- ["install_dir", "INSTALL_DIR", "string"],
1433
- ["telemetry", "TELEMETRY", "boolean"],
1434
- ["watch_debounce_ms", "WATCH_DEBOUNCE_MS", "number"]
1435
- ];
1436
- function parseBooleanEnv(value) {
1437
- const normalized = value.trim().toLowerCase();
1438
- if (["1", "true", "yes", "on"].includes(normalized))
1439
- return true;
1440
- if (["0", "false", "no", "off"].includes(normalized))
1441
- return false;
1442
- return null;
1443
- }
1444
- function parseEnvValue(value, kind) {
1445
- if (kind === "boolean")
1446
- return parseBooleanEnv(value);
1447
- if (kind === "number") {
1448
- const parsed = Number(value);
1449
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
1450
- }
1451
- return value;
1452
- }
1453
- function setCodegraphSetting(config, key, value) {
1454
- switch (key) {
1455
- case "auto_provision":
1456
- if (typeof value === "boolean")
1457
- config.auto_provision = value;
1458
- return;
1459
- case "enabled":
1460
- if (typeof value === "boolean")
1461
- config.enabled = value;
1462
- return;
1463
- case "install_dir":
1464
- if (typeof value === "string")
1465
- config.install_dir = value;
1466
- return;
1467
- case "telemetry":
1468
- if (typeof value === "boolean")
1469
- config.telemetry = value;
1470
- return;
1471
- case "watch_debounce_ms":
1472
- if (typeof value === "number")
1473
- config.watch_debounce_ms = value;
1474
- return;
1475
- }
1476
- }
1477
- function buildEnvOverrides(harness, env, warnings, merge) {
1478
- let config = {};
1479
- for (const prefix of ["OMO", harness.toUpperCase()]) {
1480
- const codegraph = {};
1481
- for (const [settingKey, envSuffix, kind] of CODEGRAPH_ENV_KEYS) {
1482
- const envKey = `${prefix}_CODEGRAPH_${envSuffix}`;
1483
- const rawValue = env[envKey];
1484
- if (rawValue === undefined)
1485
- continue;
1486
- const parsed = parseEnvValue(rawValue, kind);
1487
- if (parsed === null) {
1488
- warnings.push(`${envKey} has invalid ${kind} value "${rawValue}"`);
1489
- continue;
1490
- }
1491
- setCodegraphSetting(codegraph, settingKey, parsed);
1492
- }
1493
- if (Object.keys(codegraph).length > 0) {
1494
- config = merge(config, { codegraph });
1495
- }
1496
- }
1497
- return config;
1498
- }
1499
-
1500
- // ../../../../utils/src/omo-config/resolve.ts
1501
- import { existsSync as existsSync3 } from "node:fs";
1502
- import { dirname as dirname2, isAbsolute, join as join5, relative, resolve } from "node:path";
1503
- function containsPath(parent, child) {
1504
- const pathToChild = relative(parent, child);
1505
- return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute(pathToChild);
1506
- }
1507
- function findProjectConfigPathsNearestFirst(cwd, homeDir) {
1508
- const startDir = resolve(cwd);
1509
- const stopBeforeDir = containsPath(resolve(homeDir), startDir) ? resolve(homeDir) : null;
1510
- const paths = [];
1511
- let currentDir = startDir;
1512
- while (true) {
1513
- if (stopBeforeDir !== null && currentDir === stopBeforeDir)
1514
- break;
1515
- const configPath = join5(currentDir, ".omo", "config.jsonc");
1516
- if (existsSync3(configPath)) {
1517
- paths.push(configPath);
1518
- }
1519
- const parentDir = dirname2(currentDir);
1520
- if (parentDir === currentDir)
1521
- break;
1522
- currentDir = parentDir;
1523
- }
1524
- return paths;
1525
- }
1526
- function resolveOmoConfigPaths(options) {
1527
- const globalPath = join5(resolve(options.homeDir), ".omo", "config.jsonc");
1528
- const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
1529
- return [
1530
- { path: globalPath, scope: "global" },
1531
- ...projectPathsFarthestFirst.map((path) => ({ path, scope: "project" }))
1532
- ];
1533
- }
1534
- function toMissingSource(candidate) {
1535
- return {
1536
- exists: false,
1537
- loaded: false,
1538
- path: candidate.path,
1539
- scope: candidate.scope
1540
- };
1541
- }
1542
-
1543
- // ../../../../utils/src/omo-config/loader.ts
1500
+ // ../../../../utils/src/omo-config/body.ts
1544
1501
  var BUILT_IN_DEFAULTS = {
1545
1502
  codegraph: {
1546
1503
  auto_provision: true,
@@ -1552,6 +1509,7 @@ var HARNESS_BLOCK_KEYS = HARNESS_IDS.map((harness) => `[${harness}]`);
1552
1509
  var CODEGRAPH_SETTING_KEYS = [
1553
1510
  "auto_provision",
1554
1511
  "enabled",
1512
+ "excluded_roots",
1555
1513
  "install_dir",
1556
1514
  "telemetry",
1557
1515
  "watch_debounce_ms"
@@ -1590,7 +1548,7 @@ function mergeCodegraphConfig(base, override) {
1590
1548
  for (const key of CODEGRAPH_SETTING_KEYS) {
1591
1549
  if (!hasOwn(merged, key))
1592
1550
  continue;
1593
- setCodegraphSetting2(codegraph, key, merged[key]);
1551
+ setCodegraphSetting(codegraph, key, merged[key]);
1594
1552
  }
1595
1553
  return Object.keys(codegraph).length > 0 ? codegraph : undefined;
1596
1554
  }
@@ -1607,6 +1565,9 @@ function isKnownHarnessBlockKey(key) {
1607
1565
  return HARNESS_BLOCK_KEYS.includes(key);
1608
1566
  }
1609
1567
  function validateCodegraphValue(key, value) {
1568
+ if (key === "excluded_roots") {
1569
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? null : "must be an array of strings";
1570
+ }
1610
1571
  if (key === "install_dir")
1611
1572
  return typeof value === "string" ? null : "must be a string";
1612
1573
  if (key === "watch_debounce_ms") {
@@ -1614,7 +1575,7 @@ function validateCodegraphValue(key, value) {
1614
1575
  }
1615
1576
  return typeof value === "boolean" ? null : "must be a boolean";
1616
1577
  }
1617
- function setCodegraphSetting2(config, key, value) {
1578
+ function setCodegraphSetting(config, key, value) {
1618
1579
  switch (key) {
1619
1580
  case "auto_provision":
1620
1581
  if (typeof value === "boolean")
@@ -1624,6 +1585,11 @@ function setCodegraphSetting2(config, key, value) {
1624
1585
  if (typeof value === "boolean")
1625
1586
  config.enabled = value;
1626
1587
  return;
1588
+ case "excluded_roots":
1589
+ if (Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
1590
+ config.excluded_roots = value;
1591
+ }
1592
+ return;
1627
1593
  case "install_dir":
1628
1594
  if (typeof value === "string")
1629
1595
  config.install_dir = value;
@@ -1654,7 +1620,7 @@ function normalizeCodegraphSection(section, pathPrefix, warnings) {
1654
1620
  warnings.push(`${pathPrefix}.${key} ${error}`);
1655
1621
  continue;
1656
1622
  }
1657
- setCodegraphSetting2(codegraph, key, value);
1623
+ setCodegraphSetting(codegraph, key, value);
1658
1624
  }
1659
1625
  return codegraph;
1660
1626
  }
@@ -1733,9 +1699,131 @@ function validateHarnessApplicability(config, harness) {
1733
1699
  }
1734
1700
  return warnings;
1735
1701
  }
1702
+
1703
+ // ../../../../utils/src/omo-config/env-overrides.ts
1704
+ var CODEGRAPH_ENV_KEYS = [
1705
+ ["auto_provision", "AUTO_PROVISION", "boolean"],
1706
+ ["enabled", "ENABLED", "boolean"],
1707
+ ["install_dir", "INSTALL_DIR", "string"],
1708
+ ["telemetry", "TELEMETRY", "boolean"],
1709
+ ["watch_debounce_ms", "WATCH_DEBOUNCE_MS", "number"]
1710
+ ];
1711
+ function parseBooleanEnv(value) {
1712
+ const normalized = value.trim().toLowerCase();
1713
+ if (["1", "true", "yes", "on"].includes(normalized))
1714
+ return true;
1715
+ if (["0", "false", "no", "off"].includes(normalized))
1716
+ return false;
1717
+ return null;
1718
+ }
1719
+ function parseEnvValue(value, kind) {
1720
+ if (kind === "boolean")
1721
+ return parseBooleanEnv(value);
1722
+ if (kind === "number") {
1723
+ const parsed = Number(value);
1724
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
1725
+ }
1726
+ return value;
1727
+ }
1728
+ function setCodegraphSetting2(config, key, value) {
1729
+ switch (key) {
1730
+ case "auto_provision":
1731
+ if (typeof value === "boolean")
1732
+ config.auto_provision = value;
1733
+ return;
1734
+ case "enabled":
1735
+ if (typeof value === "boolean")
1736
+ config.enabled = value;
1737
+ return;
1738
+ case "excluded_roots":
1739
+ if (Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
1740
+ config.excluded_roots = value;
1741
+ }
1742
+ return;
1743
+ case "install_dir":
1744
+ if (typeof value === "string")
1745
+ config.install_dir = value;
1746
+ return;
1747
+ case "telemetry":
1748
+ if (typeof value === "boolean")
1749
+ config.telemetry = value;
1750
+ return;
1751
+ case "watch_debounce_ms":
1752
+ if (typeof value === "number")
1753
+ config.watch_debounce_ms = value;
1754
+ return;
1755
+ }
1756
+ }
1757
+ function buildEnvOverrides(harness, env, warnings, merge) {
1758
+ let config = {};
1759
+ for (const prefix of ["OMO", harness.toUpperCase()]) {
1760
+ const codegraph = {};
1761
+ for (const [settingKey, envSuffix, kind] of CODEGRAPH_ENV_KEYS) {
1762
+ const envKey = `${prefix}_CODEGRAPH_${envSuffix}`;
1763
+ const rawValue = env[envKey];
1764
+ if (rawValue === undefined)
1765
+ continue;
1766
+ const parsed = parseEnvValue(rawValue, kind);
1767
+ if (parsed === null) {
1768
+ warnings.push(`${envKey} has invalid ${kind} value "${rawValue}"`);
1769
+ continue;
1770
+ }
1771
+ setCodegraphSetting2(codegraph, settingKey, parsed);
1772
+ }
1773
+ if (Object.keys(codegraph).length > 0) {
1774
+ config = merge(config, { codegraph });
1775
+ }
1776
+ }
1777
+ return config;
1778
+ }
1779
+
1780
+ // ../../../../utils/src/omo-config/resolve.ts
1781
+ import { existsSync as existsSync3 } from "node:fs";
1782
+ import { dirname as dirname2, isAbsolute as isAbsolute2, join as join6, relative, resolve as resolve2 } from "node:path";
1783
+ function containsPath(parent, child) {
1784
+ const pathToChild = relative(parent, child);
1785
+ return pathToChild === "" || !pathToChild.startsWith("..") && !isAbsolute2(pathToChild);
1786
+ }
1787
+ function findProjectConfigPathsNearestFirst(cwd, homeDir) {
1788
+ const startDir = resolve2(cwd);
1789
+ const stopBeforeDir = containsPath(resolve2(homeDir), startDir) ? resolve2(homeDir) : null;
1790
+ const paths = [];
1791
+ let currentDir = startDir;
1792
+ while (true) {
1793
+ if (stopBeforeDir !== null && currentDir === stopBeforeDir)
1794
+ break;
1795
+ const configPath = join6(currentDir, ".omo", "config.jsonc");
1796
+ if (existsSync3(configPath)) {
1797
+ paths.push(configPath);
1798
+ }
1799
+ const parentDir = dirname2(currentDir);
1800
+ if (parentDir === currentDir)
1801
+ break;
1802
+ currentDir = parentDir;
1803
+ }
1804
+ return paths;
1805
+ }
1806
+ function resolveOmoConfigPaths(options) {
1807
+ const globalPath = join6(resolve2(options.homeDir), ".omo", "config.jsonc");
1808
+ const projectPathsFarthestFirst = findProjectConfigPathsNearestFirst(options.cwd, options.homeDir).reverse();
1809
+ return [
1810
+ { path: globalPath, scope: "global" },
1811
+ ...projectPathsFarthestFirst.map((path) => ({ path, scope: "project" }))
1812
+ ];
1813
+ }
1814
+ function toMissingSource(candidate) {
1815
+ return {
1816
+ exists: false,
1817
+ loaded: false,
1818
+ path: candidate.path,
1819
+ scope: candidate.scope
1820
+ };
1821
+ }
1822
+
1823
+ // ../../../../utils/src/omo-config/loader.ts
1736
1824
  function loadOmoConfig(options) {
1737
1825
  const cwd = options.cwd ?? process.cwd();
1738
- const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ?? homedir4();
1826
+ const homeDir = options.homeDir ?? process.env["HOME"] ?? process.env["USERPROFILE"] ?? homedir5();
1739
1827
  const env = options.env ?? process.env;
1740
1828
  let config = BUILT_IN_DEFAULTS;
1741
1829
  const sources = [];
@@ -1789,7 +1877,7 @@ function getCodexOmoConfig(options = {}) {
1789
1877
  }
1790
1878
  function resolveHomeDir(options) {
1791
1879
  const env = options.env ?? process.env;
1792
- return options.homeDir ?? env["HOME"] ?? env["USERPROFILE"] ?? homedir5();
1880
+ return options.homeDir ?? env["HOME"] ?? env["USERPROFILE"] ?? homedir6();
1793
1881
  }
1794
1882
 
1795
1883
  // src/mcp-bridge.ts
@@ -2272,11 +2360,13 @@ var CODEGRAPH_SKIP_HINT = `CodeGraph MCP skipped: codegraph binary not found. In
2272
2360
  `;
2273
2361
  var CODEGRAPH_DISABLED_HINT = `CodeGraph MCP skipped: disabled by OMO SOT config. Set [codex].codegraph.enabled=true to enable it.
2274
2362
  `;
2363
+ var CODEGRAPH_EXCLUDED_HINT = `CodeGraph MCP skipped: project excluded by OMO CodeGraph policy.
2364
+ `;
2275
2365
  var CODEGRAPH_VERSION = "1.0.1";
2276
2366
  var PROJECT_CWD_ENV_KEYS = ["OMO_CODEGRAPH_PROJECT_CWD", SESSION_START_CWD_ENV, "PWD"];
2277
2367
  async function runCodegraphServe(options = {}) {
2278
2368
  const env = options.env ?? processEnv;
2279
- const homeDir = options.homeDir ?? homedir6();
2369
+ const homeDir = options.homeDir ?? homedir7();
2280
2370
  const wrapperCwd = options.cwd ?? processCwd();
2281
2371
  const projectCwd = resolveProjectCwd(env, wrapperCwd);
2282
2372
  const config = options.config ?? getCodexOmoConfig({ cwd: projectCwd, env, homeDir });
@@ -2284,6 +2374,14 @@ async function runCodegraphServe(options = {}) {
2284
2374
  if (codegraphConfig.enabled === false) {
2285
2375
  return runUnavailableMcp(CODEGRAPH_DISABLED_HINT, options);
2286
2376
  }
2377
+ const excludedRoots = codegraphConfig.excluded_roots;
2378
+ const exclusion = shouldExcludeCodegraphProject(projectCwd, {
2379
+ homeDir,
2380
+ ...excludedRoots === undefined ? {} : { excludedRoots }
2381
+ });
2382
+ if (exclusion.excluded) {
2383
+ return runUnavailableMcp(CODEGRAPH_EXCLUDED_HINT, options);
2384
+ }
2287
2385
  const trustedInstallDir = config.trustedCodegraphInstallDir;
2288
2386
  const resolutionOptions = {
2289
2387
  env,
@@ -2338,10 +2436,10 @@ async function provisionMissingCodegraph(options) {
2338
2436
  return null;
2339
2437
  if (options.config.auto_provision === false)
2340
2438
  return null;
2341
- const installDir = options.trustedInstallDir ?? join6(options.homeDir, ".omo", "codegraph");
2439
+ const installDir = options.trustedInstallDir ?? join7(options.homeDir, ".omo", "codegraph");
2342
2440
  const result = await options.ensureProvisioned({
2343
2441
  installDir,
2344
- lockDir: join6(installDir, ".locks"),
2442
+ lockDir: join7(installDir, ".locks"),
2345
2443
  version: CODEGRAPH_VERSION
2346
2444
  });
2347
2445
  if (!result.provisioned || result.binPath === undefined)
@@ -2359,7 +2457,7 @@ function looksLikePath2(command) {
2359
2457
  return command.includes("/") || command.includes("\\");
2360
2458
  }
2361
2459
  function codegraphEnvForConfig(trustedInstallDir, homeDir, buildEnv) {
2362
- const env = buildEnv?.({ homeDir }) ?? buildCodegraphEnv({ homeDir });
2460
+ const env = { ...buildEnv?.({ homeDir }) ?? buildCodegraphEnv({ homeDir }), [CODEGRAPH_NO_DAEMON_ENV]: "1" };
2363
2461
  return trustedInstallDir === undefined ? env : { ...env, CODEGRAPH_INSTALL_DIR: trustedInstallDir };
2364
2462
  }
2365
2463
  function resolveProjectCwd(env, fallback) {
@@ -2367,16 +2465,16 @@ function resolveProjectCwd(env, fallback) {
2367
2465
  const candidate = env[key]?.trim();
2368
2466
  if (candidate === undefined || candidate.length === 0)
2369
2467
  continue;
2370
- const resolved = resolve2(candidate);
2468
+ const resolved = resolve3(candidate);
2371
2469
  if (existsSync5(resolved))
2372
2470
  return resolved;
2373
2471
  }
2374
- return resolve2(fallback);
2472
+ return resolve3(fallback);
2375
2473
  }
2376
2474
  function provisionedBinFromInstallDir(installDir) {
2377
2475
  if (installDir === undefined)
2378
2476
  return null;
2379
- const candidate = join6(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
2477
+ const candidate = join7(installDir, "bin", process.platform === "win32" ? "codegraph.cmd" : "codegraph");
2380
2478
  return existsSync5(candidate) ? candidate : null;
2381
2479
  }
2382
2480
  async function runCodegraphServeCli() {
@@ -2396,7 +2494,7 @@ function isDirectInvocation(argvPath) {
2396
2494
  const moduleName = basename3(modulePath);
2397
2495
  if (moduleName !== "serve.js" && moduleName !== "serve.ts")
2398
2496
  return false;
2399
- return realpathSync(resolve2(argvPath)) === realpathSync(modulePath);
2497
+ return realpathSync2(resolve3(argvPath)) === realpathSync2(modulePath);
2400
2498
  }
2401
2499
  export {
2402
2500
  runCodegraphServeCli,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sisyphuslabs/codex-codegraph",
3
- "version": "4.15.1",
3
+ "version": "4.16.0",
4
4
  "description": "Codex plugin MCP wrapper for CodeGraph.",
5
5
  "type": "module",
6
6
  "private": true,
@@ -0,0 +1,29 @@
1
+ import {
2
+ pruneDeadCodegraphProjectStores,
3
+ type PruneCodegraphStoreResult,
4
+ } from "../../../../../utils/src/codegraph/workspace.ts";
5
+
6
+ interface PruneCodegraphProjectStoresBestEffortOptions {
7
+ readonly debugLog?: (message: string) => void;
8
+ readonly prune?: (options: { readonly homeDir: string }) => PruneCodegraphStoreResult;
9
+ }
10
+
11
+ const NON_FATAL_GC_ERROR_CODES = new Set(["EACCES", "EBUSY", "ENOENT", "ENOTEMPTY", "ENOTDIR", "EPERM"]);
12
+
13
+ export function pruneCodegraphProjectStoresBestEffort(
14
+ homeDir: string,
15
+ options: PruneCodegraphProjectStoresBestEffortOptions = {},
16
+ ): void {
17
+ try {
18
+ (options.prune ?? pruneDeadCodegraphProjectStores)({ homeDir });
19
+ } catch (error) {
20
+ if (!isNonFatalCodegraphGcError(error)) throw error;
21
+ options.debugLog?.(`CodeGraph cache GC skipped: ${error.message}`);
22
+ }
23
+ }
24
+
25
+ export function isNonFatalCodegraphGcError(error: unknown): error is Error {
26
+ if (!(error instanceof Error)) return false;
27
+ const code = typeof error === "object" && error !== null && "code" in error ? (error as { readonly code?: unknown }).code : undefined;
28
+ return typeof code === "string" && NON_FATAL_GC_ERROR_CODES.has(code);
29
+ }
@@ -13,16 +13,29 @@ import {
13
13
  type SessionStartWorkerOptions,
14
14
  } from "./hook.js";
15
15
  import { runCodegraphServeCli } from "./serve.js";
16
+ import { runCodegraphSweepCli, type RunCodegraphSweepCliOptions } from "./sweep-cli.js";
16
17
 
17
18
  export interface RunCodegraphCliOptions extends SessionStartHookOptions {
19
+ readonly sweepOptions?: SweepCodegraphZombiesTestOptions;
18
20
  readonly workerOptions?: SessionStartWorkerOptions;
19
21
  }
20
22
 
23
+ type SweepCodegraphZombiesTestOptions = Omit<RunCodegraphSweepCliOptions, "argv" | "env" | "stdout">;
24
+
21
25
  export async function runCodegraphCli(options: RunCodegraphCliOptions = {}): Promise<number> {
22
26
  const argv = options.argv ?? process.argv;
23
27
  const command = argv[2];
24
28
  const subcommand = argv[3];
25
29
 
30
+ if (command === "sweep") {
31
+ return runCodegraphSweepCli({
32
+ ...options.sweepOptions,
33
+ argv,
34
+ ...(options.env === undefined ? {} : { env: options.env }),
35
+ ...(options.stdout === undefined ? {} : { stdout: options.stdout }),
36
+ });
37
+ }
38
+
26
39
  if (command === "hook" && subcommand === "session-start") {
27
40
  return runCodegraphSessionStartHook(options);
28
41
  }
@@ -0,0 +1,25 @@
1
+ import { fileURLToPath } from "node:url";
2
+
3
+ import {
4
+ sweepCodegraphZombies,
5
+ type SweepCodegraphZombiesOptions,
6
+ } from "../../../../../utils/src/codegraph/process-sweep.ts";
7
+
8
+ export async function sweepCodegraphZombiesBestEffort(
9
+ options: Omit<SweepCodegraphZombiesOptions, "pluginRoot">,
10
+ sweep: (options: SweepCodegraphZombiesOptions) => Promise<unknown> | unknown = sweepCodegraphZombies,
11
+ ): Promise<void> {
12
+ try {
13
+ await sweep({
14
+ ...options,
15
+ pluginRoot: defaultPluginRoot(),
16
+ ...(options.log === undefined ? {} : { log: options.log }),
17
+ });
18
+ } catch (error) {
19
+ options.log?.(`CodeGraph zombie sweep skipped: ${error instanceof Error ? error.message : String(error)}`);
20
+ }
21
+ }
22
+
23
+ function defaultPluginRoot(): string {
24
+ return fileURLToPath(new URL("../../..", import.meta.url));
25
+ }
@@ -1,6 +1,7 @@
1
1
  import type { Readable } from "node:stream";
2
2
 
3
3
  import type { CodexOmoConfig as SharedCodexOmoConfig } from "../../../shared/src/config-loader.ts";
4
+ import type { SweepCodegraphZombiesOptions } from "../../../../../utils/src/codegraph/process-sweep.ts";
4
5
  import type { CodegraphProvisionResult as SharedCodegraphProvisionResult } from "../../../../../utils/src/codegraph/provision.ts";
5
6
  import type {
6
7
  CodegraphCommandResolution,
@@ -9,7 +10,7 @@ import type {
9
10
  import type { CodegraphWorkspacePreparation as SharedCodegraphWorkspacePreparation } from "../../../../../utils/src/codegraph/workspace.ts";
10
11
  import type { CodegraphConfig as SharedCodegraphConfig } from "../../../../../utils/src/omo-config.ts";
11
12
 
12
- export type SessionStartAction = "skipped-disabled" | "skipped-initialized" | "spawned";
13
+ export type SessionStartAction = "skipped-disabled" | "skipped-excluded" | "skipped-initialized" | "spawned";
13
14
  export type PostToolUseAction = "emitted-guidance" | "skipped";
14
15
  export type WorkerAction = "failed" | "initialized" | "skipped-disabled" | "skipped-status" | "skipped-unavailable" | "skipped-unsupported-node" | "synced";
15
16
 
@@ -82,6 +83,7 @@ export interface SessionStartHookOptions {
82
83
  }) => Promise<boolean>;
83
84
  readonly stdin?: Readable & { readonly isTTY?: boolean };
84
85
  readonly stdout?: HookStdout;
86
+ readonly sweepZombies?: (options: SweepCodegraphZombiesOptions) => Promise<unknown> | unknown;
85
87
  readonly workerCliPath?: string;
86
88
  }
87
89