Skip to content

Indexing coverage & freshness: batch init, --git-hooks, opt-in auto-init - #1569

Open
rajeshguntupalli59 wants to merge 10 commits into
colbymchenry:mainfrom
rajeshguntupalli59:feature/indexing-coverage-and-freshness
Open

Indexing coverage & freshness: batch init, --git-hooks, opt-in auto-init#1569
rajeshguntupalli59 wants to merge 10 commits into
colbymchenry:mainfrom
rajeshguntupalli59:feature/indexing-coverage-and-freshness

Conversation

@rajeshguntupalli59

Copy link
Copy Markdown

Summary

Three additive features aimed at users running many small repos, where per-project codegraph init is 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.
  • Opt-in global auto-init — a new ~/.codegraph/config.json setting (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 run codegraph init manually. 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

  • Auto-init reuses the existing unsafeIndexRootReason and validateProjectPath guards 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.
  • A failed indexAll() (e.g. lock contention from a concurrent index) is treated as failure, not silently cached as an empty "indexed" project.
  • Concurrent auto-init of the same path from different MCP query-pool workers is handled: a losing worker's failure-triggered cleanup will not delete a winning worker's live or completed index (distinguished via the lock-contention error vs. a genuine failure).
  • --git-hooks skips the interactive prompt in both single-path and batch (--all) modes — an explicit flag is treated as consent.

Test plan

  • 20 new tests across the 5 components, all passing
  • npx tsc --noEmit clean
  • Existing directly-relevant suites (concurrent-locking, worktree-detection, all mcp-*, all cli-*) verified passing after the async conversion in getCodeGraph
  • Full npm test — I was unable to get a full-suite run to complete on my machine (Windows, limited RAM): it OOM-crashes deep in extraction.test.ts's WASM/tree-sitter tests, an area this PR doesn't touch. I confirmed this reproduces identically on a clean, unmodified main at 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.

rajeshguntupalli59 and others added 10 commits August 18, 2026 18:06
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.
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant