@colbymchenry/codegraph-darwin-x64 0.9.9 → 1.0.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 (296) 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 +246 -3
  4. package/lib/dist/bin/codegraph.js.map +1 -1
  5. package/lib/dist/context/index.d.ts.map +1 -1
  6. package/lib/dist/context/index.js +7 -0
  7. package/lib/dist/context/index.js.map +1 -1
  8. package/lib/dist/db/index.d.ts.map +1 -1
  9. package/lib/dist/db/index.js +2 -1
  10. package/lib/dist/db/index.js.map +1 -1
  11. package/lib/dist/db/migrations.d.ts +1 -1
  12. package/lib/dist/db/migrations.d.ts.map +1 -1
  13. package/lib/dist/db/migrations.js +10 -1
  14. package/lib/dist/db/migrations.js.map +1 -1
  15. package/lib/dist/db/queries.d.ts +43 -0
  16. package/lib/dist/db/queries.d.ts.map +1 -1
  17. package/lib/dist/db/queries.js +103 -7
  18. package/lib/dist/db/queries.js.map +1 -1
  19. package/lib/dist/db/schema.sql +1 -0
  20. package/lib/dist/db/sqlite-adapter.d.ts +7 -0
  21. package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
  22. package/lib/dist/db/sqlite-adapter.js +3 -0
  23. package/lib/dist/db/sqlite-adapter.js.map +1 -1
  24. package/lib/dist/directory.d.ts +34 -2
  25. package/lib/dist/directory.d.ts.map +1 -1
  26. package/lib/dist/directory.js +129 -35
  27. package/lib/dist/directory.js.map +1 -1
  28. package/lib/dist/extraction/astro-extractor.d.ts +79 -0
  29. package/lib/dist/extraction/astro-extractor.d.ts.map +1 -0
  30. package/lib/dist/extraction/astro-extractor.js +320 -0
  31. package/lib/dist/extraction/astro-extractor.js.map +1 -0
  32. package/lib/dist/extraction/extraction-version.d.ts +25 -0
  33. package/lib/dist/extraction/extraction-version.d.ts.map +1 -0
  34. package/lib/dist/extraction/extraction-version.js +28 -0
  35. package/lib/dist/extraction/extraction-version.js.map +1 -0
  36. package/lib/dist/extraction/function-ref.d.ts +118 -0
  37. package/lib/dist/extraction/function-ref.d.ts.map +1 -0
  38. package/lib/dist/extraction/function-ref.js +727 -0
  39. package/lib/dist/extraction/function-ref.js.map +1 -0
  40. package/lib/dist/extraction/generated-detection.d.ts.map +1 -1
  41. package/lib/dist/extraction/generated-detection.js +3 -0
  42. package/lib/dist/extraction/generated-detection.js.map +1 -1
  43. package/lib/dist/extraction/grammars.d.ts +7 -1
  44. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  45. package/lib/dist/extraction/grammars.js +52 -4
  46. package/lib/dist/extraction/grammars.js.map +1 -1
  47. package/lib/dist/extraction/index.d.ts +34 -0
  48. package/lib/dist/extraction/index.d.ts.map +1 -1
  49. package/lib/dist/extraction/index.js +346 -62
  50. package/lib/dist/extraction/index.js.map +1 -1
  51. package/lib/dist/extraction/languages/c-cpp.d.ts +8 -0
  52. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  53. package/lib/dist/extraction/languages/c-cpp.js +87 -28
  54. package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
  55. package/lib/dist/extraction/languages/csharp.d.ts +22 -0
  56. package/lib/dist/extraction/languages/csharp.d.ts.map +1 -1
  57. package/lib/dist/extraction/languages/csharp.js +84 -2
  58. package/lib/dist/extraction/languages/csharp.js.map +1 -1
  59. package/lib/dist/extraction/languages/dart.d.ts.map +1 -1
  60. package/lib/dist/extraction/languages/dart.js +161 -1
  61. package/lib/dist/extraction/languages/dart.js.map +1 -1
  62. package/lib/dist/extraction/languages/go.d.ts.map +1 -1
  63. package/lib/dist/extraction/languages/go.js +43 -2
  64. package/lib/dist/extraction/languages/go.js.map +1 -1
  65. package/lib/dist/extraction/languages/index.d.ts.map +1 -1
  66. package/lib/dist/extraction/languages/index.js +2 -0
  67. package/lib/dist/extraction/languages/index.js.map +1 -1
  68. package/lib/dist/extraction/languages/java.d.ts.map +1 -1
  69. package/lib/dist/extraction/languages/java.js +42 -1
  70. package/lib/dist/extraction/languages/java.js.map +1 -1
  71. package/lib/dist/extraction/languages/javascript.d.ts.map +1 -1
  72. package/lib/dist/extraction/languages/javascript.js +16 -0
  73. package/lib/dist/extraction/languages/javascript.js.map +1 -1
  74. package/lib/dist/extraction/languages/kotlin.d.ts.map +1 -1
  75. package/lib/dist/extraction/languages/kotlin.js +69 -0
  76. package/lib/dist/extraction/languages/kotlin.js.map +1 -1
  77. package/lib/dist/extraction/languages/objc.d.ts.map +1 -1
  78. package/lib/dist/extraction/languages/objc.js +42 -0
  79. package/lib/dist/extraction/languages/objc.js.map +1 -1
  80. package/lib/dist/extraction/languages/pascal.d.ts.map +1 -1
  81. package/lib/dist/extraction/languages/pascal.js +11 -0
  82. package/lib/dist/extraction/languages/pascal.js.map +1 -1
  83. package/lib/dist/extraction/languages/php.d.ts.map +1 -1
  84. package/lib/dist/extraction/languages/php.js +90 -1
  85. package/lib/dist/extraction/languages/php.js.map +1 -1
  86. package/lib/dist/extraction/languages/r.d.ts +3 -0
  87. package/lib/dist/extraction/languages/r.d.ts.map +1 -0
  88. package/lib/dist/extraction/languages/r.js +314 -0
  89. package/lib/dist/extraction/languages/r.js.map +1 -0
  90. package/lib/dist/extraction/languages/ruby.d.ts.map +1 -1
  91. package/lib/dist/extraction/languages/ruby.js +35 -0
  92. package/lib/dist/extraction/languages/ruby.js.map +1 -1
  93. package/lib/dist/extraction/languages/rust.d.ts.map +1 -1
  94. package/lib/dist/extraction/languages/rust.js +35 -2
  95. package/lib/dist/extraction/languages/rust.js.map +1 -1
  96. package/lib/dist/extraction/languages/scala.d.ts.map +1 -1
  97. package/lib/dist/extraction/languages/scala.js +61 -1
  98. package/lib/dist/extraction/languages/scala.js.map +1 -1
  99. package/lib/dist/extraction/languages/swift.d.ts.map +1 -1
  100. package/lib/dist/extraction/languages/swift.js +61 -0
  101. package/lib/dist/extraction/languages/swift.js.map +1 -1
  102. package/lib/dist/extraction/languages/typescript.d.ts +13 -0
  103. package/lib/dist/extraction/languages/typescript.d.ts.map +1 -1
  104. package/lib/dist/extraction/languages/typescript.js +38 -0
  105. package/lib/dist/extraction/languages/typescript.js.map +1 -1
  106. package/lib/dist/extraction/liquid-extractor.d.ts +7 -0
  107. package/lib/dist/extraction/liquid-extractor.d.ts.map +1 -1
  108. package/lib/dist/extraction/liquid-extractor.js +53 -9
  109. package/lib/dist/extraction/liquid-extractor.js.map +1 -1
  110. package/lib/dist/extraction/razor-extractor.d.ts +42 -0
  111. package/lib/dist/extraction/razor-extractor.d.ts.map +1 -0
  112. package/lib/dist/extraction/razor-extractor.js +285 -0
  113. package/lib/dist/extraction/razor-extractor.js.map +1 -0
  114. package/lib/dist/extraction/svelte-extractor.d.ts.map +1 -1
  115. package/lib/dist/extraction/svelte-extractor.js +6 -3
  116. package/lib/dist/extraction/svelte-extractor.js.map +1 -1
  117. package/lib/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
  118. package/lib/dist/extraction/tree-sitter-helpers.js +59 -10
  119. package/lib/dist/extraction/tree-sitter-helpers.js.map +1 -1
  120. package/lib/dist/extraction/tree-sitter-types.d.ts +33 -0
  121. package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  122. package/lib/dist/extraction/tree-sitter.d.ts +211 -0
  123. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
  124. package/lib/dist/extraction/tree-sitter.js +1681 -49
  125. package/lib/dist/extraction/tree-sitter.js.map +1 -1
  126. package/lib/dist/extraction/vue-extractor.d.ts +15 -0
  127. package/lib/dist/extraction/vue-extractor.d.ts.map +1 -1
  128. package/lib/dist/extraction/vue-extractor.js +94 -3
  129. package/lib/dist/extraction/vue-extractor.js.map +1 -1
  130. package/lib/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
  131. package/lib/dist/extraction/wasm/tree-sitter-r.wasm +0 -0
  132. package/lib/dist/graph/queries.d.ts.map +1 -1
  133. package/lib/dist/graph/queries.js +13 -40
  134. package/lib/dist/graph/queries.js.map +1 -1
  135. package/lib/dist/graph/traversal.d.ts.map +1 -1
  136. package/lib/dist/graph/traversal.js +16 -4
  137. package/lib/dist/graph/traversal.js.map +1 -1
  138. package/lib/dist/index.d.ts +34 -2
  139. package/lib/dist/index.d.ts.map +1 -1
  140. package/lib/dist/index.js +90 -8
  141. package/lib/dist/index.js.map +1 -1
  142. package/lib/dist/installer/index.d.ts.map +1 -1
  143. package/lib/dist/installer/index.js +52 -2
  144. package/lib/dist/installer/index.js.map +1 -1
  145. package/lib/dist/installer/instructions-template.d.ts +34 -11
  146. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  147. package/lib/dist/installer/instructions-template.js +44 -12
  148. package/lib/dist/installer/instructions-template.js.map +1 -1
  149. package/lib/dist/installer/targets/claude.d.ts.map +1 -1
  150. package/lib/dist/installer/targets/claude.js +6 -10
  151. package/lib/dist/installer/targets/claude.js.map +1 -1
  152. package/lib/dist/installer/targets/codex.js +4 -6
  153. package/lib/dist/installer/targets/codex.js.map +1 -1
  154. package/lib/dist/installer/targets/gemini.js +4 -6
  155. package/lib/dist/installer/targets/gemini.js.map +1 -1
  156. package/lib/dist/installer/targets/opencode.d.ts +9 -1
  157. package/lib/dist/installer/targets/opencode.d.ts.map +1 -1
  158. package/lib/dist/installer/targets/opencode.js +91 -40
  159. package/lib/dist/installer/targets/opencode.js.map +1 -1
  160. package/lib/dist/installer/targets/shared.d.ts +14 -0
  161. package/lib/dist/installer/targets/shared.d.ts.map +1 -1
  162. package/lib/dist/installer/targets/shared.js +16 -0
  163. package/lib/dist/installer/targets/shared.js.map +1 -1
  164. package/lib/dist/mcp/daemon.d.ts +60 -1
  165. package/lib/dist/mcp/daemon.d.ts.map +1 -1
  166. package/lib/dist/mcp/daemon.js +221 -8
  167. package/lib/dist/mcp/daemon.js.map +1 -1
  168. package/lib/dist/mcp/dynamic-boundaries.d.ts +41 -0
  169. package/lib/dist/mcp/dynamic-boundaries.d.ts.map +1 -0
  170. package/lib/dist/mcp/dynamic-boundaries.js +359 -0
  171. package/lib/dist/mcp/dynamic-boundaries.js.map +1 -0
  172. package/lib/dist/mcp/index.d.ts.map +1 -1
  173. package/lib/dist/mcp/index.js +18 -9
  174. package/lib/dist/mcp/index.js.map +1 -1
  175. package/lib/dist/mcp/ppid-watchdog.d.ts +44 -0
  176. package/lib/dist/mcp/ppid-watchdog.d.ts.map +1 -0
  177. package/lib/dist/mcp/ppid-watchdog.js +27 -0
  178. package/lib/dist/mcp/ppid-watchdog.js.map +1 -0
  179. package/lib/dist/mcp/proxy.d.ts +6 -0
  180. package/lib/dist/mcp/proxy.d.ts.map +1 -1
  181. package/lib/dist/mcp/proxy.js +153 -24
  182. package/lib/dist/mcp/proxy.js.map +1 -1
  183. package/lib/dist/mcp/server-instructions.d.ts +12 -1
  184. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  185. package/lib/dist/mcp/server-instructions.js +43 -16
  186. package/lib/dist/mcp/server-instructions.js.map +1 -1
  187. package/lib/dist/mcp/session.d.ts +2 -0
  188. package/lib/dist/mcp/session.d.ts.map +1 -1
  189. package/lib/dist/mcp/session.js +49 -2
  190. package/lib/dist/mcp/session.js.map +1 -1
  191. package/lib/dist/mcp/stdin-teardown.d.ts +27 -0
  192. package/lib/dist/mcp/stdin-teardown.d.ts.map +1 -0
  193. package/lib/dist/mcp/stdin-teardown.js +49 -0
  194. package/lib/dist/mcp/stdin-teardown.js.map +1 -0
  195. package/lib/dist/mcp/tools.d.ts +71 -0
  196. package/lib/dist/mcp/tools.d.ts.map +1 -1
  197. package/lib/dist/mcp/tools.js +703 -85
  198. package/lib/dist/mcp/tools.js.map +1 -1
  199. package/lib/dist/mcp/transport.d.ts.map +1 -1
  200. package/lib/dist/mcp/transport.js +18 -2
  201. package/lib/dist/mcp/transport.js.map +1 -1
  202. package/lib/dist/resolution/callback-synthesizer.d.ts +3 -3
  203. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  204. package/lib/dist/resolution/callback-synthesizer.js +549 -21
  205. package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
  206. package/lib/dist/resolution/frameworks/astro.d.ts +9 -0
  207. package/lib/dist/resolution/frameworks/astro.d.ts.map +1 -0
  208. package/lib/dist/resolution/frameworks/astro.js +169 -0
  209. package/lib/dist/resolution/frameworks/astro.js.map +1 -0
  210. package/lib/dist/resolution/frameworks/expo-modules.d.ts.map +1 -1
  211. package/lib/dist/resolution/frameworks/expo-modules.js +6 -1
  212. package/lib/dist/resolution/frameworks/expo-modules.js.map +1 -1
  213. package/lib/dist/resolution/frameworks/index.d.ts +1 -0
  214. package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
  215. package/lib/dist/resolution/frameworks/index.js +5 -1
  216. package/lib/dist/resolution/frameworks/index.js.map +1 -1
  217. package/lib/dist/resolution/frameworks/java.js +6 -1
  218. package/lib/dist/resolution/frameworks/java.js.map +1 -1
  219. package/lib/dist/resolution/frameworks/python.d.ts.map +1 -1
  220. package/lib/dist/resolution/frameworks/python.js +7 -3
  221. package/lib/dist/resolution/frameworks/python.js.map +1 -1
  222. package/lib/dist/resolution/frameworks/react-native.d.ts.map +1 -1
  223. package/lib/dist/resolution/frameworks/react-native.js +53 -3
  224. package/lib/dist/resolution/frameworks/react-native.js.map +1 -1
  225. package/lib/dist/resolution/frameworks/react.d.ts.map +1 -1
  226. package/lib/dist/resolution/frameworks/react.js +15 -3
  227. package/lib/dist/resolution/frameworks/react.js.map +1 -1
  228. package/lib/dist/resolution/frameworks/svelte.js +5 -1
  229. package/lib/dist/resolution/frameworks/svelte.js.map +1 -1
  230. package/lib/dist/resolution/frameworks/vue.js +24 -27
  231. package/lib/dist/resolution/frameworks/vue.js.map +1 -1
  232. package/lib/dist/resolution/import-resolver.d.ts +10 -0
  233. package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
  234. package/lib/dist/resolution/import-resolver.js +564 -2
  235. package/lib/dist/resolution/import-resolver.js.map +1 -1
  236. package/lib/dist/resolution/index.d.ts +80 -0
  237. package/lib/dist/resolution/index.d.ts.map +1 -1
  238. package/lib/dist/resolution/index.js +457 -7
  239. package/lib/dist/resolution/index.js.map +1 -1
  240. package/lib/dist/resolution/name-matcher.d.ts +61 -0
  241. package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
  242. package/lib/dist/resolution/name-matcher.js +590 -14
  243. package/lib/dist/resolution/name-matcher.js.map +1 -1
  244. package/lib/dist/resolution/types.d.ts +27 -3
  245. package/lib/dist/resolution/types.d.ts.map +1 -1
  246. package/lib/dist/resolution/workspace-packages.d.ts +48 -0
  247. package/lib/dist/resolution/workspace-packages.d.ts.map +1 -0
  248. package/lib/dist/resolution/workspace-packages.js +208 -0
  249. package/lib/dist/resolution/workspace-packages.js.map +1 -0
  250. package/lib/dist/search/query-utils.d.ts +17 -1
  251. package/lib/dist/search/query-utils.d.ts.map +1 -1
  252. package/lib/dist/search/query-utils.js +79 -10
  253. package/lib/dist/search/query-utils.js.map +1 -1
  254. package/lib/dist/sync/watcher.d.ts +124 -32
  255. package/lib/dist/sync/watcher.d.ts.map +1 -1
  256. package/lib/dist/sync/watcher.js +326 -111
  257. package/lib/dist/sync/watcher.js.map +1 -1
  258. package/lib/dist/telemetry/index.d.ts +146 -0
  259. package/lib/dist/telemetry/index.d.ts.map +1 -0
  260. package/lib/dist/telemetry/index.js +544 -0
  261. package/lib/dist/telemetry/index.js.map +1 -0
  262. package/lib/dist/types.d.ts +17 -2
  263. package/lib/dist/types.d.ts.map +1 -1
  264. package/lib/dist/types.js +3 -0
  265. package/lib/dist/types.js.map +1 -1
  266. package/lib/dist/upgrade/index.d.ts +132 -0
  267. package/lib/dist/upgrade/index.d.ts.map +1 -0
  268. package/lib/dist/upgrade/index.js +462 -0
  269. package/lib/dist/upgrade/index.js.map +1 -0
  270. package/lib/dist/utils.d.ts +30 -24
  271. package/lib/dist/utils.d.ts.map +1 -1
  272. package/lib/dist/utils.js +64 -48
  273. package/lib/dist/utils.js.map +1 -1
  274. package/lib/node_modules/.package-lock.json +1 -29
  275. package/lib/package.json +1 -2
  276. package/package.json +1 -1
  277. package/lib/node_modules/chokidar/LICENSE +0 -21
  278. package/lib/node_modules/chokidar/README.md +0 -305
  279. package/lib/node_modules/chokidar/esm/handler.d.ts +0 -90
  280. package/lib/node_modules/chokidar/esm/handler.js +0 -629
  281. package/lib/node_modules/chokidar/esm/index.d.ts +0 -215
  282. package/lib/node_modules/chokidar/esm/index.js +0 -798
  283. package/lib/node_modules/chokidar/esm/package.json +0 -1
  284. package/lib/node_modules/chokidar/handler.d.ts +0 -90
  285. package/lib/node_modules/chokidar/handler.js +0 -635
  286. package/lib/node_modules/chokidar/index.d.ts +0 -215
  287. package/lib/node_modules/chokidar/index.js +0 -804
  288. package/lib/node_modules/chokidar/package.json +0 -69
  289. package/lib/node_modules/readdirp/LICENSE +0 -21
  290. package/lib/node_modules/readdirp/README.md +0 -120
  291. package/lib/node_modules/readdirp/esm/index.d.ts +0 -108
  292. package/lib/node_modules/readdirp/esm/index.js +0 -257
  293. package/lib/node_modules/readdirp/esm/package.json +0 -1
  294. package/lib/node_modules/readdirp/index.d.ts +0 -108
  295. package/lib/node_modules/readdirp/index.js +0 -263
  296. 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,184 @@ 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
