@colbymchenry/codegraph-darwin-arm64 0.9.4 → 0.9.6

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 (199) hide show
  1. package/lib/dist/bin/codegraph.js +12 -0
  2. package/lib/dist/bin/codegraph.js.map +1 -1
  3. package/lib/dist/db/queries.d.ts +1 -0
  4. package/lib/dist/db/queries.d.ts.map +1 -1
  5. package/lib/dist/db/queries.js +31 -3
  6. package/lib/dist/db/queries.js.map +1 -1
  7. package/lib/dist/extraction/grammars.d.ts +1 -1
  8. package/lib/dist/extraction/grammars.d.ts.map +1 -1
  9. package/lib/dist/extraction/grammars.js +29 -1
  10. package/lib/dist/extraction/grammars.js.map +1 -1
  11. package/lib/dist/extraction/index.d.ts +15 -2
  12. package/lib/dist/extraction/index.d.ts.map +1 -1
  13. package/lib/dist/extraction/index.js +170 -78
  14. package/lib/dist/extraction/index.js.map +1 -1
  15. package/lib/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  16. package/lib/dist/extraction/languages/c-cpp.js +45 -0
  17. package/lib/dist/extraction/languages/c-cpp.js.map +1 -1
  18. package/lib/dist/extraction/languages/csharp.d.ts.map +1 -1
  19. package/lib/dist/extraction/languages/csharp.js +2 -1
  20. package/lib/dist/extraction/languages/csharp.js.map +1 -1
  21. package/lib/dist/extraction/languages/go.d.ts.map +1 -1
  22. package/lib/dist/extraction/languages/go.js +12 -0
  23. package/lib/dist/extraction/languages/go.js.map +1 -1
  24. package/lib/dist/extraction/languages/index.d.ts.map +1 -1
  25. package/lib/dist/extraction/languages/index.js +2 -0
  26. package/lib/dist/extraction/languages/index.js.map +1 -1
  27. package/lib/dist/extraction/languages/objc.d.ts +3 -0
  28. package/lib/dist/extraction/languages/objc.d.ts.map +1 -0
  29. package/lib/dist/extraction/languages/objc.js +133 -0
  30. package/lib/dist/extraction/languages/objc.js.map +1 -0
  31. package/lib/dist/extraction/mybatis-extractor.d.ts +48 -0
  32. package/lib/dist/extraction/mybatis-extractor.d.ts.map +1 -0
  33. package/lib/dist/extraction/mybatis-extractor.js +198 -0
  34. package/lib/dist/extraction/mybatis-extractor.js.map +1 -0
  35. package/lib/dist/extraction/tree-sitter-types.d.ts +4 -0
  36. package/lib/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  37. package/lib/dist/extraction/tree-sitter.d.ts +33 -0
  38. package/lib/dist/extraction/tree-sitter.d.ts.map +1 -1
  39. package/lib/dist/extraction/tree-sitter.js +351 -14
  40. package/lib/dist/extraction/tree-sitter.js.map +1 -1
  41. package/lib/dist/index.d.ts +21 -2
  42. package/lib/dist/index.d.ts.map +1 -1
  43. package/lib/dist/index.js +53 -1
  44. package/lib/dist/index.js.map +1 -1
  45. package/lib/dist/installer/index.d.ts +1 -1
  46. package/lib/dist/installer/index.js +3 -3
  47. package/lib/dist/installer/index.js.map +1 -1
  48. package/lib/dist/installer/instructions-template.d.ts +2 -2
  49. package/lib/dist/installer/instructions-template.d.ts.map +1 -1
  50. package/lib/dist/installer/instructions-template.js +1 -1
  51. package/lib/dist/installer/targets/antigravity.d.ts +57 -0
  52. package/lib/dist/installer/targets/antigravity.d.ts.map +1 -0
  53. package/lib/dist/installer/targets/antigravity.js +307 -0
  54. package/lib/dist/installer/targets/antigravity.js.map +1 -0
  55. package/lib/dist/installer/targets/gemini.d.ts +26 -0
  56. package/lib/dist/installer/targets/gemini.d.ts.map +1 -0
  57. package/lib/dist/installer/targets/gemini.js +165 -0
  58. package/lib/dist/installer/targets/gemini.js.map +1 -0
  59. package/lib/dist/installer/targets/hermes.d.ts.map +1 -1
  60. package/lib/dist/installer/targets/hermes.js +57 -3
  61. package/lib/dist/installer/targets/hermes.js.map +1 -1
  62. package/lib/dist/installer/targets/kiro.d.ts +27 -0
  63. package/lib/dist/installer/targets/kiro.d.ts.map +1 -0
  64. package/lib/dist/installer/targets/kiro.js +196 -0
  65. package/lib/dist/installer/targets/kiro.js.map +1 -0
  66. package/lib/dist/installer/targets/registry.d.ts.map +1 -1
  67. package/lib/dist/installer/targets/registry.js +6 -0
  68. package/lib/dist/installer/targets/registry.js.map +1 -1
  69. package/lib/dist/installer/targets/types.d.ts +1 -1
  70. package/lib/dist/installer/targets/types.d.ts.map +1 -1
  71. package/lib/dist/mcp/daemon-paths.d.ts +46 -0
  72. package/lib/dist/mcp/daemon-paths.d.ts.map +1 -0
  73. package/lib/dist/mcp/daemon-paths.js +125 -0
  74. package/lib/dist/mcp/daemon-paths.js.map +1 -0
  75. package/lib/dist/mcp/daemon.d.ts +161 -0
  76. package/lib/dist/mcp/daemon.d.ts.map +1 -0
  77. package/lib/dist/mcp/daemon.js +403 -0
  78. package/lib/dist/mcp/daemon.js.map +1 -0
  79. package/lib/dist/mcp/engine.d.ts +100 -0
  80. package/lib/dist/mcp/engine.d.ts.map +1 -0
  81. package/lib/dist/mcp/engine.js +291 -0
  82. package/lib/dist/mcp/engine.js.map +1 -0
  83. package/lib/dist/mcp/index.d.ts +64 -53
  84. package/lib/dist/mcp/index.d.ts.map +1 -1
  85. package/lib/dist/mcp/index.js +307 -387
  86. package/lib/dist/mcp/index.js.map +1 -1
  87. package/lib/dist/mcp/proxy.d.ts +46 -0
  88. package/lib/dist/mcp/proxy.d.ts.map +1 -0
  89. package/lib/dist/mcp/proxy.js +276 -0
  90. package/lib/dist/mcp/proxy.js.map +1 -0
  91. package/lib/dist/mcp/server-instructions.d.ts +1 -1
  92. package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
  93. package/lib/dist/mcp/server-instructions.js +1 -1
  94. package/lib/dist/mcp/session.d.ts +67 -0
  95. package/lib/dist/mcp/session.d.ts.map +1 -0
  96. package/lib/dist/mcp/session.js +276 -0
  97. package/lib/dist/mcp/session.js.map +1 -0
  98. package/lib/dist/mcp/tools.d.ts +49 -0
  99. package/lib/dist/mcp/tools.d.ts.map +1 -1
  100. package/lib/dist/mcp/tools.js +253 -17
  101. package/lib/dist/mcp/tools.js.map +1 -1
  102. package/lib/dist/mcp/transport.d.ts +111 -29
  103. package/lib/dist/mcp/transport.d.ts.map +1 -1
  104. package/lib/dist/mcp/transport.js +181 -71
  105. package/lib/dist/mcp/transport.js.map +1 -1
  106. package/lib/dist/mcp/version.d.ts +19 -0
  107. package/lib/dist/mcp/version.d.ts.map +1 -0
  108. package/lib/dist/mcp/version.js +71 -0
  109. package/lib/dist/mcp/version.js.map +1 -0
  110. package/lib/dist/resolution/callback-synthesizer.d.ts +3 -2
  111. package/lib/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  112. package/lib/dist/resolution/callback-synthesizer.js +351 -3
  113. package/lib/dist/resolution/callback-synthesizer.js.map +1 -1
  114. package/lib/dist/resolution/frameworks/expo-modules.d.ts +3 -0
  115. package/lib/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
  116. package/lib/dist/resolution/frameworks/expo-modules.js +143 -0
  117. package/lib/dist/resolution/frameworks/expo-modules.js.map +1 -0
  118. package/lib/dist/resolution/frameworks/fabric.d.ts +3 -0
  119. package/lib/dist/resolution/frameworks/fabric.d.ts.map +1 -0
  120. package/lib/dist/resolution/frameworks/fabric.js +354 -0
  121. package/lib/dist/resolution/frameworks/fabric.js.map +1 -0
  122. package/lib/dist/resolution/frameworks/index.d.ts +4 -0
  123. package/lib/dist/resolution/frameworks/index.d.ts.map +1 -1
  124. package/lib/dist/resolution/frameworks/index.js +21 -1
  125. package/lib/dist/resolution/frameworks/index.js.map +1 -1
  126. package/lib/dist/resolution/frameworks/java.d.ts.map +1 -1
  127. package/lib/dist/resolution/frameworks/java.js +270 -1
  128. package/lib/dist/resolution/frameworks/java.js.map +1 -1
  129. package/lib/dist/resolution/frameworks/nestjs.d.ts.map +1 -1
  130. package/lib/dist/resolution/frameworks/nestjs.js +324 -0
  131. package/lib/dist/resolution/frameworks/nestjs.js.map +1 -1
  132. package/lib/dist/resolution/frameworks/react-native.d.ts +3 -0
  133. package/lib/dist/resolution/frameworks/react-native.d.ts.map +1 -0
  134. package/lib/dist/resolution/frameworks/react-native.js +360 -0
  135. package/lib/dist/resolution/frameworks/react-native.js.map +1 -0
  136. package/lib/dist/resolution/frameworks/swift-objc.d.ts +37 -0
  137. package/lib/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
  138. package/lib/dist/resolution/frameworks/swift-objc.js +252 -0
  139. package/lib/dist/resolution/frameworks/swift-objc.js.map +1 -0
  140. package/lib/dist/resolution/go-module.d.ts +26 -0
  141. package/lib/dist/resolution/go-module.d.ts.map +1 -0
  142. package/lib/dist/resolution/go-module.js +78 -0
  143. package/lib/dist/resolution/go-module.js.map +1 -0
  144. package/lib/dist/resolution/import-resolver.d.ts +18 -0
  145. package/lib/dist/resolution/import-resolver.d.ts.map +1 -1
  146. package/lib/dist/resolution/import-resolver.js +538 -4
  147. package/lib/dist/resolution/import-resolver.js.map +1 -1
  148. package/lib/dist/resolution/index.d.ts +10 -0
  149. package/lib/dist/resolution/index.d.ts.map +1 -1
  150. package/lib/dist/resolution/index.js +102 -0
  151. package/lib/dist/resolution/index.js.map +1 -1
  152. package/lib/dist/resolution/name-matcher.d.ts.map +1 -1
  153. package/lib/dist/resolution/name-matcher.js +212 -0
  154. package/lib/dist/resolution/name-matcher.js.map +1 -1
  155. package/lib/dist/resolution/swift-objc-bridge.d.ts +134 -0
  156. package/lib/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
  157. package/lib/dist/resolution/swift-objc-bridge.js +256 -0
  158. package/lib/dist/resolution/swift-objc-bridge.js.map +1 -0
  159. package/lib/dist/resolution/types.d.ts +29 -0
  160. package/lib/dist/resolution/types.d.ts.map +1 -1
  161. package/lib/dist/sync/index.d.ts +3 -1
  162. package/lib/dist/sync/index.d.ts.map +1 -1
  163. package/lib/dist/sync/index.js +8 -1
  164. package/lib/dist/sync/index.js.map +1 -1
  165. package/lib/dist/sync/watcher.d.ts +119 -7
  166. package/lib/dist/sync/watcher.d.ts.map +1 -1
  167. package/lib/dist/sync/watcher.js +243 -37
  168. package/lib/dist/sync/watcher.js.map +1 -1
  169. package/lib/dist/sync/worktree.d.ts +54 -0
  170. package/lib/dist/sync/worktree.d.ts.map +1 -0
  171. package/lib/dist/sync/worktree.js +136 -0
  172. package/lib/dist/sync/worktree.js.map +1 -0
  173. package/lib/dist/types.d.ts +1 -1
  174. package/lib/dist/types.d.ts.map +1 -1
  175. package/lib/dist/types.js +3 -0
  176. package/lib/dist/types.js.map +1 -1
  177. package/lib/node_modules/.package-lock.json +29 -1
  178. package/lib/node_modules/chokidar/LICENSE +21 -0
  179. package/lib/node_modules/chokidar/README.md +305 -0
  180. package/lib/node_modules/chokidar/esm/handler.d.ts +90 -0
  181. package/lib/node_modules/chokidar/esm/handler.js +629 -0
  182. package/lib/node_modules/chokidar/esm/index.d.ts +215 -0
  183. package/lib/node_modules/chokidar/esm/index.js +798 -0
  184. package/lib/node_modules/chokidar/esm/package.json +1 -0
  185. package/lib/node_modules/chokidar/handler.d.ts +90 -0
  186. package/lib/node_modules/chokidar/handler.js +635 -0
  187. package/lib/node_modules/chokidar/index.d.ts +215 -0
  188. package/lib/node_modules/chokidar/index.js +804 -0
  189. package/lib/node_modules/chokidar/package.json +69 -0
  190. package/lib/node_modules/readdirp/LICENSE +21 -0
  191. package/lib/node_modules/readdirp/README.md +120 -0
  192. package/lib/node_modules/readdirp/esm/index.d.ts +108 -0
  193. package/lib/node_modules/readdirp/esm/index.js +257 -0
  194. package/lib/node_modules/readdirp/esm/package.json +1 -0
  195. package/lib/node_modules/readdirp/index.d.ts +108 -0
  196. package/lib/node_modules/readdirp/index.js +263 -0
  197. package/lib/node_modules/readdirp/package.json +70 -0
  198. package/lib/package.json +2 -1
  199. package/package.json +1 -1
