@colbymchenry/codegraph-win32-x64 0.9.9 → 1.0.1

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 (313) hide show
  1. package/lib/dist/bin/codegraph.d.ts +1 -0
  2. package/lib/dist/bin/codegraph.d.ts.map +1 -1
  3. package/lib/dist/bin/codegraph.js +394 -10
  4. package/lib/dist/bin/codegraph.js.map +1 -1
  5. package/lib/dist/bin/fatal-handler.d.ts +20 -0
  6. package/lib/dist/bin/fatal-handler.d.ts.map +1 -0
  7. package/lib/dist/bin/fatal-handler.js +118 -0
  8. package/lib/dist/bin/fatal-handler.js.map +1 -0
  9. package/lib/dist/context/index.d.ts.map +1 -1
  10. package/lib/dist/context/index.js +7 -0
  11. package/lib/dist/context/index.js.map +1 -1
  12. package/lib/dist/db/index.d.ts.map +1 -1
  13. package/lib/dist/db/index.js +2 -1
  14. package/lib/dist/db/index.js.map +1 -1
  15. package/lib/dist/db/migrations.d.ts +1 -1
  16. package/lib/dist/db/migrations.d.ts.map +1 -1
  17. package/lib/dist/db/migrations.js +10 -1
  18. package/lib/dist/db/migrations.js.map +1 -1
  19. package/lib/dist/db/queries.d.ts +43 -0
  20. package/lib/dist/db/queries.d.ts.map +1 -1
  21. package/lib/dist/db/queries.js +103 -7
  22. package/lib/dist/db/queries.js.map +1 -1
  23. package/lib/dist/db/schema.sql +1 -0
  24. package/lib/dist/db/sqlite-adapter.d.ts +7 -0
  25. package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
  26. package/lib/dist/db/sqlite-adapter.js +3 -0
  27. package/lib/dist/db/sqlite-adapter.js.map +1 -1
  28. package/lib/dist/directory.d.ts +49 -2
  29. package/lib/dist/directory.d.ts.map +1 -1
  30. package/lib/dist/directory.js +173 -35
  31. package/lib/dist/directory.js.map +1 -1
  32. package/lib/dist/extraction/astro-extractor.d.ts +79 -0
  33. package/lib/dist/extraction/astro-extractor.d.ts.map +1 -0
  34. package/lib/dist/extraction/astro-extractor.js +320 -0
  35. package/lib/dist/extraction/astro-extractor.js.map +1 -0
  36. package/lib/dist/extraction/extraction-version.d.ts +25 -0
  37. package/lib/dist/extraction/extraction-version.d.ts.map +1 -0
  38. package/lib/dist/extraction/extraction-version.js +28 -0
  39. package/lib/dist/extraction/extraction-version.js.map +1 -0
  40. package/lib/dist/extraction/function-ref.d.ts +118 -0
  41. package/lib/dist/extraction/function-ref.d.ts.map +1 -0
  42. package/lib/dist/extraction/function-ref.js +727 -0
  43. package/lib/dist/extraction/function-ref.js.map +1 -0
  44. package/lib/dist/extraction/generated-detection.d.ts.map +1 -1
  45. package/lib/dist/extraction/generated-detection.js +3 -0
  46. package/lib/dist/extraction/generated-detection.js.map +1 -1
  47. package/lib/dist/extraction/grammars.d.ts +7 -1
  48. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  49. package/lib/dist/extraction/grammars.js +52 -4
  50. package/lib/dist/extraction/grammars.js.map +1 -1
  51. package/lib/dist/extraction/index.d.ts +34 -0
  52. package/lib/dist/extraction/index.d.ts.map +1 -1
  53. package/lib/dist/extraction/index.js +389 -62
  54. package/lib/dist/extraction/index.js.map +1 -1
  55. package/lib/dist/extraction/languages/c-cpp.d.ts +8 -0
  56. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  57. package/lib/dist/extraction/languages/c-cpp.js +87 -28
  58. package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
  59. package/lib/dist/extraction/languages/csharp.d.ts +22 -0
  60. package/lib/dist/extraction/languages/csharp.d.ts.map +1 -1
  61. package/lib/dist/extraction/languages/csharp.js +84 -2
  62. package/lib/dist/extraction/languages/csharp.js.map +1 -1
  63. package/lib/dist/extraction/languages/dart.d.ts.map +1 -1
  64. package/lib/dist/extraction/languages/dart.js +161 -1
  65. package/lib/dist/extraction/languages/dart.js.map +1 -1
  66. package/lib/dist/extraction/languages/go.d.ts.map +1 -1
  67. package/lib/dist/extraction/languages/go.js +43 -2
  68. package/lib/dist/extraction/languages/go.js.map +1 -1
  69. package/lib/dist/extraction/languages/index.d.ts.map +1 -1
  70. package/lib/dist/extraction/languages/index.js +2 -0
  71. package/lib/dist/extraction/languages/index.js.map +1 -1
  72. package/lib/dist/extraction/languages/java.d.ts.map +1 -1
  73. package/lib/dist/extraction/languages/java.js +42 -1
  74. package/lib/dist/extraction/languages/java.js.map +1 -1
  75. package/lib/dist/extraction/languages/javascript.d.ts.map +1 -1
  76. package/lib/dist/extraction/languages/javascript.js +16 -0
  77. package/lib/dist/extraction/languages/javascript.js.map +1 -1
  78. package/lib/dist/extraction/languages/kotlin.d.ts.map +1 -1
  79. package/lib/dist/extraction/languages/kotlin.js +69 -0
  80. package/lib/dist/extraction/languages/kotlin.js.map +1 -1
  81. package/lib/dist/extraction/languages/objc.d.ts.map +1 -1
  82. package/lib/dist/extraction/languages/objc.js +42 -0
  83. package/lib/dist/extraction/languages/objc.js.map +1 -1
  84. package/lib/dist/extraction/languages/pascal.d.ts.map +1 -1
  85. package/lib/dist/extraction/languages/pascal.js +11 -0
  86. package/lib/dist/extraction/languages/pascal.js.map +1 -1
  87. package/lib/dist/extraction/languages/php.d.ts.map +1 -1
  88. package/lib/dist/extraction/languages/php.js +90 -1
  89. package/lib/dist/extraction/languages/php.js.map +1 -1
  90. package/lib/dist/extraction/languages/r.d.ts +3 -0
  91. package/lib/dist/extraction/languages/r.d.ts.map +1 -0
  92. package/lib/dist/extraction/languages/r.js +314 -0
  93. package/lib/dist/extraction/languages/r.js.map +1 -0
  94. package/lib/dist/extraction/languages/ruby.d.ts.map +1 -1
  95. package/lib/dist/extraction/languages/ruby.js +35 -0
  96. package/lib/dist/extraction/languages/ruby.js.map +1 -1
  97. package/lib/dist/extraction/languages/rust.d.ts.map +1 -1
  98. package/lib/dist/extraction/languages/rust.js +35 -2
  99. package/lib/dist/extraction/languages/rust.js.map +1 -1
  100. package/lib/dist/extraction/languages/scala.d.ts.map +1 -1
  101. package/lib/dist/extraction/languages/scala.js +61 -1
  102. package/lib/dist/extraction/languages/scala.js.map +1 -1
  103. package/lib/dist/extraction/languages/swift.d.ts.map +1 -1
  104. package/lib/dist/extraction/languages/swift.js +61 -0
  105. package/lib/dist/extraction/languages/swift.js.map +1 -1
  106. package/lib/dist/extraction/languages/typescript.d.ts +13 -0
  107. package/lib/dist/extraction/languages/typescript.d.ts.map +1 -1
  108. package/lib/dist/extraction/languages/typescript.js +38 -0
  109. package/lib/dist/extraction/languages/typescript.js.map +1 -1
  110. package/lib/dist/extraction/liquid-extractor.d.ts +7 -0
  111. package/lib/dist/extraction/liquid-extractor.d.ts.map +1 -1
  112. package/lib/dist/extraction/liquid-extractor.js +53 -9
  113. package/lib/dist/extraction/liquid-extractor.js.map +1 -1
  114. package/lib/dist/extraction/razor-extractor.d.ts +42 -0
  115. package/lib/dist/extraction/razor-extractor.d.ts.map +1 -0
  116. package/lib/dist/extraction/razor-extractor.js +285 -0
  117. package/lib/dist/extraction/razor-extractor.js.map +1 -0
  118. package/lib/dist/extraction/svelte-extractor.d.ts.map +1 -1
  119. package/lib/dist/extraction/svelte-extractor.js +6 -3
  120. package/lib/dist/extraction/svelte-extractor.js.map +1 -1
  121. package/lib/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
  122. package/lib/dist/extraction/tree-sitter-helpers.js +59 -10
  123. package/lib/dist/extraction/tree-sitter-helpers.js.map +1 -1
  124. package/lib/dist/extraction/tree-sitter-types.d.ts +33 -0
  125. package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  126. package/lib/dist/extraction/tree-sitter.d.ts +211 -0
  127. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
  128. package/lib/dist/extraction/tree-sitter.js +1681 -49
  129. package/lib/dist/extraction/tree-sitter.js.map +1 -1
  130. package/lib/dist/extraction/vue-extractor.d.ts +15 -0
  131. package/lib/dist/extraction/vue-extractor.d.ts.map +1 -1
  132. package/lib/dist/extraction/vue-extractor.js +94 -3
  133. package/lib/dist/extraction/vue-extractor.js.map +1 -1
  134. package/lib/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  135. package/lib/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
  136. package/lib/dist/graph/queries.d.ts.map +1 -1
  137. package/lib/dist/graph/queries.js +13 -40
  138. package/lib/dist/graph/queries.js.map +1 -1
  139. package/lib/dist/graph/traversal.d.ts.map +1 -1
  140. package/lib/dist/graph/traversal.js +16 -4
  141. package/lib/dist/graph/traversal.js.map +1 -1
  142. package/lib/dist/index.d.ts +34 -2
  143. package/lib/dist/index.d.ts.map +1 -1
  144. package/lib/dist/index.js +90 -8
  145. package/lib/dist/index.js.map +1 -1
  146. package/lib/dist/installer/index.d.ts.map +1 -1
  147. package/lib/dist/installer/index.js +63 -2
  148. package/lib/dist/installer/index.js.map +1 -1
  149. package/lib/dist/installer/instructions-template.d.ts +34 -11
  150. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  151. package/lib/dist/installer/instructions-template.js +44 -12
  152. package/lib/dist/installer/instructions-template.js.map +1 -1
  153. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  154. package/lib/dist/installer/targets/claude.js +6 -10
  155. package/lib/dist/installer/targets/claude.js.map +1 -1
  156. package/lib/dist/installer/targets/codex.js +4 -6
  157. package/lib/dist/installer/targets/codex.js.map +1 -1
  158. package/lib/dist/installer/targets/gemini.js +4 -6
  159. package/lib/dist/installer/targets/gemini.js.map +1 -1
  160. package/lib/dist/installer/targets/opencode.d.ts +9 -1
  161. package/lib/dist/installer/targets/opencode.d.ts.map +1 -1
  162. package/lib/dist/installer/targets/opencode.js +91 -40
  163. package/lib/dist/installer/targets/opencode.js.map +1 -1
  164. package/lib/dist/installer/targets/shared.d.ts +14 -0
  165. package/lib/dist/installer/targets/shared.d.ts.map +1 -1
  166. package/lib/dist/installer/targets/shared.js +16 -0
  167. package/lib/dist/installer/targets/shared.js.map +1 -1
  168. package/lib/dist/mcp/daemon-manager.d.ts +42 -0
  169. package/lib/dist/mcp/daemon-manager.d.ts.map +1 -0
  170. package/lib/dist/mcp/daemon-manager.js +129 -0
  171. package/lib/dist/mcp/daemon-manager.js.map +1 -0
  172. package/lib/dist/mcp/daemon-registry.d.ts +47 -0
  173. package/lib/dist/mcp/daemon-registry.d.ts.map +1 -0
  174. package/lib/dist/mcp/daemon-registry.js +229 -0
  175. package/lib/dist/mcp/daemon-registry.js.map +1 -0
  176. package/lib/dist/mcp/daemon.d.ts +60 -1
  177. package/lib/dist/mcp/daemon.d.ts.map +1 -1
  178. package/lib/dist/mcp/daemon.js +226 -8
  179. package/lib/dist/mcp/daemon.js.map +1 -1
  180. package/lib/dist/mcp/dynamic-boundaries.d.ts +41 -0
  181. package/lib/dist/mcp/dynamic-boundaries.d.ts.map +1 -0
  182. package/lib/dist/mcp/dynamic-boundaries.js +359 -0
  183. package/lib/dist/mcp/dynamic-boundaries.js.map +1 -0
  184. package/lib/dist/mcp/index.d.ts +1 -0
  185. package/lib/dist/mcp/index.d.ts.map +1 -1
  186. package/lib/dist/mcp/index.js +31 -9
  187. package/lib/dist/mcp/index.js.map +1 -1
  188. package/lib/dist/mcp/liveness-watchdog.d.ts +18 -0
  189. package/lib/dist/mcp/liveness-watchdog.d.ts.map +1 -0
  190. package/lib/dist/mcp/liveness-watchdog.js +207 -0
  191. package/lib/dist/mcp/liveness-watchdog.js.map +1 -0
  192. package/lib/dist/mcp/ppid-watchdog.d.ts +44 -0
  193. package/lib/dist/mcp/ppid-watchdog.d.ts.map +1 -0
  194. package/lib/dist/mcp/ppid-watchdog.js +27 -0
  195. package/lib/dist/mcp/ppid-watchdog.js.map +1 -0
  196. package/lib/dist/mcp/proxy.d.ts +6 -0
  197. package/lib/dist/mcp/proxy.d.ts.map +1 -1
  198. package/lib/dist/mcp/proxy.js +153 -24
  199. package/lib/dist/mcp/proxy.js.map +1 -1
  200. package/lib/dist/mcp/server-instructions.d.ts +12 -1
  201. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  202. package/lib/dist/mcp/server-instructions.js +43 -16
  203. package/lib/dist/mcp/server-instructions.js.map +1 -1
  204. package/lib/dist/mcp/session.d.ts +2 -0
  205. package/lib/dist/mcp/session.d.ts.map +1 -1
  206. package/lib/dist/mcp/session.js +49 -2
  207. package/lib/dist/mcp/session.js.map +1 -1
  208. package/lib/dist/mcp/stdin-teardown.d.ts +27 -0
  209. package/lib/dist/mcp/stdin-teardown.d.ts.map +1 -0
  210. package/lib/dist/mcp/stdin-teardown.js +49 -0
  211. package/lib/dist/mcp/stdin-teardown.js.map +1 -0
  212. package/lib/dist/mcp/tools.d.ts +71 -0
  213. package/lib/dist/mcp/tools.d.ts.map +1 -1
  214. package/lib/dist/mcp/tools.js +703 -85
  215. package/lib/dist/mcp/tools.js.map +1 -1
  216. package/lib/dist/mcp/transport.d.ts.map +1 -1
  217. package/lib/dist/mcp/transport.js +18 -2
  218. package/lib/dist/mcp/transport.js.map +1 -1
  219. package/lib/dist/resolution/callback-synthesizer.d.ts +3 -3
  220. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  221. package/lib/dist/resolution/callback-synthesizer.js +549 -21
  222. package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
  223. package/lib/dist/resolution/frameworks/astro.d.ts +9 -0
  224. package/lib/dist/resolution/frameworks/astro.d.ts.map +1 -0
  225. package/lib/dist/resolution/frameworks/astro.js +169 -0
  226. package/lib/dist/resolution/frameworks/astro.js.map +1 -0
  227. package/lib/dist/resolution/frameworks/expo-modules.d.ts.map +1 -1
  228. package/lib/dist/resolution/frameworks/expo-modules.js +6 -1
  229. package/lib/dist/resolution/frameworks/expo-modules.js.map +1 -1
  230. package/lib/dist/resolution/frameworks/index.d.ts +1 -0
  231. package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
  232. package/lib/dist/resolution/frameworks/index.js +5 -1
  233. package/lib/dist/resolution/frameworks/index.js.map +1 -1
  234. package/lib/dist/resolution/frameworks/java.js +6 -1
  235. package/lib/dist/resolution/frameworks/java.js.map +1 -1
  236. package/lib/dist/resolution/frameworks/python.d.ts.map +1 -1
  237. package/lib/dist/resolution/frameworks/python.js +7 -3
  238. package/lib/dist/resolution/frameworks/python.js.map +1 -1
  239. package/lib/dist/resolution/frameworks/react-native.d.ts.map +1 -1
  240. package/lib/dist/resolution/frameworks/react-native.js +53 -3
  241. package/lib/dist/resolution/frameworks/react-native.js.map +1 -1
  242. package/lib/dist/resolution/frameworks/react.d.ts.map +1 -1
  243. package/lib/dist/resolution/frameworks/react.js +15 -3
  244. package/lib/dist/resolution/frameworks/react.js.map +1 -1
  245. package/lib/dist/resolution/frameworks/svelte.js +5 -1
  246. package/lib/dist/resolution/frameworks/svelte.js.map +1 -1
  247. package/lib/dist/resolution/frameworks/vue.js +24 -27
  248. package/lib/dist/resolution/frameworks/vue.js.map +1 -1
  249. package/lib/dist/resolution/import-resolver.d.ts +10 -0
  250. package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
  251. package/lib/dist/resolution/import-resolver.js +620 -2
  252. package/lib/dist/resolution/import-resolver.js.map +1 -1
  253. package/lib/dist/resolution/index.d.ts +80 -0
  254. package/lib/dist/resolution/index.d.ts.map +1 -1
  255. package/lib/dist/resolution/index.js +457 -7
  256. package/lib/dist/resolution/index.js.map +1 -1
  257. package/lib/dist/resolution/name-matcher.d.ts +61 -0
  258. package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
  259. package/lib/dist/resolution/name-matcher.js +590 -14
  260. package/lib/dist/resolution/name-matcher.js.map +1 -1
  261. package/lib/dist/resolution/types.d.ts +27 -3
  262. package/lib/dist/resolution/types.d.ts.map +1 -1
  263. package/lib/dist/resolution/workspace-packages.d.ts +48 -0
  264. package/lib/dist/resolution/workspace-packages.d.ts.map +1 -0
  265. package/lib/dist/resolution/workspace-packages.js +208 -0
  266. package/lib/dist/resolution/workspace-packages.js.map +1 -0
  267. package/lib/dist/search/query-utils.d.ts +17 -1
  268. package/lib/dist/search/query-utils.d.ts.map +1 -1
  269. package/lib/dist/search/query-utils.js +79 -10
  270. package/lib/dist/search/query-utils.js.map +1 -1
  271. package/lib/dist/sync/watcher.d.ts +124 -32
  272. package/lib/dist/sync/watcher.d.ts.map +1 -1
  273. package/lib/dist/sync/watcher.js +326 -111
  274. package/lib/dist/sync/watcher.js.map +1 -1
  275. package/lib/dist/telemetry/index.d.ts +146 -0
  276. package/lib/dist/telemetry/index.d.ts.map +1 -0
  277. package/lib/dist/telemetry/index.js +544 -0
  278. package/lib/dist/telemetry/index.js.map +1 -0
  279. package/lib/dist/types.d.ts +17 -2
  280. package/lib/dist/types.d.ts.map +1 -1
  281. package/lib/dist/types.js +3 -0
  282. package/lib/dist/types.js.map +1 -1
  283. package/lib/dist/upgrade/index.d.ts +132 -0
  284. package/lib/dist/upgrade/index.d.ts.map +1 -0
  285. package/lib/dist/upgrade/index.js +462 -0
  286. package/lib/dist/upgrade/index.js.map +1 -0
  287. package/lib/dist/utils.d.ts +30 -24
  288. package/lib/dist/utils.d.ts.map +1 -1
  289. package/lib/dist/utils.js +64 -48
  290. package/lib/dist/utils.js.map +1 -1
  291. package/lib/node_modules/.package-lock.json +1 -29
  292. package/lib/package.json +1 -2
  293. package/package.json +1 -1
  294. package/lib/node_modules/chokidar/LICENSE +0 -21
  295. package/lib/node_modules/chokidar/README.md +0 -305
  296. package/lib/node_modules/chokidar/esm/handler.d.ts +0 -90
  297. package/lib/node_modules/chokidar/esm/handler.js +0 -629
  298. package/lib/node_modules/chokidar/esm/index.d.ts +0 -215
  299. package/lib/node_modules/chokidar/esm/index.js +0 -798
  300. package/lib/node_modules/chokidar/esm/package.json +0 -1
  301. package/lib/node_modules/chokidar/handler.d.ts +0 -90
  302. package/lib/node_modules/chokidar/handler.js +0 -635
  303. package/lib/node_modules/chokidar/index.d.ts +0 -215
  304. package/lib/node_modules/chokidar/index.js +0 -804
  305. package/lib/node_modules/chokidar/package.json +0 -69
  306. package/lib/node_modules/readdirp/LICENSE +0 -21
  307. package/lib/node_modules/readdirp/README.md +0 -120
  308. package/lib/node_modules/readdirp/esm/index.d.ts +0 -108
  309. package/lib/node_modules/readdirp/esm/index.js +0 -257
  310. package/lib/node_modules/readdirp/esm/package.json +0 -1
  311. package/lib/node_modules/readdirp/index.d.ts +0 -108
  312. package/lib/node_modules/readdirp/index.js +0 -263
  313. package/lib/node_modules/readdirp/package.json +0 -70