+ * Find git repositories nested under `absDir` (inclusive), shallow bounded BFS.
265
+ * Stops descending at each repo root found — contents belong to that repo's own
266
+ * enumeration. Skips default-ignored dirs (`node_modules` can contain `.git`
267
+ * from npm git-dependencies — that never makes it project code) and CodeGraph
268
+ * data dirs. Depth- and entry-capped so a huge ignored tree can't stall the scan.
269
+ */
270
+ function findNestedGitRepos(absDir, relPrefix) {
271
+ const found = [];
272
+ const defaults = defaultsOnlyIgnore();
273
+ const queue = [
274
+ { abs: absDir, rel: relPrefix, depth: 0 },
275
+ ];
276
+ let examined = 0;
277
+ while (queue.length > 0) {
278
+ const { abs, rel, depth } = queue.shift();
279
+ if (++examined > EMBEDDED_REPO_SEARCH_ENTRIES) {
280
+ (0, errors_1.logDebug)('Embedded-repo search entry cap hit — deeper repos (if any) not discovered', { under: relPrefix });
281
+ break;
282
+ }
283
+ if (fs.existsSync(path.join(abs, '.git'))) {
284
+ found.push(rel);
285
+ continue; // its own git handles everything below
286
+ }
287
+ if (depth >= EMBEDDED_REPO_SEARCH_DEPTH)
288
+ continue;
289
+ let entries;
290
+ try {
291
+ entries = fs.readdirSync(abs, { withFileTypes: true });
292
+ }
293
+ catch {
294
+ continue;
295
+ }
296
+ for (const entry of entries) {
297
+ if (!entry.isDirectory())
298
+ continue;
299
+ if (entry.name === '.git' || (0, directory_1.isCodeGraphDataDir)(entry.name))
300
+ continue;
301
+ const childRel = rel + entry.name + '/';
302
+ if (defaults.ignores(childRel))
303
+ continue;
304
+ queue.push({ abs: path.join(abs, entry.name), rel: childRel, depth: depth + 1 });
305
+ }
306
+ }
307
+ return found;
308
+ }
309
+ /**
310
+ * Workspace-scope ignore matcher. Ordinary paths get the root's matcher
311
+ * (built-in defaults + root `.gitignore`); paths inside an EMBEDDED repo get
312
+ * that repo's own matcher (defaults + its root `.gitignore`) — the parent's
313
+ * `.gitignore` hides a child repo from git, not from the index (#514). A
314
+ * directory path (trailing slash) that is an ANCESTOR of an embedded root is
315
+ * never ignored, so directory-pruning callers (the Linux per-directory
316
+ * watcher) still descend to reach the embedded repos.
317
+ *
318
+ * Single source of truth for indexer and watcher scope — they must not diverge.
319
+ */
320
+ class ScopeIgnore {
321
+ rootMatcher;
322
+ embedded;
323
+ defaults = defaultsOnlyIgnore();
324
+ constructor(rootMatcher, embedded) {
325
+ this.rootMatcher = rootMatcher;
326
+ // Longest root first so paths in nested embedded repos hit the innermost matcher.
327
+ this.embedded = [...embedded].sort((a, b) => b.root.length - a.root.length);
328
+ }
329
+ ignores(rel) {
330
+ for (const { root, matcher } of this.embedded) {
331
+ if (rel.startsWith(root)) {
332
+ const inner = rel.slice(root.length);
333
+ if (inner === '')
334
+ return false;
335
+ // Built-in defaults apply to the FULL path uniformly (#407) — an
336
+ // embedded repo inside node_modules (an npm git-dependency) must stay
337
+ // excluded even though its own rules wouldn't ignore its files.
338
+ return this.defaults.ignores(rel) || matcher.ignores(inner);
339
+ }
340
+ }
341
+ // Never prune a directory that leads to an embedded repo.
342
+ if (rel.endsWith('/') && this.embedded.some(({ root }) => root.startsWith(rel))) {
343
+ return false;
344
+ }
345
+ return this.rootMatcher.ignores(rel);
346
+ }
347
+ }
348
+ exports.ScopeIgnore = ScopeIgnore;
349
+ /**
350
+ * Build the workspace-scope matcher. When the caller already knows the
351
+ * embedded roots (the scanner discovers them during collection), pass them to
352
+ * skip rediscovery; otherwise they're discovered here (the watcher path).
353
+ */
354
+ function buildScopeIgnore(rootDir, embeddedRoots) {
355
+ const roots = embeddedRoots ? [...embeddedRoots] : discoverEmbeddedRepoRoots(rootDir);
356
+ return new ScopeIgnore(buildDefaultIgnore(rootDir), roots.map((root) => ({ root, matcher: buildDefaultIgnore(path.join(rootDir, root)) })));
357
+ }
358
+ /**
359
+ * Standalone discovery of every embedded repo root under `rootDir` (relative,
360
+ * trailing-slashed) — both the untracked kind (#193) and the gitignored kind
361
+ * (#514), recursively (an embedded repo can embed further repos). Returns []
362
+ * for non-git roots: the filesystem walk handles nested repos there already.
363
+ */
364
+ function discoverEmbeddedRepoRoots(rootDir) {
365
+ try {
366
+ (0, child_process_1.execFileSync)('git', ['rev-parse', '--git-dir'], { cwd: rootDir, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
367
+ }
368
+ catch {
369
+ return [];
370
+ }
371
+ const out = [];
372
+ const defaults = defaultsOnlyIgnore();
373
+ const visit = (repoAbs, prefix) => {
374
+ const candidates = [];
375
+ try {
376
+ 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 });
377
+ for (const e of o.split('\0')) {
378
+ if (e.endsWith('/') && !defaults.ignores(e)) {
379
+ candidates.push(...findNestedGitRepos(path.join(repoAbs, e), e));
380
+ }
381
+ }
382
+ }
383
+ catch { /* untracked listing failed — ignored-side discovery still runs */ }
384
+ candidates.push(...findIgnoredEmbeddedRepos(repoAbs));
385
+ for (const rel of candidates) {
386
+ const full = (0, utils_1.normalizePath)(prefix + rel);
387
+ out.push(full);
388
+ visit(path.join(repoAbs, rel), full);
389
+ }
390
+ };
391
+ visit(rootDir, '');
392
+ return out;
393
+ }
394
+ /**
395
+ * Discover embedded repos hidden by `repoDir`'s OWN ignore rules: for each
396
+ * gitignored directory (skipping built-in default excludes), search for nested
397
+ * `.git` roots. Returns repo paths relative to `repoDir`, trailing-slashed.
398
+ */
399
+ function findIgnoredEmbeddedRepos(repoDir) {
400
+ const defaults = defaultsOnlyIgnore();
401
+ const repos = [];
402
+ for (const dir of listIgnoredDirs(repoDir)) {
403
+ if (defaults.ignores(dir))
404
+ continue;
405
+ repos.push(...findNestedGitRepos(path.join(repoDir, dir), dir));
406
+ }
407
+ return repos;
168
408
  }
