Files
pi-lsp/test/unit
Evan Reichard 77876264ee feat(watcher): forward FS events as workspace/didChangeWatchedFiles
LSP servers maintain their own workspace index built at initialize time
and rely on the client to push file-system events. Previously the daemon
only synced the single file being queried, so externally created/changed
files (codegen, build scripts, git checkout, the agent's own writes from
the perspective of other open files) left the server's index stale until
manual /lsp-destroy.

Each ClientEntry now lazily owns a WorkspaceWatcher (chokidar + picomatch)
that translates FS events into workspace/didChangeWatchedFiles batches.
Patterns come from the server via client/registerCapability (no
speculative watching). Ignores layer a tiny baseline (.git, .DS_Store)
over the repo's root .gitignore, with a fallback list for non-git
workspaces. Events debounce 50ms quiet / 500ms max wait.

Notable: gopls registers absolute-path globs (/abs/root/**/*.go) rather
than relative ones, so compileWatchers() matches each event against both
relative and absolute path forms. Caught by the integration test; unit
regression test added.

Rollback: PI_LSP_DISABLE_WATCHERS=1 disables all watcher creation.

- src/client.ts: honor register/unregisterCapability for
  workspace/didChangeWatchedFiles; advertise dynamicRegistration;
  expose getFileWatchers/onWatchersChanged/sendNotification
- src/watcher.ts: new WorkspaceWatcher with layered ignores,
  debounce+batch, Created+Deleted coalescing, dual-form glob matching
- src/daemon.ts: per-entry watcher lifecycle, PI_LSP_DISABLE_WATCHERS,
  LSP_DEBUG-gated pattern/event logging
- test/unit/watcher.test.ts: 11 tests against real chokidar + temp dir
- test/integration/watcher-gopls.test.ts: end-to-end against gopls
- AGENTS.md: new "Workspace File Watching" section
- flake.nix: add go (required by gopls integration test)
2026-05-19 23:43:32 -04:00
..