feat(hooks): auto-reindex after git commit with embeddings preservation
Add PostToolUse hook that re-runs `gitnexus analyze` after git commit/merge,
automatically detecting and preserving embeddings via meta.json stats.
- Persist embeddings count in meta.json stats.embeddings field
- Add PostToolUse handler to both hook variants (cjs + plugin)
- Register PostToolUse hook in setup.ts for Claude Code
- Add "Keeping the Index Fresh" section to generated CLAUDE.md/AGENTS.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
revert running gitanalyz
fix: address code review findings for auto-reindex hooks
- Fix hook timeout units: seconds not milliseconds (8000->8, 120000->120)
- Remove unused execFileSync import from gitnexus-hook.cjs
- Remove unused `output` variable in PostToolUse handler
- Remove spurious template interpolation in ai-context.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
refactor: clean up gitnexus-hook.cjs per review feedback
- Hoist spawnSync import to module scope
- Add shell: isWin for npx fallback on Windows
- Extract findGitNexusDir helper, reuse in both PreToolUse and PostToolUse
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix(hooks): stricter git regex, proper spawnSync error handling, embeddings in recovery commands
- Tighten commit/merge regex to not match git merge-base (require \s|$ after subcommand)
- Replace try/catch with child.error/signal inspection for spawnSync timeout detection
- Include --embeddings in manual recovery commands when embeddings were detected
- Extract emitPostToolContext helper to reduce duplication
- Apply all fixes to both hook variants (cjs + plugin)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fix(hooks): single-launch CLI resolution, guard PreToolUse stderr on failure
- Plugin: detect gitnexus binary via which/where once, then run exactly once
(prevents double execution when binary exists but command fails)
- Both hooks: only forward augment stderr as additionalContext when exit code
is 0, preventing CLI error output from leaking into agent context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
docs: update README and CLI skill for PostToolUse auto-reindex
- README: editor support table now shows PreToolUse + PostToolUse
- README: description mentions auto-reindex after commits
- gitnexus-cli skill: document auto-reindex in "When to run" section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
findEnclosingFunctionId generated IDs without :startLine suffix,
but node creation includes it. This caused every CALLS edge to
reference a non-existent source node, making the process detector
find 0 entry points and produce 0 execution flows.
Bumps to 1.3.9.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
KuzuDB's native module holds open handles that prevent Node.js from
exiting cleanly. Previously only force-exited when embeddings were used
(for ONNX Runtime segfault workaround), but the same issue affects all
analyze runs. Now always calls process.exit(0) after completion.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
CLAUDE.md and AGENTS.md now contain direct enforcement instructions instead
of a passive skill router table. Based on Vercel eval data showing skills
are skipped 56% of the time, and industry research on effective AGENTS.md
patterns from 2,500+ repos.
Key changes:
- Always/When/Never three-tier boundary structure
- RFC 2119 language (MUST, NEVER) for critical rules
- Exact tool commands with parameters inline
- Self-check checklist forcing model to verify its own work
- ~77 lines, well within the <150 line adherence threshold
Skills are still installed as bonus depth for Claude Code's skill system.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
When a repo has no parseable files (e.g., unsupported languages or all
files filtered out), chunks.reduce returns 0, causing createASTCache(0)
to pass max:0 to LRUCache which throws TypeError. This clamps maxSize
to at least 1 and adds a progress message when no parseable files exist.
Instead of crashing the pipeline when a native tree-sitter binding
(e.g. tree-sitter-swift) fails to build, skip those files early and
warn the user with an actionable message.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Resolved FUNCTION_NODE_TYPES: keep 'anonymous_function' for PHP (php_only grammar),
add Kotlin 'lambda_literal' and Swift 'init_declaration'/'deinit_declaration'
- Resolved pipeline.ts: adopt chunked pipeline structure, integrate
processRoutesFromExtracted into per-chunk worker data processing
- Resolved framework-detection.ts: use upstream AST-BASED FRAMEWORK DETECTION heading
- Fixed accumulated/mergeResult in parse-worker to include routes field
The Kotlin PR added tree-sitter-kotlin to package.json but didn't
include the lockfile update, causing npm ci to fail in CI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
forceExit killed the fork worker before local-backend.test.ts finished,
losing 12 test results. The real issue is KuzuDB's C++ destructor
segfaulting during fork process exit — all tests pass but vitest
reports the post-test crash as a failure.
dangerouslyIgnoreUnhandledErrors ignores the process-level crash
without affecting test results (98/98 tests still run and report).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
KuzuDB's C++ destructor crashes the vitest fork worker on exit,
causing a ~7 minute hang before timeout. forceExit kills the
worker immediately after tests complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GitHub Actions shallow clones don't have the root commit available,
causing checkStaleness to fail silently. HEAD~1 is always available.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 59 test files covering unit and integration tests
- vitest config with coverage thresholds and fork pooling
- Test fixtures (mini-repo + multi-language sample code)
- Add vitest + coverage-v8 to devDependencies
- Add test scripts (test, test:integration, test:all, test:watch, test:coverage)
- Move typescript to devDependencies where it belongs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge origin/main which moves tree-sitter-swift to optionalDependencies
with conditional imports. Reorder Kotlin entries before C/C++/PHP in all
files so they don't sit adjacent to Swift entries, preventing future
merge conflicts when upstream modifies Swift support.
The PR merge reverted the Swift install fix. tree-sitter-swift must be
in optionalDependencies with conditional createRequire imports, otherwise
npm install fails on systems where the native build can't succeed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The disconnect() method was unconditionally importing embedder.js on
every graceful shutdown, which loads @huggingface/transformers and
onnxruntime-node — triggering the exact crash this branch fixes.
Since process.exit(0) follows immediately, the OS reclaims all
resources without needing disposeEmbedder(). Matches the pattern
already established in analyze.ts (lines 318-320).
Fixes#89
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add endsWith('.*') check before appending wildcard suffix to prevent
possible double-append if grammar returns identifier text that already
includes the wildcard.
The heritage query only matched bare user_type delegation specifiers
(interface implementation), missing constructor_invocation patterns
used for class extension. Adds a second heritage pattern for
constructor invocations, capturing ~3x more heritage edges.
tree-sitter-kotlin (fwcd) has no interface_declaration node — both
interfaces and classes are class_declaration nodes. Use anonymous
keyword literal matching ("interface" vs "class") to produce the
correct @definition.interface / @definition.class captures.
Verified against two real Kotlin repos: a small one (3 Interface,
92 Class) and a large one (35 Interface, 677 Class, 5998 Function).
Convert static imports of @huggingface/transformers (which triggers
onnxruntime-node native binary loading) to dynamic import() calls.
This prevents crashes on Node versions whose ABI isn't supported by
the prebuilt onnxruntime binaries (e.g. Node v24).
Affected entry points:
- cli/analyze.ts: embedding pipeline only loaded when --embeddings is passed
- mcp/local/local-backend.ts: embedder only loaded on first semantic search
- server/api.ts: embedder only loaded when search endpoint needs embeddings
Fixes#89
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The module-level `let ftsLoaded` was declared twice (line 19 and 679),
causing TS2451. Removed the duplicate and cleaned up redundant
assignments in loadFTSExtension.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The MCP server called process.exit(1) at startup when no repositories
were found in the registry. This prevented users from configuring the
MCP integration before running `gitnexus analyze`.
The server now starts gracefully with 0 repos and discovers newly
indexed repos lazily via refreshRepos() on each tool call.
Closes#91
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The script now detects missing native binding and runs node-gyp rebuild
after patching. This handles the case where tree-sitter-swift's own
postinstall fails during npm install — our postinstall picks up,
patches binding.gyp, and rebuilds successfully.
Keep main's barLog implementation, preserve both currentDbPath and
ftsLoaded reset in closeKuzu, take PR's new resolveRepo pattern
for /api/query. Path traversal guard confirmed intact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>