Commit Graph
6 Commits
Author SHA1 Message Date
b48170e69f feat(mcp): per-file staleness banner + tunable watcher debounce (#403) (#428)
Two coupled changes addressing the issue's underlying ask — "how does the
agent know when the index lags" — without resorting to a static wait.

Per-file staleness banner
-------------------------
FileWatcher now tracks per-path `pendingFiles` (path, firstSeenMs,
lastSeenMs, indexing) — events since the last successful sync, cleared
only after a sync whose `syncStartedMs >= lastSeenMs` commits. Chokidar
initial-scan events are gated behind a `ready` flag (with `waitUntilReady()`
exposed so tests can deterministically wait through it) so a fresh startup
doesn't falsely flag every existing file as pending.

ToolHandler now wraps every code-returning response (search, context,
callers, callees, impact, trace, explore, node, files) with
`withStalenessNotice`: intersects "files referenced in the response" with
`getPendingFiles()` and emits a hybrid signal —

  * banner at the top for files referenced AND pending (with edit age +
    indexing/pending-sync state, telling the agent to Read those specific
    files directly; the rest of the response stays fresh and codegraph
    stays authoritative for it),
  * compact footer for pending files elsewhere in the project not
    referenced above (capped at 5).

Cost is one boolean check + N substring matches when pending; zero
allocation when idle. `codegraph_status` surfaces the same data as a
first-class `### Pending sync:` section so the agent can ask "is the index
caught up?" in one call.

Cross-project quirk: when an agent passes `projectPath` matching the
default session's project, the staleness wrapper switches from the cached
cross-project CodeGraph (no watcher) to the default one (with watcher) so
the signal still fires. Same fix applied to `handleStatus`.

CODEGRAPH_WATCH_DEBOUNCE_MS
---------------------------
MCP `serve --mcp` now reads `CODEGRAPH_WATCH_DEBOUNCE_MS` and forwards it
to `cg.watch({ debounceMs })`. Clamped to [100ms, 60s]; out-of-range or
non-numeric values fall back to the FileWatcher default (2000ms). Active
value is logged to stderr on watcher startup so it's discoverable. The
docs in `server-instructions.ts`, `installer/instructions-template.ts`,
and `.cursor/rules/codegraph.mdc` no longer claim "~500ms"; they now
describe the banner mechanism instead — since per-file staleness replaces
the "wait N ms" guidance entirely, the docs become accurate at any
debounce value.

Validation
----------
* 847 unit/integration tests pass (added 15 new ones — pending-file
  tracking, banner/footer routing, status section, env-var parsing).
* Direct MCP probe through a real `codegraph serve --mcp` process: edit a
  file, query within the debounce window, banner fires naming the
  edited file with edit-age.
* Real Claude TUI session via `scripts/agent-eval/itrun.sh` with
  `CODEGRAPH_WATCH_DEBOUNCE_MS=10000`: agent edits `math.ts`, calls
  `codegraph_explore`, reads the banner, **and discloses it unprompted in
  its final reply**: "note: symbol index is mid-sync for the new `divide`,
  but the source it returned is verbatim from disk."

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 23:48:10 -05:00
4a4a37d135 feat(mcp): detect borrowed git worktree index and surface on read tools (#312)
When a worktree is nested inside the main checkout (e.g. agent tools that place
worktrees under .claude/worktrees/<name>/), the nearest-.codegraph walk resolves
UP to the main checkout's index and queries silently return that tree's code —
usually a different branch. Symbols changed only in the worktree are invisible,
and nothing tells the user (#155).

Two layers:

- **Detection** (src/sync/worktree.ts): detectWorktreeIndexMismatch() compares
  the caller's git working-tree root vs the resolved index root via
  'git rev-parse --show-toplevel'. Best-effort; no git / not a repo / monorepo
  subdir / plain-ancestor index → no warning.
- **Surface**: codegraph status (CLI + MCP) embeds a verbose multi-line warning;
  every MCP read tool (search/context/trace/callers/callees/impact/explore/node/
  files) prefixes a compact one-line notice naming the borrowed index and the
  fix (codegraph init -i in the worktree). Detection is cached per session per
  start path, so it costs at most a single pair of 'git rev-parse' spawns per
  project no matter how many tool calls — respects the wall-clock-latency
  invariant.

Real-git tests (no mocking) cover both layers. Validated on macOS / Linux
(Docker) / Windows (Parallels VM); 11/11 worktree tests green on all three.

Closes #155

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 20:57:20 -05:00
cf7db7cb98 fix(mcp): skip fs.watch on WSL2 /mnt drives that hang MCP startup (#199) (#210)
Recursive fs.watch on a WSL2 /mnt NTFS/9p mount walks the directory tree
with every readdir/stat crossing the Windows boundary, stalling the event
loop long enough to blow past opencode's 30s MCP handshake timeout so the
tools never appear. This is the file-watcher half of the #172 fix, which
moved the DB/WASM open off the handshake but left the watcher on the
critical path.

- Add watchDisabledReason() policy: CODEGRAPH_NO_WATCH (off) >
  CODEGRAPH_FORCE_WATCH (force on) > WSL2 + /mnt auto-detect (off).
  FileWatcher.start() and the MCP server both honor it; the server now
  logs why watching is off and how to refresh.
- Add `codegraph serve --mcp --no-watch`.
- When watching is off, init/install offer git sync hooks (post-commit,
  post-merge, post-checkout) that run `codegraph sync` in the background,
  or fall back to manual sync; either way the user is told the index
  stays frozen until re-synced. uninit removes the hooks.
- Tests: watch-policy + git-hooks (idempotency, user-content preservation,
  core.hooksPath).

Root-cause analysis and workaround by @mengfanbo123.

Closes #199

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 10:32:08 -05:00
Colby McHenry 3da5c96a0b feat: Add file watcher with debounced auto-sync and comprehensive test coverage
Addresses the need for automatic graph synchronization on file changes. Implements FileWatcher using native OS file events (FSEvents/inotify/ReadDirectoryChangesW) with 2-second debouncing to prevent thrashing on rapid saves. Filters changes against include/exclude patterns and ignores .codegraph directory modifications. Integrates with CodeGraph API (watch/unwatch/isWatching methods) and MCP server for automatic activation. Updates documentation to reflect shift from semantic to full-text search and removal of manual hook installation requirements.
2026-04-07 16:02:15 -05:00
Colby McHenry d0ee6f7fc4 Enhances code extraction and project indexing
Adds support for Dart and Liquid languages with tree-sitter parsing.
Improves accuracy of code symbol extraction for existing languages.
Indexes project files to enhance code navigation features.
Migrates build system to facilitate code contributions.
Removes git hook functionality.
Integrates Sentry for error tracking and reporting.
Enhances project initialization and configuration loading.
2026-02-09 22:18:59 -06:00
Colby McHenry cc6e7a5c89 Init 2026-01-18 16:25:00 -06:00