@@ -2,11 +2,17 @@
2
2
  /**
3
3
  * File Watcher
4
4
  *
5
- * Watches the project directory for file changes and triggers
6
- * debounced sync operations to keep the code graph up-to-date.
5
+ * Watches the project directory for file changes and triggers debounced sync
6
+ * operations to keep the code graph up-to-date.
7
7
  *
8
- * Uses Node.js native fs.watch with recursive mode (macOS FSEvents,
9
- * Windows ReadDirectoryChangesW, Linux inotify on Node 19+).
8
+ * Uses chokidar, whose `ignored` callback filters directories BEFORE they are
9
+ * watched so we never register inotify watches on excluded trees like
10
+ * node_modules/, dist/, .git/ (fixes #276: recursive fs.watch exhausted the
11
+ * kernel watch budget on large repos). The ignore decision reuses the indexer's
12
+ * `buildDefaultIgnore` (built-in default-ignore dirs + the project's .gitignore)
13
+ * so the watcher watches exactly the set the indexer indexes — in particular,
14
+ * node_modules/build/cache dirs are excluded even when the repo has no
15
+ * .gitignore (#407), which a .gitignore-only filter would miss.
10
16
  */
11
17
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
18
  if (k2 === undefined) k2 = k;
@@ -41,29 +47,82 @@ var __importStar = (this && this.__importStar) || (function () {
41
47
  return result;
42
48
  };
43
49
  })();
