Indexing coverage & freshness: batch init, --git-hooks, opt-in auto-init - #1569
Open
rajeshguntupalli59 wants to merge 10 commits into
Open
Conversation
Batch init (--all), a generalized --git-hooks flag, and an opt-in global auto-init setting for MCP-triggered indexing.
Five tasks: batch init (--all), generalized --git-hooks flag, global autoInit user-config, codegraph config CLI command, and MCP wiring.
…de, add regression test
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wire the opt-in global autoInit setting (Task 3's getAutoInit) into ToolHandler.getCodeGraph: when a project has no .codegraph/ and autoInit is on, index it automatically instead of just telling the agent to run `codegraph init`. Unsafe roots (home directory etc.) are still refused. getCodeGraph becomes async, which ripples to its private callers worktreeMismatchFor/withWorktreeNotice/withStalenessNotice (also made async) and all call sites (10 direct + 3 propagated). Fixes a test in concurrent-locking.test.ts that called the now-async getCodeGraph synchronously via an `as any` cast (missed by tsc since the cast opts out of type checking there).
Reviewer-found fixes to the auto-init branch added in c287067: - Critical: require the projectPath to already exist AND pass validateProjectPath before attempting auto-init, not just unsafeIndexRootReason (which doesn't cover ~/.ssh, ~/.aws, ~/.gnupg, ~/.config). Auto-init must only ever index a directory the user already has, never create one via CodeGraph.init's mkdirSync. - Critical: check indexAll()'s IndexResult.success instead of discarding it — a failed indexAll (e.g. contended file lock) was being cached and returned as if it succeeded, permanently leaving an empty "indexed but broken" .codegraph/ on disk. - Important: on any auto-init failure, close the opened DB connection and remove the partially-created .codegraph/ directory so the next call retries cleanly instead of leaking a handle or hitting "already initialized". - Important: de-dupe concurrent auto-init attempts for the same path onto one in-flight Promise (new autoInitInFlight map), so two simultaneous tool calls against the same unindexed project can't race two separate init/indexAll runs. Extracted the auto-init mechanics into a new private autoInitProject method. Added a test for the sensitive-nonexistent-path case and strengthened the "indexes automatically" test to assert real query content, not just that a .codegraph/ dir appeared.
…, README
Three findings from the whole-branch review.
1. (Critical) auto-init's failure cleanup could delete another query-pool
worker's live index. Each worker builds its own ToolHandler
(src/mcp/query-worker.ts), so autoInitProject's in-flight de-dup map — a
per-instance field — does not de-dupe across workers. Two workers can both
pass isInitialized on the same fresh path; the loser's indexAll RESOLVES
`{ success: false, errors: ['Could not acquire file lock ...'] }` rather
than throwing, and the catch block then rmSync'd the whole .codegraph/ —
the WINNER's in-progress index, out from under its open SQLite handle.
Contended failures are now tagged `skipCleanup` and the rmSync is gated on
it: the loser closes its handle and walks away, falling through to
NotIndexedError so the next call re-resolves and finds the finished index.
Genuine sole-owner failures still clean up as before.
2. (Important) `codegraph init --git-hooks` still opened an interactive
prompt in single-path mode: offerWatchFallback was passed
`yes: mode === 'batch'`, always false outside --all, so the user could
answer "manual" and get no hooks despite the flag — and a setup script or
CI run blocked on a prompt nobody could answer. An explicit --git-hooks
now implies yes in both modes.
3. (Important) Document `codegraph config get|set auto-init` and the new
`init --all` / `--git-hooks` flags in the README CLI Reference.
Tests: both new tests were verified to FAIL with their fix reverted.
- mcp-auto-init: a losing worker hitting the real FileLock (real pid-held
lock file, real contention result, real cleanup branch) leaves the winner's
directory byte-identical and still queryable from a fresh handler. Asserts
the whole directory listing, not just codegraph.db — on Windows rmSync
cannot unlink the open .db but does take out every unopened sibling first
(pre-fix it stripped .gitignore).
- cli-init-batch: single-path `init --git-hooks` against the built binary
with stdin at /dev/null and no `select` stub, so the hooks can only be
installed via the non-interactive path.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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
Three additive features aimed at users running many small repos, where per-project
codegraph initis easy to forget and the live watcher only runs while a session is open:codegraph init --all <dirs...>— batch-index many repos in one command, with a per-repo summary and continue-past-failure semantics.codegraph init --git-hooks— explicitly force-enable the existing git-hook freshness sync (installGitSyncHook) even when the live watcher isn't disabled, instead of it only being offered automatically on WSL2/CODEGRAPH_NO_WATCH.~/.codegraph/config.jsonsetting (codegraph config get|set auto-init) that, when on, makes the MCP server index an unindexed project on first query instead of just telling the agent to runcodegraph initmanually. Default is off; nothing changes for existing users unless they opt in.Design
Full design rationale and API surface: see the included spec doc (
docs/superpowers/specs/2026-08-18-indexing-coverage-and-freshness-design.md) and implementation plan (docs/superpowers/plans/2026-08-18-indexing-coverage-and-freshness.md).Notable implementation details
unsafeIndexRootReasonandvalidateProjectPathguards unchanged — it will not create an index under a home directory, filesystem root, or any sensitive path (~/.ssh,~/.aws, etc.), and only ever indexes a path that already exists on disk.indexAll()(e.g. lock contention from a concurrent index) is treated as failure, not silently cached as an empty "indexed" project.--git-hooksskips the interactive prompt in both single-path and batch (--all) modes — an explicit flag is treated as consent.Test plan
npx tsc --noEmitcleanconcurrent-locking,worktree-detection, allmcp-*, allcli-*) verified passing after the async conversion ingetCodeGraphnpm test— I was unable to get a full-suite run to complete on my machine (Windows, limited RAM): it OOM-crashes deep inextraction.test.ts's WASM/tree-sitter tests, an area this PR doesn't touch. I confirmed this reproduces identically on a clean, unmodifiedmainat the same point, so it's a pre-existing environment limit on this machine rather than anything this PR introduces — but I wasn't able to get a green full-suite run locally to report here, so flagging it explicitly for CI/maintainer verification.🤖 Built with Claude Code using a spec → plan → subagent-per-task implementation workflow, with an independent review pass (and one fix round) on every task plus a final whole-branch review.