169
409
  /**
170
410
  * Collect git-visible files (tracked + untracked, .gitignore-respected) from the
@@ -177,41 +417,55 @@ function buildDefaultIgnore(rootDir) {
177
417
  * skips them entirely, and untracked output reports them only as an opaque
178
418
  * "subdir/" entry (trailing slash) rather than expanding their files. Each
179
419
  * embedded repo is its own git boundary, so we re-run `git ls-files` inside it.
180
- * (See issue #193.)
420
+ * (See issue #193.) GITIGNORED embedded repos are invisible even to that —
421
+ * they're discovered separately via `findIgnoredEmbeddedRepos` (#514); every
422
+ * embedded repo root (however found) is recorded in `embeddedRoots` so callers
423
+ * can exempt its files from the parent's own gitignore rules.
181
424
  */
182
- function collectGitFiles(repoDir, prefix, files) {
425
+ function collectGitFiles(repoDir, prefix, files, embeddedRoots) {
183
426
  const gitOpts = { cwd: repoDir, encoding: 'utf-8', timeout: 30000, maxBuffer: 50 * 1024 * 1024, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true };
184
427
  // Tracked files. --recurse-submodules pulls in files from active submodules,
185
428
  // which the index would otherwise represent only as a commit pointer.
186
429
  // Without this, monorepos using submodules index 0 files. (See issue #147.)
187
430
  // Note: --recurse-submodules only supports -c/--cached and --stage modes — it
188
431
  // 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
- }
432
+ // -z gives NUL-separated, unquoted output so non-ASCII (e.g. CJK) paths
433
+ // survive verbatim. Without it git octal-escapes and double-quotes such paths
434
+ // (the core.quotepath default), and the quoted form never matches a real file
435
+ // on disk → those files are silently dropped from the index. (#541)
436
+ const tracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-c', '--recurse-submodules'], gitOpts);
437
+ for (const rel of tracked.split('\0')) {
438
+ if (rel)
439
+ files.add((0, utils_1.normalizePath)(prefix + rel));
195
440
  }
196
441
  // Untracked files (submodules manage their own untracked state). Embedded git
197
442
  // repos surface here as a single "subdir/" entry that git refuses to descend
198
443
  // 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)
444
+ const untracked = (0, child_process_1.execFileSync)('git', ['ls-files', '-z', '-o', '--exclude-standard'], gitOpts);
445
+ for (const rel of untracked.split('\0')) {
446
+ if (!rel)
203
447
  continue;
204
- if (trimmed.endsWith('/')) {
448
+ if (rel.endsWith('/')) {
205
449
  // git only emits a trailing-slash directory entry for an embedded repo.
206
450
  // 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);
451
+ // itself skips it (we never descend into a non-repo opaque dir). Never
452
+ // descend into default-ignored locations — an embedded repo inside
453
+ // node_modules is an npm git-dependency, not project code.
454
+ const childDir = path.join(repoDir, rel);
455
+ if (fs.existsSync(path.join(childDir, '.git')) && !defaultsOnlyIgnore().ignores(rel)) {
456
+ embeddedRoots?.add((0, utils_1.normalizePath)(prefix + rel));
457
+ collectGitFiles(childDir, prefix + rel, files, embeddedRoots);
211
458
  }
212
459
  continue;
213
460
  }
214
- files.add((0, utils_1.normalizePath)(prefix + trimmed));
461
+ files.add((0, utils_1.normalizePath)(prefix + rel));
462
+ }
463
+ // Embedded repos hidden by THIS repo's ignore rules (`/packages/` in a
464
+ // super-repo .gitignore) never appear in any listing above — discover and
465
+ // recurse into them too. (#514)
466
+ for (const rel of findIgnoredEmbeddedRepos(repoDir)) {
467
+ embeddedRoots?.add((0, utils_1.normalizePath)(prefix + rel));
468
+ collectGitFiles(path.join(repoDir, rel), prefix + rel, files, embeddedRoots);
215
469
  }
216
470
  }
217
471
  /**
@@ -238,11 +492,15 @@ function getGitVisibleFiles(rootDir) {
238
492
  }
239
493
  }
240
494
  const files = new Set();
241
- collectGitFiles(rootDir, '', files);
495
+ const embeddedRoots = new Set();
496
+ collectGitFiles(rootDir, '', files, embeddedRoots);
242
497
  // Apply built-in default ignores uniformly — to tracked files too, since
243
498
  // committing a dependency/build dir doesn't make it project code. A
244
499
  // `.gitignore` negation (e.g. `!vendor/`) is the explicit opt-in. (issue #407)
245
- const ig = buildDefaultIgnore(rootDir);
500
+ // Files inside an EMBEDDED repo are matched against that repo's own rules,
501
+ // not the parent's: the parent's .gitignore hides the child repo from git,
502
+ // not from the index. (#514)
503
+ const ig = buildScopeIgnore(rootDir, embeddedRoots);
246
504
  return new Set([...files].filter((f) => !ig.ignores(f)));
247
505
  }
248
506
  catch {
@@ -252,38 +510,65 @@ function getGitVisibleFiles(rootDir) {
252
510
  /**
253
511
  * Use `git status` to detect changed files instead of scanning every file.
254
512
  * Returns null on failure so callers fall back to full scan.
513
+ *
514
+ * Recurses into embedded repos — both the untracked kind (#193: the parent's
515
+ * status collapses them to an opaque `?? subdir/` entry) and the gitignored
516
+ * kind (#514: they never appear in the parent's status at all) — running
517
+ * `git status` inside each, so changes in a multi-repo workspace sync without
518
+ * a full rescan. Deleting an ENTIRE embedded repo dir is the one case this
519
+ * cannot see (the child status that would report the deletions is gone with
520
+ * it); a full `codegraph index` reconciles that.
255
521
  */
256
522
  function getGitChangedFiles(rootDir) {
257
523
  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 };
524
+ const changes = { modified: [], added: [], deleted: [] };
525
+ collectGitStatus(rootDir, '', changes);
526
+ return changes;
282
527
  }