@@ -41,9 +41,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
41
41
  return (mod && mod.__esModule) ? mod : { "default": mod };
42
42
  };
43
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.loadAllGrammars = exports.loadGrammarsForLanguages = exports.initGrammars = exports.getSupportedLanguages = exports.isGrammarLoaded = exports.isLanguageSupported = exports.isSourceFile = exports.detectLanguage = exports.extractFromSource = exports.ExtractionOrchestrator = void 0;
44
+ exports.loadAllGrammars = exports.loadGrammarsForLanguages = exports.initGrammars = exports.getSupportedLanguages = exports.isGrammarLoaded = exports.isLanguageSupported = exports.isSourceFile = exports.detectLanguage = exports.extractFromSource = exports.ExtractionOrchestrator = exports.ScopeIgnore = void 0;
45
45
  exports.hashContent = hashContent;
46
46
  exports.buildDefaultIgnore = buildDefaultIgnore;
47
+ exports.buildScopeIgnore = buildScopeIgnore;
48
+ exports.discoverEmbeddedRepoRoots = discoverEmbeddedRepoRoots;
47
49
  exports.scanDirectory = scanDirectory;
48
50
  exports.scanDirectoryAsync = scanDirectoryAsync;
49
51
  const fs = __importStar(require("fs"));
@@ -53,6 +55,7 @@ const crypto = __importStar(require("crypto"));
53
55
  const child_process_1 = require("child_process");