50
+ var __importDefault = (this && this.__importDefault) || function (mod) {
51
+ return (mod && mod.__esModule) ? mod : { "default": mod };
52
+ };
44
53
  Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.FileWatcher = void 0;
46
- const fs = __importStar(require("fs"));
54
+ exports.FileWatcher = exports.LockUnavailableError = void 0;
55
+ const path = __importStar(require("path"));
56
+ const chokidar_1 = __importDefault(require("chokidar"));
47
57
  const extraction_1 = require("../extraction");
48
58
  const errors_1 = require("../errors");
49
59
  const utils_1 = require("../utils");
50
60
  const watch_policy_1 = require("./watch-policy");
61
+ /**
62
+ * Thrown by a `syncFn` to signal that the underlying sync couldn't acquire
63
+ * the cross-process write lock (#449). The watcher treats this as "no
64
+ * progress" — preserves `pendingFiles`, skips `onSyncComplete`, and the
65
+ * `finally` block reschedules. Quiet (debug-only) because a long-running
66
+ * external indexer can hit this every debounce cycle.
67
+ */
68
+ class LockUnavailableError extends Error {
69
+ constructor(message = 'CodeGraph file lock unavailable; another process is writing') {
70
+ super(message);
71
+ this.name = 'LockUnavailableError';
72
+ }
73
+ }
74
+ exports.LockUnavailableError = LockUnavailableError;
51
75
  /**
52
76
  * FileWatcher monitors a project directory for changes and triggers
53
77
  * debounced sync operations via a provided callback.
54
78
  *
55
79
  * Design goals:
56
- * - Minimal resource usage (native OS file events, no polling)
80
+ * - Minimal resource usage (chokidar filters excluded directories before
81
+ * registering an inotify watch — see module docs / #276)
57
82
  * - Debounced to avoid thrashing on rapid saves
58
83
  * - Filters to supported source files by extension
59
- * - Ignores .codegraph/ directory changes
84
+ * - Ignores .codegraph/ and .git/ regardless of .gitignore
85
+ * - Tracks per-file pending state so MCP tools can flag stale results
86
+ * without blocking on a sync (issue #403)
60
87
  */