283
528
  catch {
284
529
  return null;
285
530
  }
286
531
  }
532
+ function collectGitStatus(repoDir, prefix, out) {
533
+ 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 });
534
+ const untrackedDirs = [];
535
+ for (const line of output.split('\n')) {
536
+ if (line.length < 4)
537
+ continue; // Minimum: "XY file"
538
+ const statusCode = line.substring(0, 2);
539
+ const rel = (0, utils_1.normalizePath)(line.substring(3));
540
+ // Untracked directory entries (trailing slash) may hide an embedded repo —
541
+ // collect for the recursion below instead of treating as a file.
542
+ if (statusCode === '??' && rel.endsWith('/')) {
543
+ untrackedDirs.push(rel);
544
+ continue;
545
+ }
546
+ const filePath = (0, utils_1.normalizePath)(prefix + rel);
547
+ // Skip non-source files (git status already omits .gitignored paths).
548
+ if (!(0, grammars_1.isSourceFile)(filePath))
549
+ continue;
550
+ if (statusCode === '??') {
551
+ out.added.push(filePath);
552
+ }
553
+ else if (statusCode.includes('D')) {
554
+ out.deleted.push(filePath);
555
+ }
556
+ else {
557
+ // M, MM, AM, A (staged), etc. — treat as modified
558
+ out.modified.push(filePath);
559
+ }
560
+ }
561
+ // Recurse embedded repos found under untracked dirs (at the dir itself or
562
+ // nested deeper) and under this repo's gitignored dirs.
563
+ for (const rel of untrackedDirs) {
564
+ for (const repoRel of findNestedGitRepos(path.join(repoDir, rel), rel)) {
565
+ collectGitStatus(path.join(repoDir, repoRel), prefix + repoRel, out);
566
+ }
567
+ }
568
+ for (const rel of findIgnoredEmbeddedRepos(repoDir)) {
569
+ collectGitStatus(path.join(repoDir, rel), prefix + rel, out);
570
+ }
571
+ }
287
572
  /**
288
573
  * Recursively scan a directory for source files.
289
574
  *
@@ -341,16 +626,14 @@ function scanDirectoryWalk(rootDir, onProgress) {
341
626
  let count = 0;
342
627
  const visitedDirs = new Set();
343
628
  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;
629
+ const giPath = path.join(dir, '.gitignore');
630
+ if (!fs.existsSync(giPath))
631
+ return null;
632
+ // readGitignorePatterns is defensive: a non-UTF-8 (DLP-encrypted) or
633
+ // uncompilable .gitignore is skipped/filtered with a warning, never thrown
634
+ // (issue #682) — so the per-file `.ignores()` calls below can't crash.
635
+ const patterns = readGitignorePatterns(giPath);
636
+ return patterns ? { dir, ig: (0, ignore_1.default)().add(patterns) } : null;
354
637
  };
355
638
  const isIgnored = (fullPath, isDir, matchers) => {
356
639
  for (const { dir, ig } of matchers) {
@@ -392,8 +675,9 @@ function scanDirectoryWalk(rootDir, onProgress) {
392
675
  return;
393
676
  }
394
677
  for (const entry of entries) {
395
- // Never descend into git internals or our own data directory.
396
- if (entry.name === '.git' || entry.name === '.codegraph')
678
+ // Never descend into git internals or any CodeGraph data directory
679
+ // (the active one or a sibling another environment created — #636).
680
+ if (entry.name === '.git' || (0, directory_1.isCodeGraphDataDir)(entry.name))
397
681
  continue;
398
682
  const fullPath = path.join(dir, entry.name);
399
683
  const relativePath = (0, utils_1.normalizePath)(path.relative(rootDir, fullPath));