54
56
  const tree_sitter_1 = require("./tree-sitter");
55
57
  const grammars_1 = require("./grammars");
58
+ const directory_1 = require("../directory");
56
59
  const errors_1 = require("../errors");
57
60
  const utils_1 = require("../utils");
58
61
  const ignore_1 = __importDefault(require("ignore"));
@@ -147,6 +150,74 @@ const DEFAULT_IGNORE_PATTERNS = [
147
150
  'cmake-build-*/', // CLion / CMake build trees
148
151
  'bazel-*/', // Bazel output symlink trees
149
152
  ];
153
+ /** True if `buf` decodes as strict UTF-8 (no invalid byte sequences). */
154
+ function isValidUtf8(buf) {
155
+ try {
156
+ new TextDecoder('utf-8', { fatal: true }).decode(buf);
157
+ return true;
158
+ }
159
+ catch {
160
+ return false;
161
+ }
162
+ }
163
+ /**
164
+ * Read a `.gitignore` and return patterns safe to hand to the `ignore` matcher —
165
+ * never throwing, even when the file isn't real gitignore text. Two failure
166
+ * modes, both seen in the wild (issue #682):
167
+ *
168
+ * - The file isn't valid UTF-8 — e.g. transparently encrypted in place by
169
+ * corporate DLP / endpoint-security software, leaving a UTF-16 header plus
170
+ * ciphertext. None of it is meaningful patterns, so the whole file is skipped.
171
+ * - The file is text but a single line can't be compiled to a regex by the
172
+ * `ignore` library — `\\[` and friends throw "Unterminated character class".
173
+ * Crucially the throw is LAZY (at match time, not `.add()`), so it would
174
+ * otherwise escape mid-scan. That one pattern is dropped; the rest are kept.
175
+ *
176
+ * Either way a warning that NAMES the file is logged (the reporter couldn't tell
177
+ * which `.gitignore` was at fault) and indexing continues instead of aborting.
178
+ * Returns '' when there's nothing usable.
179
+ */
180
+ function readGitignorePatterns(giPath) {
181
+ let buf;
182
+ try {
183
+ buf = fs.readFileSync(giPath);
184
+ }
185
+ catch {
186
+ return ''; // unreadable (permissions / race) — treat as absent
187
+ }
188
+ // A NUL byte never appears in real gitignore text, and a fatal UTF-8 decode
189
+ // catches the rest. Such a file isn't ignore patterns at all.
190
+ if (buf.includes(0) || !isValidUtf8(buf)) {
191
+ (0, errors_1.logWarn)('Ignoring a .gitignore that is not valid UTF-8 text — it may have been encrypted ' +
192
+ 'in place by endpoint-security software. Indexing continues without it.', { file: giPath });
193
+ return '';
194
+ }
195
+ const content = buf.toString('utf-8');
196
+ // Fast path: one `.ignores()` call forces the library to compile EVERY rule,
197
+ // so if it doesn't throw, the whole file is safe to use verbatim.
198
+ try {
199
+ (0, ignore_1.default)().add(content).ignores('.codegraph-probe');
200
+ return content;
201
+ }
202
+ catch {
203
+ // Fall through: a line is uncompilable — keep the good ones, drop the bad.
204
+ }
205
+ const kept = [];
206
+ let dropped = 0;
207
+ for (const line of content.split(/\r?\n/)) {
208
+ try {
209
+ (0, ignore_1.default)().add(line).ignores('.codegraph-probe');
210
+ kept.push(line);
211
+ }
212
+ catch {
213
+ dropped++;
214
+ }
215
+ }
216
+ if (dropped > 0) {
217
+ (0, errors_1.logWarn)(`Skipped ${dropped} unparseable pattern(s) in a .gitignore; the rest are applied.`, { file: giPath });
218
+ }
219
+ return kept.join('\n');
220
+ }
150
221
  /**
151
222
  * An `ignore` matcher seeded with the built-in defaults, merged with the project's
152
223
  * root .gitignore so a negation there (e.g. `!vendor/`) overrides a default. Shared
@@ -156,15 +227,225 @@ const DEFAULT_IGNORE_PATTERNS = [
156
227
  */