61
88
  class FileWatcher {
62
89
  watcher = null;
63
90
  debounceTimer = null;
64
- hasChanges = false;
91
+ /**
92
+ * Files seen by the watcher since the last successful sync — populated on
93
+ * every chokidar event, cleared at the start of a sync, and re-populated by
94
+ * events that arrive mid-sync (or restored on sync failure). Keyed by the
95
+ * same project-relative POSIX path the rest of the codebase uses, so a
96
+ * caller can intersect tool-response file paths against this map cheaply.
97
+ */
98
+ pendingFiles = new Map();
99
+ /**
100
+ * Wall-clock ms at which the in-flight sync began. Combined with
101
+ * {@link pendingFiles}'s `lastSeenMs`, this distinguishes "still in the
102
+ * debounce window" (lastSeen > syncStarted, sync hasn't started yet for
103
+ * this edit) from "currently being indexed" (lastSeen <= syncStarted).
104
+ */
105
+ syncStartedMs = 0;
65
106
  syncing = false;
66
107
  stopped = false;
108
+ /**
109
+ * False until chokidar fires its `ready` event. Gates `pendingFiles`
110
+ * insertion so the initial crawl's `add` events (one per pre-existing
111
+ * source file) don't pollute the per-file staleness signal. The events
112
+ * still flow into `scheduleSync()` to preserve the previous "initial
113
+ * scan triggers a reconciling sync" behavior.
114
+ */
115
+ chokidarReady = false;
116
+ /**
117
+ * Callbacks that resolve when chokidar fires `ready`. Used by tests (and
118
+ * any production caller that cares about a clean baseline) to deterministically
119
+ * gate on the end of the initial scan instead of guessing at a sleep duration.
120
+ */
121
+ readyWaiters = [];
122
+ // The shared ignore matcher (built-in defaults + project .gitignore), built
123
+ // once at start(). Same source of truth the indexer uses, so watcher scope
124
+ // can never diverge from index scope.
125
+ ignoreMatcher = null;
67
126
  projectRoot;
68
127
  debounceMs;
69
128
  syncFn;
@@ -84,49 +143,108 @@ class FileWatcher {
84
143
  if (this.watcher)
85
144
  return true; // Already watching
86
145
  this.stopped = false;
87
- // Some environments make recursive fs.watch unusable — most notably WSL2
88
- // /mnt/ drives, where setup blocks long enough to break MCP startup
89
- // handshakes (issue #199). Skip watching there; callers fall back to
90
- // manual `codegraph sync` or the git sync hooks.
146
+ // Some environments make filesystem watching unusable — most notably
147
+ // WSL2 /mnt/ drives, where the underlying fs.watch calls block long
148
+ // enough to break MCP startup handshakes (issue #199). Skip watching
149
+ // there; callers fall back to manual `codegraph sync` or git sync hooks.
91
150
  const disabledReason = (0, watch_policy_1.watchDisabledReason)(this.projectRoot);
92
151
  if (disabledReason) {
93
152
  (0, errors_1.logDebug)('File watcher disabled', { reason: disabledReason, projectRoot: this.projectRoot });
94
153
  return false;
95
154
  }
155
+ // Reuse the indexer's ignore set so the watcher and indexer agree on scope.
156
+ // chokidar only registers an inotify watch on directories that pass this
157
+ // filter — that's the #276 fix.
158
+ this.ignoreMatcher = (0, extraction_1.buildDefaultIgnore)(this.projectRoot);
96
159
  try {
97
- this.watcher = fs.watch(this.projectRoot, { recursive: true }, (_eventType, filename) => {
98
- if (!filename || this.stopped)
160
+ this.watcher = chokidar_1.default.watch(this.projectRoot, {
161
+ // chokidar calls this for every path it encounters and only watches
162
+ // those that pass — so excluded trees (node_modules/, dist/, .git/, …)
163
+ // never get an inotify watch in the first place.
164
+ ignored: (testPath, stats) => this.shouldIgnore(testPath, stats),
165
+ });
166
+ // Chokidar emits `add` for every pre-existing source file during its
167
+ // initial scan. Those events should still trigger the post-startup
168
+ // reconciling sync (preserving prior behavior), but they must NOT land
169
+ // in pendingFiles — otherwise every file in the project shows up as
170
+ // "edited but not indexed" on startup, which is the opposite of the
171
+ // signal #403 is supposed to provide. Flip the flag on chokidar's
172
+ // `ready` event; from then on, real edits populate pendingFiles.
173
+ //
174
+ // We also clear `pendingFiles` here as defense-in-depth: chokidar can
175
+ // emit late initial-scan `add` events via setImmediate AFTER the
176
+ // `ready` callback runs (observed under test-parallelism load).
177
+ // Clearing once at ready guarantees a clean baseline; real subsequent
178
+ // edits repopulate the set normally.
179
+ this.watcher.on('ready', () => {
180
+ this.chokidarReady = true;
181
+ this.pendingFiles.clear();
182
+ for (const cb of this.readyWaiters)
183
+ cb();
184
+ this.readyWaiters.length = 0;
185
+ });
186
+ // chokidar emits 'all' for every event type; we only sync source files.
187
+ this.watcher.on('all', (_event, filePath) => {
188
+ if (this.stopped)
99
189
  return;
100
- // Normalize path separators
101
- const normalized = (0, utils_1.normalizePath)(filename);
102
- // Ignore .codegraph/ directory changes (our own DB writes)
103
- if (normalized === '.codegraph' ||
104
- normalized.startsWith('.codegraph/') ||
105
- normalized.startsWith('.codegraph\\')) {
190
+ const normalized = (0, utils_1.normalizePath)(path.relative(this.projectRoot, filePath));
191
+ // Defense in depth: `ignored` should already keep these out, but events
192
+ // can still arrive during setup or via symlink traversal.
193
+ if (this.isAlwaysIgnored(normalized))
106
194
  return;
107
- }
108
- // Only sync changes to files we can actually parse.
109
- if (!(0, extraction_1.isSourceFile)(normalized)) {
195
+ if (!(0, extraction_1.isSourceFile)(normalized))
110
196
  return;
111
- }
112
197
  (0, errors_1.logDebug)('File change detected', { file: normalized });
113
- this.hasChanges = true;
198
+ // Only track events from after chokidar's initial scan as pending
199
+ // edits — pre-existing files on disk are already represented by
200
+ // (or about to be reconciled by) the index, not a user edit.
201
+ if (this.chokidarReady) {
202
+ const now = Date.now();
203
+ const existing = this.pendingFiles.get(normalized);
204
+ this.pendingFiles.set(normalized, {
205
+ firstSeenMs: existing?.firstSeenMs ?? now,
206
+ lastSeenMs: now,
207
+ });
208
+ }
114
209
  this.scheduleSync();
115
210
  });
116
- // Handle watcher errors gracefully
211
+ // Handle watcher errors gracefully — don't crash, the user can restart.
117
212
  this.watcher.on('error', (err) => {
118
213
  (0, errors_1.logWarn)('File watcher error', { error: String(err) });
119
- // Don't crash — watcher may recover or user can restart
120
214
  });
121
215
  (0, errors_1.logDebug)('File watcher started', { projectRoot: this.projectRoot, debounceMs: this.debounceMs });
122
216
  return true;
123
217
  }
124
218
  catch (err) {
125
- // Recursive watch not supported (e.g., Linux < Node 19)
126
- (0, errors_1.logWarn)('Could not start file watcher — recursive fs.watch not supported on this platform', { error: String(err) });
219
+ // Watcher setup failed (e.g., permission denied, missing directory).
220
+ (0, errors_1.logWarn)('Could not start file watcher', { error: String(err) });
127
221
  return false;
128
222
  }
129
223
  }
224
+ /** Our own dirs are always ignored, regardless of .gitignore. */
225
+ isAlwaysIgnored(rel) {
226
+ return (rel === '.codegraph' || rel.startsWith('.codegraph/') ||
227
+ rel === '.git' || rel.startsWith('.git/'));
228
+ }
229
+ /**
230
+ * chokidar `ignored` predicate — true for any path that should NOT be watched.
231
+ * Uses chokidar's provided `stats` to decide directory-vs-file so a dir-only
232
+ * rule like `build/` matches, without an extra `statSync` per path.
233
+ */
234
+ shouldIgnore(testPath, stats) {
235
+ const rel = (0, utils_1.normalizePath)(path.relative(this.projectRoot, testPath));
236
+ if (!rel || rel === '.' || rel.startsWith('..'))
237
+ return false; // root / outside
238
+ if (this.isAlwaysIgnored(rel))
239
+ return true;
240
+ if (!this.ignoreMatcher)
241
+ return false;
242
+ if (stats) {
243
+ return this.ignoreMatcher.ignores(stats.isDirectory() ? rel + '/' : rel);
244
+ }
245
+ // Stats unknown: test both forms so a directory match isn't missed.
246
+ return this.ignoreMatcher.ignores(rel) || this.ignoreMatcher.ignores(rel + '/');
247
+ }
130
248
  /**
131
249
  * Stop watching for file changes.
132
250
  */
@@ -140,7 +258,9 @@ class FileWatcher {
140
258
  this.watcher.close();
141
259
  this.watcher = null;
142
260
  }
143
- this.hasChanges = false;
261
+ this.pendingFiles.clear();
262
+ this.chokidarReady = false;
263
+ this.ignoreMatcher = null;
144
264
  (0, errors_1.logDebug)('File watcher stopped');
145
265
  }
146
266
  /**
@@ -149,6 +269,31 @@ class FileWatcher {
149
269
  isActive() {
150
270
  return this.watcher !== null && !this.stopped;
151
271
  }
272
+ /**
273
+ * Resolves once chokidar has fired its `ready` event (or immediately if
274
+ * it has already done so). Useful for tests that need a deterministic
275
+ * boundary before asserting on `pendingFiles` — guessing a sleep duration
276
+ * is flaky under load because chokidar can take longer than expected to
277
+ * finish its initial crawl on slow filesystems / parallel test runs.
278
+ *
279
+ * Production callers don't need this: `pendingFiles` is read continuously,
280
+ * the staleness banner is always correct (empty or populated), and the
281
+ * initial-scan window is a small one-time startup cost.
282
+ */
283
+ waitUntilReady(timeoutMs = 10000) {
284
+ if (this.chokidarReady)
285
+ return Promise.resolve();
286
+ return new Promise((resolve, reject) => {
287
+ const t = setTimeout(() => {
288
+ const idx = this.readyWaiters.indexOf(handler);
289
+ if (idx >= 0)
290
+ this.readyWaiters.splice(idx, 1);
291
+ reject(new Error(`FileWatcher.waitUntilReady timed out after ${timeoutMs}ms`));
292
+ }, timeoutMs);
293
+ const handler = () => { clearTimeout(t); resolve(); };
294
+ this.readyWaiters.push(handler);
295
+ });
296
+ }
152
297
  /**
153
298
  * Schedule a debounced sync.
154
299
  */
@@ -163,30 +308,91 @@ class FileWatcher {
163
308
  }
164
309
  /**
165
310
  * Flush pending changes by running sync.
311
+ *
312
+ * pendingFiles is NOT cleared at the start of sync — entries are removed
313
+ * only after sync commits successfully, and only for entries whose
314
+ * lastSeenMs <= syncStartedMs. That way, a query that arrives mid-sync
315
+ * still sees the affected files marked stale (the DB hasn't been updated
316
+ * yet), and an event that lands mid-sync persists into the follow-up.
317
+ *
318
+ * On sync failure pendingFiles is left untouched — every edit is still
319
+ * unindexed, and the rescheduled sync will absorb the same set next time.
166
320
  */
167
321
  async flush() {
168
322
  // If already syncing, the post-sync check will re-trigger
169
323
  if (this.syncing || this.stopped)
170
324
  return;
171
- this.hasChanges = false;
325
+ this.syncStartedMs = Date.now();
172
326
  this.syncing = true;
173
327
  try {
174
328
  const result = await this.syncFn();
329
+ // Remove entries whose most recent event predates this sync — those
330
+ // edits are now in the DB. Entries with lastSeenMs > syncStartedMs
331
+ // arrived mid-sync; whether the in-flight sync captured them depends
332
+ // on when sync read that file, so we keep them as pending and let
333
+ // the follow-up sync handle them. We prefer false positives ("shown
334
+ // stale, actually fresh" → at worst one extra Read) over false
335
+ // negatives ("shown fresh, actually stale" → misleads the agent).
336
+ for (const [filePath, info] of this.pendingFiles) {
337
+ if (info.lastSeenMs <= this.syncStartedMs) {
338
+ this.pendingFiles.delete(filePath);
339
+ }
340
+ }
175
341
  this.onSyncComplete?.(result);
176
342
  }
177
343
  catch (err) {
178
- const error = err instanceof Error ? err : new Error(String(err));
179
- (0, errors_1.logWarn)('Watch sync failed', { error: error.message });
180
- this.onSyncError?.(error);
344
+ if (err instanceof LockUnavailableError) {
345
+ // Lock-failure no-op (another writer holds the lock). pendingFiles
346
+ // stays intact and the `finally` block reschedules. Debug-only —
347
+ // a long external index would otherwise spam stderr every cycle.
348
+ (0, errors_1.logDebug)('Watch sync skipped: file lock unavailable', {
349
+ pendingFiles: this.pendingFiles.size,
350
+ });
351
+ }
352
+ else {
353
+ const error = err instanceof Error ? err : new Error(String(err));
354
+ (0, errors_1.logWarn)('Watch sync failed', { error: error.message });
355
+ this.onSyncError?.(error);
356
+ }
357
+ // Failure: leave pendingFiles untouched. Every edit it tracks is
358
+ // still unindexed; the rescheduled sync sees the same set.
181
359
  }
182
360
  finally {
183
361
  this.syncing = false;
184
- // If new changes arrived during sync, schedule another
185
- if (this.hasChanges && !this.stopped) {
362
+ // If pending files remain (mid-sync events, or this sync failed),
363
+ // schedule another pass.
364
+ if (this.pendingFiles.size > 0 && !this.stopped) {
186
365
  this.scheduleSync();
187
366
  }
188
367
  }
189
368
  }
369
+ /**
370
+ * Snapshot of files seen by the watcher since the last successful sync.
371
+ *
372
+ * Used by MCP tool responses to mark stale results without blocking on a
373
+ * sync: a tool that returns a hit in `src/foo.ts` while `src/foo.ts` is in
374
+ * this list tells the agent "Read this file directly, the index lags."
375
+ *
376
+ * `indexing` is true when a sync is currently in flight whose start time is
377
+ * AFTER this file's most recent event — i.e. that sync will absorb the
378
+ * edit. False means the file is still inside the debounce window and no
379
+ * sync has started yet (a follow-up call a few hundred ms later may show
380
+ * `indexing: true` or the file may have left the list entirely).
381
+ *
382
+ * Cheap: O(pendingFiles.size), no I/O, no locks.
383
+ */
384
+ getPendingFiles() {
385
+ const result = [];
386
+ for (const [filePath, info] of this.pendingFiles) {
387
+ result.push({
388
+ path: filePath,
389
+ firstSeenMs: info.firstSeenMs,
390
+ lastSeenMs: info.lastSeenMs,
391
+ indexing: this.syncing && this.syncStartedMs >= info.lastSeenMs,
392
+ });
393
+ }
394
+ return result;
395
+ }
190
396
  }
191
397
  exports.FileWatcher = FileWatcher;
192
398
  //# sourceMappingURL=watcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,2CAA6B;AAE7B,wDAA+C;AAE/C,8CAAiE;AACjE,sCAA8C;AAC9C,oCAAyC;AACzC,iDAAqD;AAwBrD;;;;;;GAMG;AACH,MAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,GAAG,6DAA6D;QACjF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AALD,oDAKC;AAsBD;;;;;;;;;;;;GAYG;AACH,MAAa,WAAW;IACd,OAAO,GAAqB,IAAI,CAAC;IACjC,aAAa,GAAyC,IAAI,CAAC;IACnE;;;;;;OAMG;IACK,YAAY,GAAG,IAAI,GAAG,EAAuD,CAAC;IACtF;;;;;OAKG;IACK,aAAa,GAAG,CAAC,CAAC;IAClB,OAAO,GAAG,KAAK,CAAC;IAChB,OAAO,GAAG,KAAK,CAAC;IACxB;;;;;;OAMG;IACK,aAAa,GAAG,KAAK,CAAC;IAC9B;;;;OAIG;IACK,YAAY,GAAsB,EAAE,CAAC;IAC7C,4EAA4E;IAC5E,2EAA2E;IAC3E,sCAAsC;IAC9B,aAAa,GAAkB,IAAI,CAAC;IAE3B,WAAW,CAAS;IACpB,UAAU,CAAS;IACnB,MAAM,CAA8D;IACpE,cAAc,CAAkC;IAChD,WAAW,CAA+B;IAE3D,YACE,WAAmB,EACnB,MAAmE,EACnE,UAAwB,EAAE;QAE1B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;QAC7C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;QAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC,CAAC,mBAAmB;QAClD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QAErB,qEAAqE;QACrE,oEAAoE;QACpE,qEAAqE;QACrE,yEAAyE;QACzE,MAAM,cAAc,GAAG,IAAA,kCAAmB,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC7D,IAAI,cAAc,EAAE,CAAC;YACnB,IAAA,iBAAQ,EAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7F,OAAO,KAAK,CAAC;QACf,CAAC;QAED,4EAA4E;QAC5E,yEAAyE;QACzE,gCAAgC;QAChC,IAAI,CAAC,aAAa,GAAG,IAAA,+BAAkB,EAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE1D,IAAI,CAAC;YACH,IAAI,CAAC,OAAO,GAAG,kBAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE;gBAC9C,oEAAoE;gBACpE,uEAAuE;gBACvE,iDAAiD;gBACjD,OAAO,EAAE,CAAC,QAAgB,EAAE,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC;aACjF,CAAC,CAAC;YAEH,qEAAqE;YACrE,mEAAmE;YACnE,uEAAuE;YACvE,oEAAoE;YACpE,oEAAoE;YACpE,kEAAkE;YAClE,iEAAiE;YACjE,EAAE;YACF,sEAAsE;YACtE,iEAAiE;YACjE,gEAAgE;YAChE,sEAAsE;YACtE,qCAAqC;YACrC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC5B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;gBAC1B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,YAAY;oBAAE,EAAE,EAAE,CAAC;gBACzC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;YAEH,wEAAwE;YACxE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAc,EAAE,QAAgB,EAAE,EAAE;gBAC1D,IAAI,IAAI,CAAC,OAAO;oBAAE,OAAO;gBAEzB,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAE5E,wEAAwE;gBACxE,0DAA0D;gBAC1D,IAAI,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC;oBAAE,OAAO;gBAC7C,IAAI,CAAC,IAAA,yBAAY,EAAC,UAAU,CAAC;oBAAE,OAAO;gBAEtC,IAAA,iBAAQ,EAAC,sBAAsB,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;gBACvD,kEAAkE;gBAClE,gEAAgE;gBAChE,6DAA6D;gBAC7D,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACvB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;oBACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;oBACnD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,EAAE;wBAChC,WAAW,EAAE,QAAQ,EAAE,WAAW,IAAI,GAAG;wBACzC,UAAU,EAAE,GAAG;qBAChB,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC,CAAC,CAAC;YAEH,wEAAwE;YACxE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAY,EAAE,EAAE;gBACxC,IAAA,gBAAO,EAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACxD,CAAC,CAAC,CAAC;YAEH,IAAA,iBAAQ,EAAC,sBAAsB,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACjG,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,qEAAqE;YACrE,IAAA,gBAAO,EAAC,8BAA8B,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,iEAAiE;IACzD,eAAe,CAAC,GAAW;QACjC,OAAO,CACL,GAAG,KAAK,YAAY,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC;YACrD,GAAG,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAC1C,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,YAAY,CAAC,QAAgB,EAAE,KAAa;QAClD,MAAM,GAAG,GAAG,IAAA,qBAAa,EAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC,CAAC,iBAAiB;QAChF,IAAI,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO,KAAK,CAAC;QACtC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC3E,CAAC;QACD,oEAAoE;QACpE,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC;IAClF,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAA,iBAAQ,EAAC,sBAAsB,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAChD,CAAC;IAED;;;;;;;;;;OAUG;IACH,cAAc,CAAC,SAAS,GAAG,KAAK;QAC9B,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QACjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE;gBACxB,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAC/C,IAAI,GAAG,IAAI,CAAC;oBAAE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC/C,MAAM,CAAC,IAAI,KAAK,CAAC,8CAA8C,SAAS,IAAI,CAAC,CAAC,CAAC;YACjF,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YACtD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC1B,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IAED;;;;;;;;;;;OAWG;IACK,KAAK,CAAC,KAAK;QACjB,0DAA0D;QAC1D,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAEzC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YACnC,oEAAoE;YACpE,mEAAmE;YACnE,qEAAqE;YACrE,kEAAkE;YAClE,oEAAoE;YACpE,+DAA+D;YAC/D,kEAAkE;YAClE,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACjD,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBAC1C,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;YACD,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,oBAAoB,EAAE,CAAC;gBACxC,mEAAmE;gBACnE,iEAAiE;gBACjE,iEAAiE;gBACjE,IAAA,iBAAQ,EAAC,2CAA2C,EAAE;oBACpD,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;iBACrC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClE,IAAA,gBAAO,EAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBACvD,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;YACD,iEAAiE;YACjE,2DAA2D;QAC7D,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YAErB,kEAAkE;YAClE,yBAAyB;YACzB,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAChD,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACH,eAAe;QACb,MAAM,MAAM,GAAkB,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,QAAQ,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,UAAU;aAChE,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAtUD,kCAsUC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Git Worktree Awareness
3
+ *
4
+ * A CodeGraph index lives in a `.codegraph/` directory and is resolved by
5
+ * walking up parent directories to the nearest one (see
6
+ * `findNearestCodeGraphRoot`). That walk is unaware of git worktrees: when a
7
+ * worktree is created *inside* the main checkout (e.g. some tools place them
8
+ * under `.gitignore`d paths like `.claude/worktrees/<name>/`), a command run
9
+ * from the worktree walks up and silently resolves the MAIN checkout's index.
10
+ *
11
+ * Every query then returns results from the main tree's code — usually a
12
+ * different branch — rather than the worktree the user is actually editing.
13
+ * Symbols added or changed only in the worktree are invisible. This module
14
+ * detects that "borrowed index" situation so callers can warn about it.
15
+ *
16
+ * Detection is best-effort: when git is unavailable or the path isn't a repo,
17
+ * it reports "no mismatch" and callers carry on unchanged.
18
+ */
19
+ /**
20
+ * Absolute, symlink-resolved toplevel of the git working tree that `dir`
21
+ * belongs to, or null when `dir` isn't inside a git repo (or git is missing).
22
+ *
23
+ * `git rev-parse --show-toplevel` returns the per-worktree root: the main
24
+ * checkout and each linked worktree report their own distinct directory, which
25
+ * is exactly the distinction this module relies on.
26
+ */
27
+ export declare function gitWorktreeRoot(dir: string): string | null;
28
+ export interface WorktreeIndexMismatch {
29
+ /** The git working tree the command was run from. */
30
+ worktreeRoot: string;
31
+ /** The (different) working tree whose `.codegraph` index is being used. */
32
+ indexRoot: string;
33
+ }
34
+ /**
35
+ * Detect when `startPath` lives in one git working tree but the resolved
36
+ * CodeGraph index (`indexRoot`) belongs to a *different* working tree.
37
+ *
38
+ * Returns null — meaning "nothing to warn about" — when:
39
+ * - `startPath` isn't in a git repo (or git is unavailable),
40
+ * - the index already lives in `startPath`'s own working tree, or
41
+ * - `indexRoot` isn't itself a working-tree root (an unrelated parent dir
42
+ * that merely happens to contain a `.codegraph/`), which keeps non-git
43
+ * and monorepo-subdir layouts from producing false warnings.
44
+ */
45
+ export declare function detectWorktreeIndexMismatch(startPath: string, indexRoot: string): WorktreeIndexMismatch | null;
46
+ /** One-line-per-fact warning describing a detected mismatch. */
47
+ export declare function worktreeMismatchWarning(m: WorktreeIndexMismatch): string;
48
+ /**
49
+ * Compact, single-line variant for prefixing a tool's result. Read tools
50
+ * return their answer inline, so the heads-up has to ride on the same payload
51
+ * the agent is already reading — a multi-line block would bury the result.
52
+ */
53
+ export declare function worktreeMismatchNotice(m: WorktreeIndexMismatch): string;
54
+ //# sourceMappingURL=worktree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/sync/worktree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAW1D;AAED,MAAM,WAAW,qBAAqB;IACpC,qDAAqD;IACrD,YAAY,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,qBAAqB,GAAG,IAAI,CAa9B;AAED,gEAAgE;AAChE,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CASxE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAOvE"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /**
3
+ * Git Worktree Awareness
4
+ *
5
+ * A CodeGraph index lives in a `.codegraph/` directory and is resolved by
6
+ * walking up parent directories to the nearest one (see
7
+ * `findNearestCodeGraphRoot`). That walk is unaware of git worktrees: when a
8
+ * worktree is created *inside* the main checkout (e.g. some tools place them
9
+ * under `.gitignore`d paths like `.claude/worktrees/<name>/`), a command run
10
+ * from the worktree walks up and silently resolves the MAIN checkout's index.
11
+ *
12
+ * Every query then returns results from the main tree's code — usually a
13
+ * different branch — rather than the worktree the user is actually editing.
14
+ * Symbols added or changed only in the worktree are invisible. This module
15
+ * detects that "borrowed index" situation so callers can warn about it.
16
+ *
17
+ * Detection is best-effort: when git is unavailable or the path isn't a repo,
18
+ * it reports "no mismatch" and callers carry on unchanged.
19
+ */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || (function () {
37
+ var ownKeys = function(o) {
38
+ ownKeys = Object.getOwnPropertyNames || function (o) {
39
+ var ar = [];
40
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
41
+ return ar;
42
+ };
43
+ return ownKeys(o);
44
+ };
45
+ return function (mod) {
46
+ if (mod && mod.__esModule) return mod;
47
+ var result = {};
48
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49
+ __setModuleDefault(result, mod);
50
+ return result;
51
+ };
52
+ })();
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.gitWorktreeRoot = gitWorktreeRoot;
55
+ exports.detectWorktreeIndexMismatch = detectWorktreeIndexMismatch;
56
+ exports.worktreeMismatchWarning = worktreeMismatchWarning;
57
+ exports.worktreeMismatchNotice = worktreeMismatchNotice;
58
+ const fs = __importStar(require("fs"));
59
+ const path = __importStar(require("path"));
60
+ const child_process_1 = require("child_process");
61
+ /**
62
+ * Absolute, symlink-resolved toplevel of the git working tree that `dir`
63
+ * belongs to, or null when `dir` isn't inside a git repo (or git is missing).
64
+ *
65
+ * `git rev-parse --show-toplevel` returns the per-worktree root: the main
66
+ * checkout and each linked worktree report their own distinct directory, which
67
+ * is exactly the distinction this module relies on.
68
+ */
69
+ function gitWorktreeRoot(dir) {
70
+ try {
71
+ const out = (0, child_process_1.execFileSync)('git', ['rev-parse', '--show-toplevel'], {
72
+ cwd: dir,
73
+ encoding: 'utf8',
74
+ stdio: ['ignore', 'pipe', 'ignore'],
75
+ }).trim();
76
+ return out ? realpath(out) : null;
77
+ }
78
+ catch {
79
+ return null;
80
+ }
81
+ }
82
+ /**
83
+ * Detect when `startPath` lives in one git working tree but the resolved
84
+ * CodeGraph index (`indexRoot`) belongs to a *different* working tree.
85
+ *
86
+ * Returns null — meaning "nothing to warn about" — when:
87
+ * - `startPath` isn't in a git repo (or git is unavailable),
88
+ * - the index already lives in `startPath`'s own working tree, or
89
+ * - `indexRoot` isn't itself a working-tree root (an unrelated parent dir
90
+ * that merely happens to contain a `.codegraph/`), which keeps non-git
91
+ * and monorepo-subdir layouts from producing false warnings.
92
+ */
93
+ function detectWorktreeIndexMismatch(startPath, indexRoot) {
94
+ const worktreeRoot = gitWorktreeRoot(startPath);
95
+ if (!worktreeRoot)
96
+ return null;
97
+ const resolvedIndexRoot = realpath(indexRoot);
98
+ if (worktreeRoot === resolvedIndexRoot)
99
+ return null;
100
+ // Only flag it when the index root is itself a real working-tree root. This
101
+ // distinguishes "borrowed another worktree's index" from "index sits in a
102
+ // plain ancestor directory", and avoids warning outside git entirely.
103
+ if (gitWorktreeRoot(resolvedIndexRoot) !== resolvedIndexRoot)
104
+ return null;
105
+ return { worktreeRoot, indexRoot: resolvedIndexRoot };
106
+ }
107
+ /** One-line-per-fact warning describing a detected mismatch. */
108
+ function worktreeMismatchWarning(m) {
109
+ return (`This CodeGraph index belongs to a different git working tree.\n` +
110
+ ` Running in: ${m.worktreeRoot}\n` +
111
+ ` Index from: ${m.indexRoot}\n` +
112
+ `Results reflect that tree's code (often a different branch), not this worktree — ` +
113
+ `symbols changed only here are missing. Run "codegraph init -i" in this worktree ` +
114
+ `for a worktree-local index.`);
115
+ }
116
+ /**
117
+ * Compact, single-line variant for prefixing a tool's result. Read tools
118
+ * return their answer inline, so the heads-up has to ride on the same payload
119
+ * the agent is already reading — a multi-line block would bury the result.
120
+ */
121
+ function worktreeMismatchNotice(m) {
122
+ return (`⚠ CodeGraph results below come from a different git worktree (${m.indexRoot}), ` +
123
+ `not where you're working (${m.worktreeRoot}) — they may reflect another branch, ` +
124
+ `and symbols changed only here are missing. Run "codegraph init -i" here for a ` +
125
+ `worktree-local index.`);
126
+ }
127
+ /** Resolve symlinks where possible so tmp/realpath quirks don't break equality. */
128
+ function realpath(p) {
129
+ try {
130
+ return fs.realpathSync(path.resolve(p));
131
+ }
132
+ catch {
133
+ return path.resolve(p);
134
+ }
135
+ }
136
+ //# sourceMappingURL=worktree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/sync/worktree.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcH,0CAWC;AAoBD,kEAgBC;AAGD,0DASC;AAOD,wDAOC;AArFD,uCAAyB;AACzB,2CAA6B;AAC7B,iDAA6C;AAE7C;;;;;;;GAOG;AACH,SAAgB,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,4BAAY,EAAC,KAAK,EAAE,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE;YAChE,GAAG,EAAE,GAAG;YACR,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AASD;;;;;;;;;;GAUG;AACH,SAAgB,2BAA2B,CACzC,SAAiB,EACjB,SAAiB;IAEjB,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAChD,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAE/B,MAAM,iBAAiB,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,YAAY,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAC;IAEpD,4EAA4E;IAC5E,0EAA0E;IAC1E,sEAAsE;IACtE,IAAI,eAAe,CAAC,iBAAiB,CAAC,KAAK,iBAAiB;QAAE,OAAO,IAAI,CAAC;IAE1E,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC;AACxD,CAAC;AAED,gEAAgE;AAChE,SAAgB,uBAAuB,CAAC,CAAwB;IAC9D,OAAO,CACL,iEAAiE;QACjE,iBAAiB,CAAC,CAAC,YAAY,IAAI;QACnC,iBAAiB,CAAC,CAAC,SAAS,IAAI;QAChC,mFAAmF;QACnF,kFAAkF;QAClF,6BAA6B,CAC9B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,sBAAsB,CAAC,CAAwB;IAC7D,OAAO,CACL,iEAAiE,CAAC,CAAC,SAAS,KAAK;QACjF,6BAA6B,CAAC,CAAC,YAAY,uCAAuC;QAClF,gFAAgF;QAChF,uBAAuB,CACxB,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,SAAS,QAAQ,CAAC,CAAS;IACzB,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;AACH,CAAC"}
@@ -20,7 +20,7 @@ export type EdgeKind = 'contains' | 'calls' | 'imports' | 'exports' | 'extends'
20
20
  * Supported programming languages. See NODE_KINDS for why this is a
21
21
  * runtime-iterable const array.
22
22
  */
23
- export declare const LANGUAGES: readonly ["typescript", "javascript", "tsx", "jsx", "python", "go", "rust", "java", "c", "cpp", "csharp", "php", "ruby", "swift", "kotlin", "dart", "svelte", "vue", "liquid", "pascal", "scala", "lua", "luau", "yaml", "twig", "unknown"];
23
+ export declare const LANGUAGES: readonly ["typescript", "javascript", "tsx", "jsx", "python", "go", "rust", "java", "c", "cpp", "csharp", "php", "ruby", "swift", "kotlin", "dart", "svelte", "vue", "liquid", "pascal", "scala", "lua", "luau", "objc", "yaml", "twig", "xml", "properties", "unknown"];
24
24
  export type Language = (typeof LANGUAGES)[number];
25
25
  /**
26
26
  * A node in the knowledge graph representing a code symbol