Skip to content

Fix the indexer lifecycle, keep git history intact, and make the MCP surface truthful - #26

Merged
Phoenixrr2113 merged 1 commit into
mainfrom
fix/batch-two-indexer-truthfulness
Aug 21, 2026
Merged

Phoenixrr2113 merged 1 commit into
mainfrom
fix/batch-two-indexer-truthfulness

Conversation

@Phoenixrr2113

Copy link
Copy Markdown
Owner

What this fixes

Batch two of the pre-launch audit. Four work streams, each fixed test-first by a dedicated agent and then attacked by an independent reviewer across three empirical rounds against live fixture graphs. The review rounds found four defects the unit tests missed; all are fixed here.

Indexer and git history

  • The Project node was created only after indexing finished, but file linking used OPTIONAL MATCH on it, so HAS_FILE edges silently never existed and incremental indexing always re-parsed everything. The node is now upserted before any file work and again right after a full-reindex delete.
  • Git sync diffed every commit against its parent, which does not exist for a root commit, and the failure was swallowed. Root commits now diff against git's empty tree, and diff failures are logged.
  • Git reports repo-root-relative paths, but they were joined onto the indexed root, so indexing a subdirectory of a repo linked nothing. Paths now resolve through the real repo root, and files outside the indexed root are skipped.
  • On macOS, roots under /tmp or /var/folders resolved differently through git (symlink-resolved) than through path.resolve, so every file failed the boundary check and all history edges were dropped. The boundary check now compares realpath'd roots while edge paths stay in the caller's namespace so they match stored File paths byte for byte.
  • Re-indexing a changed file deleted the File node and every edge on it, destroying git history that the sync checkpoint never re-created. Content changes now replace only the file's symbols and update the File node in place; true deletions keep the old full-removal behavior.
  • registerTier2Languages() had no call site, so 29 tree-sitter languages indexed zero files. It is now called before file discovery, with grammar failures logged per language.

MCP truthfulness

  • The knowledge tool documented eight actions but its enum accepted two. All six missing actions had real backends and are now wired, with schema params verified against backend signatures. Recall's temporal and speaker params (at, from, to, timeline, speaker, includeExpired) are now declared. The description's semantic search example named a parameter that does not exist; it is fixed, and a new doc-consistency test asserts every example key is a declared schema property.
  • The profile route and codebase persona queried f.path and f.language, which do not exist on File nodes, so results were silently empty. They now use the real filePath and extension properties with an extension-to-language display map, and lastModified is correctly typed as an ISO string.
  • The project path filter used a bare prefix match, so /x/project also matched /x/project-extra and leaked a sibling project's files into the profile. Matching is now exact-or-boundary, and a relative projectPath returns a 400 from the route and an error from the persona instead of an empty result.

Label taxonomy

  • The node-label allowlist was hand-copied in nine places across four packages and had already drifted. One canonical set now lives in @codegraph/types with named subsets for each deliberate variation, membership locked by tests, and all sites migrated.
  • Node ids for Commit, MarkdownDocument, Section, CodeBlock, Link, and Entity nodes were built from symbol-only fields, so every Commit collided on the same id. Ids now key on each label's real MERGE identity.

Verification

  • pnpm turbo build: 21/21. pnpm turbo test: 33/33. pnpm release:check: passes, packaging smoke verifies database and dashboard.
  • Reviewer rounds ran the real indexer, git sync, MCP personas, and HTTP routes against ephemeral embedded databases with fixture git repos (subdirectory roots, symlinked tmp paths, root commits, sibling projects, tier-2 Ruby files).
  • Test counts: core 190, graph 72, api 148, mcp-server 76, types 14.

Known items deliberately not in this PR (ledger)

  • Incremental edge counters still report attempts, not stores.
  • plugin-nlp conversation chunker returned zero episodes from a two-line chat transcript.
  • getNeighborsImpl filters Entity nodes out entirely, so knowledge entities never appear as graph neighbors.
  • Import is declared as a node label but never materialized as a node.
  • The dashboard graph legend still carries its own label list (needs a color/shape map refactor).
  • getNodesPaginated is exported but has no production callers.

🤖 Generated with Claude Code

…surface truthful

Indexer: the Project node is now created before file linking, so HAS_FILE
edges exist and incremental indexing can finally skip unchanged files.
Git sync handles root commits (empty-tree diff), symlinked roots
(realpath boundary check with caller-namespace edge paths), and joins
git paths against the repo root instead of the indexed root. Tier-2
language registration is now actually called. Re-indexing a changed
file no longer deletes the File node, so MODIFIED_IN history survives
incremental runs and the file watcher.

MCP truthfulness: all eight documented knowledge actions are reachable
(six were rejected by the enum), recall's temporal and speaker params
are declared in the schema, and a doc-consistency test keeps every
description example honest. The profile route and codebase persona no
longer query phantom properties (f.path, f.language), match project
paths on directory boundaries so sibling projects cannot leak into each
other, and reject relative paths instead of returning silently empty.

Labels: one canonical label taxonomy in @codegraph/types replaces nine
hand-copied lists across graph, core, api, and dashboard, with tests
locking each deliberate subset. Node ids for Commit, MarkdownDocument,
Section, CodeBlock, Link, and Entity now key on their real MERGE
identity instead of colliding on empty symbol fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
v0-landing-page-build Skipped Skipped v0 Aug 21, 2026 6:48am

@Phoenixrr2113
Phoenixrr2113 merged commit 283579f into main Aug 21, 2026
12 checks passed
@Phoenixrr2113
Phoenixrr2113 deleted the fix/batch-two-indexer-truthfulness branch August 21, 2026 07:03

This branch was previously deployed

1 inactive deployment
Preview — 59047c4e Deployed Aug 21, 2026 by vercel[bot]
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