157
228
  function buildDefaultIgnore(rootDir) {
158
229
  const ig = (0, ignore_1.default)().add(DEFAULT_IGNORE_PATTERNS);
230
+ const rootGitignore = path.join(rootDir, '.gitignore');
231
+ if (fs.existsSync(rootGitignore))
232
+ ig.add(readGitignorePatterns(rootGitignore));
233
+ return ig;
234
+ }
235
+ /**
236
+ * Defaults-only ignore matcher (no root `.gitignore` merged). Used wherever the
237
+ * parent repo's own ignore rules must NOT apply — inside embedded child repos,
238
+ * whose gitignore semantics their own `git ls-files` already enforced (#514).
239
+ */
240
+ function defaultsOnlyIgnore() {
241
+ return (0, ignore_1.default)().add(DEFAULT_IGNORE_PATTERNS);
242
+ }
243
+ /**
244
+ * List the gitignored DIRECTORIES of a repo (collapsed, trailing-slash form),
245
+ * relative to `repoDir`. These are invisible to every other `git ls-files` /
246
+ * `git status` mode — and in a multi-repo workspace they are exactly where the
247
+ * nested project repos live (a super-repo `.gitignore`s its child repos to keep
248
+ * `git status` quiet; that does not make them third-party code). (#514)
249
+ */
250
+ function listIgnoredDirs(repoDir) {
159
251
  try {
160
- const rootGitignore = path.join(rootDir, '.gitignore');
161
- if (fs.existsSync(rootGitignore))
162
- ig.add(fs.readFileSync(rootGitignore, 'utf-8'));
252
+ const out = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '-i', '--exclude-standard', '--directory'], { cwd: repoDir, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
253
+ return out.split('\0').filter((e) => e.endsWith('/'));
163
254
  }
164
255
  catch {
165
- // Unreadable root .gitignore — the built-in defaults still apply.
256
+ return [];
166
257
  }
167
- return ig;
258
+ }
259
+ /** Max directory depth searched below an ignored dir for nested `.git` roots. */
260
+ const EMBEDDED_REPO_SEARCH_DEPTH = 4;
261
+ /** Max directories examined per search — a huge ignored data dir must never stall a scan/sync. */
262
+ const EMBEDDED_REPO_SEARCH_ENTRIES = 2000;
263
+ /**
264
+ * Classify a directory's `.git` entry for embedded-repo discovery.
265
+ *
266
+ * - A `.git` **directory** is an embedded clone — distinct first-party code a
267
+ * super-repo merely hides from git; index it (#193, #514).
268
+ * - A `.git` **file** is a pointer (`gitdir: …`). A git **worktree** points into
269
+ * the host repo's own `.git/worktrees/<name>`, so it is a second working view
270
+ * of a repo CodeGraph already indexes — indexing it just duplicates the whole
271
+ * graph N times; skip it (#848). A **submodule** points into `.git/modules/`
272
+ * and is distinct code, so index it as before.
273
+ *
274
+ * Returns `'none'` when there is no `.git` entry here.
275
+ */
276
+ function classifyGitDir(absDir) {
277
+ let st;
278
+ try {
279
+ st = fs.statSync(path.join(absDir, '.git'));
280
+ }
281
+ catch {
282
+ return 'none';
283
+ }
284
+ if (st.isDirectory())
285
+ return 'embedded';
286
+ if (!st.isFile())
287
+ return 'none';
288
+ try {
289
+ const gitdir = fs.readFileSync(path.join(absDir, '.git'), 'utf8').match(/^gitdir:\s*(.+)$/m)?.[1]?.trim();
290
+ // A linked worktree's gitdir lives under some repo's `.git/worktrees/`.
291
+ // Match both separators so a Windows-style pointer is recognized too.
292
+ if (gitdir && /(^|[\\/])\.git[\\/]worktrees[\\/]/.test(gitdir))
293
+ return 'worktree';
294
+ }
295
+ catch {
296
+ // Unreadable `.git` pointer — fall back to the prior "index it" behavior.
297
+ }
298
+ return 'embedded';
299
+ }
300
+ /**
301
+ * Find git repositories nested under `absDir` (inclusive), shallow bounded BFS.
302
+ * Stops descending at each repo root found — contents belong to that repo's own
303
+ * enumeration. Skips default-ignored dirs (`node_modules` can contain `.git`
304
+ * from npm git-dependencies — that never makes it project code) and CodeGraph
305
+ * data dirs. Depth- and entry-capped so a huge ignored tree can't stall the scan.
306
+ */
307
+ function findNestedGitRepos(absDir, relPrefix) {
308
+ const found = [];
309
+ const defaults = defaultsOnlyIgnore();
310
+ const queue = [
311
+ { abs: absDir, rel: relPrefix, depth: 0 },
312
+ ];
313
+ let examined = 0;
314
+ while (queue.length > 0) {
315
+ const { abs, rel, depth } = queue.shift();
316
+ if (++examined > EMBEDDED_REPO_SEARCH_ENTRIES) {
317
+ (0, errors_1.logDebug)('Embedded-repo search entry cap hit — deeper repos (if any) not discovered', { under: relPrefix });
318
+ break;
319
+ }
320
+ const cls = classifyGitDir(abs);
321
+ if (cls === 'worktree') {
322
+ continue; // a git worktree duplicates an already-indexed repo (#848) — skip
323
+ }
324
+ if (cls === 'embedded') {
325
+ found.push(rel);
326
+ continue; // its own git handles everything below
327
+ }
328
+ if (depth >= EMBEDDED_REPO_SEARCH_DEPTH)
329
+ continue;
330
+ let entries;
331
+ try {
332
+ entries = fs.readdirSync(abs, { withFileTypes: true });
333
+ }
334
+ catch {
335
+ continue;
336
+ }
337
+ for (const entry of entries) {
338
+ if (!entry.isDirectory())
339
+ continue;
340
+ if (entry.name === '.git' || (0, directory_1.isCodeGraphDataDir)(entry.name))
341
+ continue;
342
+ const childRel = rel + entry.name + '/';
343
+ if (defaults.ignores(childRel))
344
+ continue;
345
+ queue.push({ abs: path.join(abs, entry.name), rel: childRel, depth: depth + 1 });
346
+ }
347
+ }
348
+ return found;
349
+ }
350
+ /**
351
+ * Workspace-scope ignore matcher. Ordinary paths get the root's matcher
352
+ * (built-in defaults + root `.gitignore`); paths inside an EMBEDDED repo get
353
+ * that repo's own matcher (defaults + its root `.gitignore`) — the parent's
354
+ * `.gitignore` hides a child repo from git, not from the index (#514). A
355
+ * directory path (trailing slash) that is an ANCESTOR of an embedded root is
356
+ * never ignored, so directory-pruning callers (the Linux per-directory
357
+ * watcher) still descend to reach the embedded repos.
358
+ *
359
+ * Single source of truth for indexer and watcher scope — they must not diverge.
360
+ */
361
+ class ScopeIgnore {
362
+ rootMatcher;
363
+ embedded;
364
+ defaults = defaultsOnlyIgnore();
365
+ constructor(rootMatcher, embedded) {
366
+ this.rootMatcher = rootMatcher;
367
+ // Longest root first so paths in nested embedded repos hit the innermost matcher.
368
+ this.embedded = [...embedded].sort((a, b) => b.root.length - a.root.length);
369
+ }
370
+ ignores(rel) {
371
+ for (const { root, matcher } of this.embedded) {
372
+ if (rel.startsWith(root)) {
373
+ const inner = rel.slice(root.length);
374
+ if (inner === '')
375
+ return false;
376
+ // Built-in defaults apply to the FULL path uniformly (#407) — an
377
+ // embedded repo inside node_modules (an npm git-dependency) must stay
378
+ // excluded even though its own rules wouldn't ignore its files.
379
+ return this.defaults.ignores(rel) || matcher.ignores(inner);
380
+ }
381
+ }
382
+ // Never prune a directory that leads to an embedded repo.
383
+ if (rel.endsWith('/') && this.embedded.some(({ root }) => root.startsWith(rel))) {
384
+ return false;
385
+ }
386
+ return this.rootMatcher.ignores(rel);
387
+ }
388
+ }
389
+ exports.ScopeIgnore = ScopeIgnore;
390
+ /**
391
+ * Build the workspace-scope matcher. When the caller already knows the
392
+ * embedded roots (the scanner discovers them during collection), pass them to
393
+ * skip rediscovery; otherwise they're discovered here (the watcher path).
394
+ */
395
+ function buildScopeIgnore(rootDir, embeddedRoots) {
396
+ const roots = embeddedRoots ? [...embeddedRoots] : discoverEmbeddedRepoRoots(rootDir);
397
+ return new ScopeIgnore(buildDefaultIgnore(rootDir), roots.map((root) => ({ root, matcher: buildDefaultIgnore(path.join(rootDir, root)) })));
398
+ }
399
+ /**
400
+ * Standalone discovery of every embedded repo root under `rootDir` (relative,
401
+ * trailing-slashed) — both the untracked kind (#193) and the gitignored kind
402
+ * (#514), recursively (an embedded repo can embed further repos). Returns []
403
+ * for non-git roots: the filesystem walk handles nested repos there already.
404
+ */
405
+ function discoverEmbeddedRepoRoots(rootDir) {
406
+ try {
407
+ (0, child_process_1.execFileSync)('git', ['rev-parse', '--git-dir'], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
408
+ }
409
+ catch {
410
+ return [];
411
+ }
412
+ const out = [];
413
+ const defaults = defaultsOnlyIgnore();
414
+ const visit = (repoAbs, prefix) => {
415
+ const candidates = [];
416
+ try {
417
+ const o = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '--exclude-standard', '--directory'], { cwd: repoAbs, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
418
+ for (const e of o.split('\0')) {
419
+ if (e.endsWith('/') && !defaults.ignores(e)) {
420
+ candidates.push(...findNestedGitRepos(path.join(repoAbs, e), e));
421
+ }
422
+ }
423
+ }
424
+ catch { /* untracked listing failed — ignored-side discovery still runs */ }
425
+ candidates.push(...findIgnoredEmbeddedRepos(repoAbs));
426
+ for (const rel of candidates) {
427
+ const full = (0, utils_1.normalizePath)(prefix + rel);
428
+ out.push(full);
429
+ visit(path.join(repoAbs, rel), full);
430
+ }
431
+ };
432
+ visit(rootDir, '');
433
+ return out;
434
+ }
435
+ /**
436
+ * Discover embedded repos hidden by `repoDir`'s OWN ignore rules: for each
437
+ * gitignored directory (skipping built-in default excludes), search for nested
438
+ * `.git` roots. Returns repo paths relative to `repoDir`, trailing-slashed.
439
+ */
440
+ function findIgnoredEmbeddedRepos(repoDir) {
441
+ const defaults = defaultsOnlyIgnore();
442
+ const repos = [];
443
+ for (const dir of listIgnoredDirs(repoDir)) {
444
+ if (defaults.ignores(dir))
445
+ continue;
446
+ repos.push(...findNestedGitRepos(path.join(repoDir, dir), dir));
447
+ }
448
+ return repos;
168
449
  }
169
450
  /**
170
451
  * Collect git-visible files (tracked + untracked, .gitignore-respected) from the
@@ -177,41 +458,57 @@ function buildDefaultIgnore(rootDir) {
177
458
  * skips them entirely, and untracked output reports them only as an opaque
178
459
  * "subdir/" entry (trailing slash) rather than expanding their files. Each
179
460
  * embedded repo is its own git boundary, so we re-run `git ls-files` inside it.
180
- * (See issue #193.)
461
+ * (See issue #193.) GITIGNORED embedded repos are invisible even to that —
462
+ * they're discovered separately via `findIgnoredEmbeddedRepos` (#514); every
463
+ * embedded repo root (however found) is recorded in `embeddedRoots` so callers
464
+ * can exempt its files from the parent's own gitignore rules.
181
465
  */
182
- function collectGitFiles(repoDir, prefix, files) {
466
+ function collectGitFiles(repoDir, prefix, files, embeddedRoots) {
183
467
  const gitOpts = { cwd: repoDir, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true };
184
468
  // Tracked files. --recurse-submodules pulls in files from active submodules,
185
469
  // which the index would otherwise represent only as a commit pointer.
186
470
  // Without this, monorepos using submodules index 0 files. (See issue #147.)
187
471
  // Note: --recurse-submodules only supports -c/--cached and --stage modes — it
188
472
  // can't be combined with -o, so untracked files are gathered separately below.
189
- const tracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-c', '--recurse-submodules'], gitOpts);
190
- for (const line of tracked.split('\n')) {
191
- const trimmed = line.trim();
192
- if (trimmed) {
193
- files.add((0, utils_1.normalizePath)(prefix + trimmed));
194
- }
473
+ // -z gives NUL-separated, unquoted output so non-ASCII (e.g. CJK) paths
474
+ // survive verbatim. Without it git octal-escapes and double-quotes such paths
475
+ // (the core.quotepath default), and the quoted form never matches a real file
476
+ // on disk → those files are silently dropped from the index. (#541)
477
+ const tracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-c', '--recurse-submodules'], gitOpts);
478
+ for (const rel of tracked.split('\0')) {
479
+ if (rel)
480
+ files.add((0, utils_1.normalizePath)(prefix + rel));
195
481
  }
196
482
  // Untracked files (submodules manage their own untracked state). Embedded git
197
483
  // repos surface here as a single "subdir/" entry that git refuses to descend
198
484
  // into — recurse into those as their own repos so their source gets indexed.
199
- const untracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-o', '--exclude-standard'], gitOpts);
200
- for (const line of untracked.split('\n')) {
201
- const trimmed = line.trim();
202
- if (!trimmed)
485
+ const untracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '--exclude-standard'], gitOpts);
486
+ for (const rel of untracked.split('\0')) {
487
+ if (!rel)
203
488
  continue;
204
- if (trimmed.endsWith('/')) {
489
+ if (rel.endsWith('/')) {
205
490
  // git only emits a trailing-slash directory entry for an embedded repo.
206
491
  // Guard with a .git check anyway, and skip anything else exactly as git
207
- // itself skips it (we never descend into a non-repo opaque dir).
208
- const childDir = path.join(repoDir, trimmed);
209
- if (fs.existsSync(path.join(childDir, '.git'))) {
210
- collectGitFiles(childDir, prefix + trimmed, files);
492
+ // itself skips it (we never descend into a non-repo opaque dir). Never
493
+ // descend into default-ignored locations — an embedded repo inside
494
+ // node_modules is an npm git-dependency, not project code.
495
+ const childDir = path.join(repoDir, rel);
496
+ // A git worktree surfaces here as an opaque untracked dir too — skip it,
497
+ // it's a duplicate working view of an already-indexed repo (#848).
498
+ if (classifyGitDir(childDir) === 'embedded' && !defaultsOnlyIgnore().ignores(rel)) {
499
+ embeddedRoots?.add((0, utils_1.normalizePath)(prefix + rel));
500
+ collectGitFiles(childDir, prefix + rel, files, embeddedRoots);
211
501
  }
212
502
  continue;
213
503
  }
214
- files.add((0, utils_1.normalizePath)(prefix + trimmed));
504
+ files.add((0, utils_1.normalizePath)(prefix + rel));
505
+ }
506
+ // Embedded repos hidden by THIS repo's ignore rules (`/packages/` in a
507
+ // super-repo .gitignore) never appear in any listing above — discover and
508
+ // recurse into them too. (#514)
509
+ for (const rel of findIgnoredEmbeddedRepos(repoDir)) {
510
+ embeddedRoots?.add((0, utils_1.normalizePath)(prefix + rel));
511
+ collectGitFiles(path.join(repoDir, rel), prefix + rel, files, embeddedRoots);
215
512
  }
216
513
  }
217
514
  /**
@@ -238,11 +535,15 @@ function getGitVisibleFiles(rootDir) {
238
535
  }
239
536
  }
240
537
  const files = new Set();
241
- collectGitFiles(rootDir, '', files);
538
+ const embeddedRoots = new Set();
539
+ collectGitFiles(rootDir, '', files, embeddedRoots);
242
540
  // Apply built-in default ignores uniformly — to tracked files too, since
243
541
  // committing a dependency/build dir doesn't make it project code. A
244
542
  // `.gitignore` negation (e.g. `!vendor/`) is the explicit opt-in. (issue #407)
245
- const ig = buildDefaultIgnore(rootDir);
543
+ // Files inside an EMBEDDED repo are matched against that repo's own rules,
544
+ // not the parent's: the parent's .gitignore hides the child repo from git,
545
+ // not from the index. (#514)
546
+ const ig = buildScopeIgnore(rootDir, embeddedRoots);
246
547
  return new Set([...files].filter((f) => !ig.ignores(f)));
247
548
  }
248
549
  catch {
@@ -252,38 +553,65 @@ function getGitVisibleFiles(rootDir) {
252
553
  /**
253
554
  * Use `git status` to detect changed files instead of scanning every file.
254
555
  * Returns null on failure so callers fall back to full scan.
556
+ *
557
+ * Recurses into embedded repos — both the untracked kind (#193: the parent's
558
+ * status collapses them to an opaque `?? subdir/` entry) and the gitignored
559
+ * kind (#514: they never appear in the parent's status at all) — running
560
+ * `git status` inside each, so changes in a multi-repo workspace sync without
561
+ * a full rescan. Deleting an ENTIRE embedded repo dir is the one case this
562
+ * cannot see (the child status that would report the deletions is gone with
563
+ * it); a full `codegraph index` reconciles that.
255
564
  */
256
565
  function getGitChangedFiles(rootDir) {
257
566
  try {
258
- const output = (0, child_process_1.execFileSync)('git', ['status', '--porcelain', '--no-renames'], { cwd: rootDir, encoding: 'utf-8', timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
259
- const modified = [];
260
- const added = [];
261
- const deleted = [];
262
- for (const line of output.split('\n')) {
263
- if (line.length < 4)
264
- continue; // Minimum: "XY file"
265
- const statusCode = line.substring(0, 2);
266
- const filePath = (0, utils_1.normalizePath)(line.substring(3));
267
- // Skip non-source files (git status already omits .gitignored paths).
268
- if (!(0, grammars_1.isSourceFile)(filePath))
269
- continue;
270
- if (statusCode === '??') {
271
- added.push(filePath);
272
- }
273
- else if (statusCode.includes('D')) {
274
- deleted.push(filePath);
275
- }
276
- else {
277
- // M, MM, AM, A (staged), etc. — treat as modified
278
- modified.push(filePath);
279
- }
280
- }
281
- return { modified, added, deleted };
567
+ const changes = { modified: [], added: [], deleted: [] };
568
+ collectGitStatus(rootDir, '', changes);
569
+ return changes;
282
570
  }
283
571
  catch {
284
572
  return null;
285
573
  }
286
574
  }
575
+ function collectGitStatus(repoDir, prefix, out) {
576
+ const output = (0, child_process_1.execFileSync)('git', ['status', '--porcelain', '--no-renames'], { cwd: repoDir, encoding: 'utf-8', timeout: 10000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
577
+ const untrackedDirs = [];
578
+ for (const line of output.split('\n')) {
579
+ if (line.length < 4)
580
+ continue; // Minimum: "XY file"
581
+ const statusCode = line.substring(0, 2);
582
+ const rel = (0, utils_1.normalizePath)(line.substring(3));
583
+ // Untracked directory entries (trailing slash) may hide an embedded repo —
584
+ // collect for the recursion below instead of treating as a file.
585
+ if (statusCode === '??' && rel.endsWith('/')) {
586
+ untrackedDirs.push(rel);
587
+ continue;
588
+ }
589
+ const filePath = (0, utils_1.normalizePath)(prefix + rel);
590
+ // Skip non-source files (git status already omits .gitignored paths).
591
+ if (!(0, grammars_1.isSourceFile)(filePath))
592
+ continue;
593
+ if (statusCode === '??') {
594
+ out.added.push(filePath);
595
+ }
596
+ else if (statusCode.includes('D')) {
597
+ out.deleted.push(filePath);
598
+ }
599
+ else {
600
+ // M, MM, AM, A (staged), etc. — treat as modified
601
+ out.modified.push(filePath);
602
+ }
603
+ }
604
+ // Recurse embedded repos found under untracked dirs (at the dir itself or
605
+ // nested deeper) and under this repo's gitignored dirs.
606
+ for (const rel of untrackedDirs) {
607
+ for (const repoRel of findNestedGitRepos(path.join(repoDir, rel), rel)) {
608
+ collectGitStatus(path.join(repoDir, repoRel), prefix + repoRel, out);
609
+ }
610
+ }
611
+ for (const rel of findIgnoredEmbeddedRepos(repoDir)) {
612
+ collectGitStatus(path.join(repoDir, rel), prefix + rel, out);
613
+ }
614
+ }
287
615
  /**
288
616
  * Recursively scan a directory for source files.
289
617
  *
@@ -341,16 +669,14 @@ function scanDirectoryWalk(rootDir, onProgress) {
341
669
  let count = 0;
342
670
  const visitedDirs = new Set();
343
671
  const loadIgnore = (dir) => {
344
- try {
345
- const giPath = path.join(dir, '.gitignore');
346
- if (fs.existsSync(giPath)) {
347
- return { dir, ig: (0, ignore_1.default)().add(fs.readFileSync(giPath, 'utf-8')) };
348
- }
349
- }
350
- catch {
351
- // Unreadable .gitignore treat as absent.
352
- }
353
- return null;
672
+ const giPath = path.join(dir, '.gitignore');
673
+ if (!fs.existsSync(giPath))
674
+ return null;
675
+ // readGitignorePatterns is defensive: a non-UTF-8 (DLP-encrypted) or
676
+ // uncompilable .gitignore is skipped/filtered with a warning, never thrown
677
+ // (issue #682) — so the per-file `.ignores()` calls below can't crash.
678
+ const patterns = readGitignorePatterns(giPath);
679
+ return patterns ? { dir, ig: (0, ignore_1.default)().add(patterns) } : null;
354
680
  };
355
681
  const isIgnored = (fullPath, isDir, matchers) => {
356
682
  for (const { dir, ig } of matchers) {
@@ -392,8 +718,9 @@ function scanDirectoryWalk(rootDir, onProgress) {
392
718
  return;
393
719
  }
394
720
  for (const entry of entries) {
395
- // Never descend into git internals or our own data directory.
396
- if (entry.name === '.git' || entry.name === '.codegraph')
721
+ // Never descend into git internals or any CodeGraph data directory
722
+ // (the active one or a sibling another environment created — #636).
723
+ if (entry.name === '.git' || (0, directory_1.isCodeGraphDataDir)(entry.name))
397
724
  continue;
398
725
  const fullPath = path.join(dir, entry.name);
399
726
  const relativePath = (0, utils_1.normalizePath)(path.relative(rootDir, fullPath));