mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-29 14:49:36 +08:00
main
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
637fb0fac8 |
fix(mcp): release an idle explicit project and its writer lock (#2087) (#2283)
* fix(mcp): release an idle explicit project and its writer lock (#2087)
A daemon that answered a `projectPath` query for another indexed project
opened it in-process and, with no owner there, took its writer lock. The
project cache only evicted over its LRU bound or on shutdown, so the lock
stayed held for the daemon's whole life: the project's own daemon could not
become its writer and `codegraph index` there was refused.
Release a cached explicit project once it has gone unused for 10 minutes
(CODEGRAPH_PROJECT_IDLE_TIMEOUT_MS; 0 never releases), through the same
trim path as LRU eviction, so an active call or a running catch-up still
defers it. The next call reopens the project and catches it up (#1835).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit
|
||
|
|
c405ac5e6c |
fix(windows): make load-sensitive tests wait on real signals; longer pid-file retry (#1773) (#2078)
* test: make Windows load-sensitive tests wait on the tree, not the clock (#1773) Each failure from the loaded Windows run was traced to its mechanism and reproduced deterministically before changing it. No assertion is weakened. - daemon-lock-refresh: the PowerShell holder slept 200ms against a 375ms retry budget. Windows refuses a replace-rename while any handle to the target is open, even a Node read handle, so hold one in-process and close it inside the rename mock after the first real failure. Also asserts the first rename really failed with a retryable code. - mcp-projectpath-lifecycle: the owner daemon armed a 500ms idle timer at start and exited (code 0) before a starved engine reached it. It now starts with idle exit off and is armed over IPC once the engines hold a session. The file waits for catch-up instead of the gate's 3s serve-anyway deadline, and its index-heavy hooks and eviction case get explicit timeouts. - mcp-daemon / mcp-writer-lock teardown: racing launchers spawn detached daemon candidates whose cwd is the fixture; a loser still starting at teardown pinned it (EBUSY) or took over after the winner was stopped. A --require preload records candidate pids, and teardown waits for the losers before stopping the winner. - mcp-writer-lock: writer.pid appears before the daemon binds and rewrites daemon.pid, so cleanup could probe a daemon mid-start ('unverified'); wait for both proxies to attach. Removal uses fs.promises.rm, because fs.rmSync gives up on the first Windows access-denied error despite maxRetries. - mcp-daemon #1963: connect only after the proxy attached (lock before bind). - sync-rebuild-convergence / multi-repo-workspace: explicit timeouts scoped to the cases that build real indexes; the global timeout is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(daemon): give the Windows pid-file replace a longer retry budget (#1773) Windows refuses to replace a file while any handle to it is open, including a plain Node read handle, so an antivirus scan, an indexer, or another session reading daemon.pid can each block the daemon's startup refresh for a moment, and for longer on a loaded machine. The retry waited 375ms in all; it now backs off 25, 50, 100, 200, then 400ms three times, about 1.6s over eight attempts, still well inside a launcher's ~6s connect window. Permanent failures and non-Windows errors still abort at once, and an ownership change still stops the retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0a9f3de72c |
fix: make the full test suite pass on Windows (#2053)
* test: close resolution graphs before removing Windows fixtures
Close ArkTS and JVM graph connections in afterEach, including failed assertions. Verified both files on Windows 11 and macOS (32 tests).
* test: compare explore source lines across LF and CRLF checkouts
Normalize only line endings when matching emitted source against checked-out fixtures. Preserve the closure coverage and whole-line assertions. Both files pass on Windows 11 and macOS (15 tests).
* test: exercise old Git fallback without a POSIX shell shim
Inject only the unsupported ls-files invocation and run every other Git command against real repositories. Assert that each rejected call retries, use portable graph paths, and clean up fixtures. Passes on Windows 11 and macOS.
* test: normalize Python fixture before generating CRLF cases
The tests added in #2004 produced CRCRLF from a Windows checkout. Normalize the input to LF before constructing either variant. All 28 native and WASM cases pass on Windows 11 and macOS.
* test: allow time for eviction fixture indexes on Windows
The #2036 eviction test builds and reconciles nine real indexes and consistently exceeds its default five-second timeout on the VM. Allow 15 seconds for this test alone, preserving every assertion. The full file passes on Windows 11 and macOS (21 tests).
* test: finish MCP processes before resetting Windows fixtures
Launch actual servers with their runtime flags and await termination before directory removal. Use asynchronous removal retries for daemon fixtures. Establish a ready daemon and stop its first proxy before simulating PID reuse, then make source stale without opening a competing SQLite writer. Preserve lock and database byte-equality assertions. All touched files validated on Windows 11 and macOS.
* test: allow Windows named-pipe fallback polling to finish
The VM takes up to 25.7 seconds to complete the nominal six-second retry loop. Allow 30 seconds for the three fallback waits and 40 seconds for the two shorter enclosing tests, retaining their lock-preservation and read-only assertions. The full daemon file is validated on Windows 11 and macOS.
* fix(daemon): retry transient Windows PID-file sharing violations
A transient EPERM replacing daemon.pid aborted startup, observed in the quiet-client test and reproduced with a real locked handle at
|
||
|
|
1926ec39a2 |
fix(index): coordinate rebuilds with running MCP daemons (#1325) (#2051)
* fix: safely stop daemon before reindex * fix(index): coordinate rebuilds with running MCP daemons (#1325) Stop verified project daemons and confirm termination before recreating SQLite. Fence daemon and proxy reopening throughout rebuilds while preserving foreign and newer locks. Add Windows lifecycle coverage and cross-platform shutdown regressions. Co-authored-by: Harry B ✦ <drewavesx0@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): fence project opens during index rebuilds after rebase Carry the #1325 rebuild fence through the upstream explicit-project lifecycle, read-only engine opens, synchronous initialization retries, and direct writer acquisition. Preserve shared project leases, read-only fallback behavior, freshness handling, and direct-mode query pools. Cover watched, unwatched, and read-only engines blocking during a foreign rebuild and recovering after the fence is released. * fix(mcp): answer a running index rebuild as guidance, not a tool error (#1325) A projectPath call during `codegraph index` hit assertNoRebuild's plain Error and returned isError; it is an expected, temporary condition, so it now uses a RebuildInProgressError that the tool handler answers success-shaped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Harry B ✦ <drewavesx0@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
585f37066c |
fix(mcp): keep explicit projects synchronized (#1835) (#2036)
* fix(mcp): keep an explicit projectPath project in sync (#1835) A project opened through a tool call's `projectPath` (a repository other than the server's default — e.g. an indexed child of an un-indexed workspace) was opened read-only: no catch-up sync on open and no file watcher, so its answers went stale until someone ran `codegraph sync`. The engine now owns the lifecycle of every project the ToolHandler opens for an explicit path, mirroring the default project: - the project's writer lock is acquired (#1740 single-writer rule); if another live process holds it, that process keeps syncing and we only read; - a catch-up `sync()` runs on open and the first call against that project awaits it, time-boxed like the default gate (#905); - a file watcher runs for as long as the project stays cached. Bounds: the cache is keyed by the canonical (realpath) root, so a symlinked spelling shares one connection and one watcher; it is LRU with `MAX_CACHED_PROJECTS = 8` — opening a ninth closes the least recently used (watcher stopped, writer lock released, DB closed); `stop()` closes them all. Un-indexed paths still get the success-shaped guidance. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * fix(mcp): keep explicit projects synchronized (#1835) Explicit projectPath connections bypassed catch-up and synchronization ownership. Share canonical project leases and catch-up gates, retain daemon sessions, and retry ownership after a writer exits. Advertise direct-writer readiness and drain active work before eviction or shutdown. Add exact SQLite regressions for concurrent sessions, aliases, no-watch behavior, and teardown. Co-authored-by: danusha2345 <danusha2345@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): retry catch-up quietly on sync lock contention Handle LockUnavailableError without marking catch-up complete or logging an alarming failure, and verify timer-driven recovery against a real indexing lock. Make the eviction regression deterministic by applying its short timeout only to the held catch-up. Other projects must finish reconciling before the test can assert that the oldest eligible graph was closed. --------- Co-authored-by: danusha2345 <danusha2345@users.noreply.github.com> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> |