fix(cli): never run daemon/catch-up when launched at $HOME or filesystem root#68
Merged
Conversation
…tem root An IDE (e.g. Kiro) launches 'serve --mcp' with no --path and CWD=$HOME, so the project defaulted to the home directory: the server spawned a daemon AND ran a catch-up sync that indexed the ENTIRE home tree, pegging a CPU at 99% (serve --mcp --path /config/. observed). The v0.15.2 home guard only gated the watcher; spawn_catch_up / sync_project_once were never guarded. Promote the home/filesystem-root detection in codegraph-watch into a public too_broad_root_reason() + TooBroadRoot, reused as the single source of truth by both the watcher guard (wording unchanged) and a new CLI should_run_daemon_services(). cmd_serve now, before selecting a serve mode, refuses a too-broad root: it serves tools off any existing index via serve_direct_no_services() but starts NO daemon, watcher, or catch-up, logging one clear line. serve_direct also gates spawn_catch_up behind the same predicate. Only an EXACT $HOME or filesystem-root match is too broad; a real project nested under $HOME (e.g. ~/workspace/.../codegraph-rust) is unaffected and keeps its daemon + catch-up. Canonicalization makes /config/. compare equal to $HOME. Covered by policy tests (home/root flagged, nested project not, $HOME/. normalized) and a CLI should_run_daemon_services test. Cargo.lock is the 0.15.2->0.15.3 sync.
Extend the existing home/filesystem-root note: when the resolved root is exactly $HOME or /, the server now disables the daemon and catch-up sync in addition to the watcher (an IDE launching serve --mcp from $HOME would otherwise index the whole home tree and peg a CPU at 99%). Tools still answer off any existing index; a real project nested under $HOME is unaffected; pin --path to get per-project services.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes two symptoms a user saw in
ps(on v0.15.3): an IDE (Kiro) launchingcodegraph serve --mcpwith CWD=$HOME spawned a daemonserve --mcp --path /config/.that pegged a CPU at 99%, indexing the entire home tree.Root cause
cmd_servedefaults the project to the process CWD when no--pathis given. Kiro launches the stdio server with the workspace's FIRST root folder as CWD, which for this user resolves to$HOME. With a$HOME/.codegraphpresent, the server entered SpawnOrProxy → spawned a daemon AND ranspawn_catch_up→sync_project_once($HOME), indexing the whole home tree. v0.15.2's home guard only gated the WATCHER; the daemon spawn and catch-up were never guarded.Fix
codegraph-watchinto a publictoo_broad_root_reason()+TooBroadRoot, the single source of truth (the watcher'shome_or_too_broad_root_reasonnow delegates to the sameclassify_too_broad_root, keeping its wording → watcher behavior unchanged).cmd_serveconsults it BEFORE selecting a serve mode: when the resolved root is exactly$HOMEor/, it serves tools off any existing index viaserve_direct_no_services(NO daemon, NO watcher, NO catch-up) and logs one clear line. Never enters SpawnOrProxy/BeDaemon.serve_directgatesspawn_catch_upbehindshould_run_daemon_services(the 99% CPU source).$HOME(e.g.~/projects/myapp) is UNAFFECTED — full daemon + catch-up. Only an EXACT$HOME/filesystem-root match is too broad;/config/.canonicalizes to equal$HOME.Clarifying the "two daemons" question
Daemons are shared PER PROJECT ROOT (same root → same socket → shared). The two daemons in the user's
psdiffered only because Kiro used the wrong root ($HOME). With this fix a $HOME launch runs daemon-less; a real project still spawns ONE daemon shared by all its windows' proxies (verified: 1 daemon + 2 proxies).Verification
cargo test -p codegraph-watch -p codegraph-rs: pass (3 new tests + watcher behavior unchanged)cargo clippy --workspace --all-targets -- -D warnings: exit 0cargo fmt --all --check: exit 0bash scripts/guardrail.sh: exit 0git status --porcelain reference/golden/: cleanScope
No new EdgeKind/NodeKind, no new dependency, no hand version bump (Cargo.lock 0.15.2→0.15.3 sync), confined to codegraph-cli / codegraph-watch + docs.
Deferred follow-up (documented, NOT in this release)
The deeper "Kiro auto-discovers its real workspace" fix is deferred: Kiro does NOT push
rootUri/workspaceFoldersininitialize(confirmed) but DOES support the server-drivenroots/listflow — implementing that (+ deferring daemon spawn until the workspace is resolved) is a larger transport change for its own release. Until then a $HOME-launched window runs daemon-less but safe; pin--pathto opt into a shared per-project daemon.Final Verification Wave: F1 (plan compliance), F2 (code quality), F3 (hands-on QA), F4 (scope fidelity) — all APPROVE.