@veewo/gitnexus 1.3.11-rc.1 → 1.4.6-rc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -79
- package/dist/benchmark/agent-context/tool-runner.js +2 -2
- package/dist/benchmark/neonspark-candidates.js +3 -3
- package/dist/benchmark/tool-runner.js +2 -2
- package/dist/cli/ai-context.d.ts +2 -1
- package/dist/cli/ai-context.js +16 -12
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +68 -48
- package/dist/cli/augment.js +1 -1
- package/dist/cli/eval-server.d.ts +8 -1
- package/dist/cli/eval-server.js +30 -13
- package/dist/cli/index.js +28 -82
- package/dist/cli/lazy-action.d.ts +6 -0
- package/dist/cli/lazy-action.js +18 -0
- package/dist/cli/mcp.js +3 -1
- package/dist/cli/setup.js +87 -48
- package/dist/cli/setup.test.js +18 -13
- package/dist/cli/skill-gen.d.ts +26 -0
- package/dist/cli/skill-gen.js +549 -0
- package/dist/cli/status.js +13 -4
- package/dist/cli/tool.d.ts +3 -2
- package/dist/cli/tool.js +50 -16
- package/dist/cli/wiki.js +8 -4
- package/dist/config/ignore-service.d.ts +25 -0
- package/dist/config/ignore-service.js +76 -0
- package/dist/config/supported-languages.d.ts +4 -1
- package/dist/config/supported-languages.js +3 -2
- package/dist/core/augmentation/engine.js +94 -67
- package/dist/core/embeddings/embedder.d.ts +1 -1
- package/dist/core/embeddings/embedder.js +1 -1
- package/dist/core/embeddings/embedding-pipeline.d.ts +3 -3
- package/dist/core/embeddings/embedding-pipeline.js +52 -25
- package/dist/core/embeddings/types.d.ts +1 -1
- package/dist/core/graph/types.d.ts +7 -2
- package/dist/core/ingestion/ast-cache.js +3 -2
- package/dist/core/ingestion/call-processor.d.ts +8 -6
- package/dist/core/ingestion/call-processor.js +468 -206
- package/dist/core/ingestion/call-routing.d.ts +53 -0
- package/dist/core/ingestion/call-routing.js +108 -0
- package/dist/core/ingestion/constants.d.ts +16 -0
- package/dist/core/ingestion/constants.js +16 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +2 -1
- package/dist/core/ingestion/entry-point-scoring.js +116 -23
- package/dist/core/ingestion/export-detection.d.ts +18 -0
- package/dist/core/ingestion/export-detection.js +231 -0
- package/dist/core/ingestion/filesystem-walker.js +4 -3
- package/dist/core/ingestion/framework-detection.d.ts +19 -4
- package/dist/core/ingestion/framework-detection.js +182 -6
- package/dist/core/ingestion/heritage-processor.d.ts +13 -5
- package/dist/core/ingestion/heritage-processor.js +109 -55
- package/dist/core/ingestion/import-processor.d.ts +16 -20
- package/dist/core/ingestion/import-processor.js +199 -579
- package/dist/core/ingestion/language-config.d.ts +46 -0
- package/dist/core/ingestion/language-config.js +167 -0
- package/dist/core/ingestion/mro-processor.d.ts +45 -0
- package/dist/core/ingestion/mro-processor.js +369 -0
- package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
- package/dist/core/ingestion/named-binding-extraction.js +363 -0
- package/dist/core/ingestion/parsing-processor.d.ts +4 -1
- package/dist/core/ingestion/parsing-processor.js +107 -109
- package/dist/core/ingestion/pipeline.d.ts +6 -3
- package/dist/core/ingestion/pipeline.js +208 -114
- package/dist/core/ingestion/process-processor.js +8 -2
- package/dist/core/ingestion/resolution-context.d.ts +53 -0
- package/dist/core/ingestion/resolution-context.js +132 -0
- package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
- package/dist/core/ingestion/resolvers/csharp.js +109 -0
- package/dist/core/ingestion/resolvers/go.d.ts +19 -0
- package/dist/core/ingestion/resolvers/go.js +42 -0
- package/dist/core/ingestion/resolvers/index.d.ts +18 -0
- package/dist/core/ingestion/resolvers/index.js +13 -0
- package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
- package/dist/core/ingestion/resolvers/jvm.js +87 -0
- package/dist/core/ingestion/resolvers/php.d.ts +15 -0
- package/dist/core/ingestion/resolvers/php.js +35 -0
- package/dist/core/ingestion/resolvers/python.d.ts +19 -0
- package/dist/core/ingestion/resolvers/python.js +52 -0
- package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
- package/dist/core/ingestion/resolvers/ruby.js +15 -0
- package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
- package/dist/core/ingestion/resolvers/rust.js +73 -0
- package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
- package/dist/core/ingestion/resolvers/standard.js +123 -0
- package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
- package/dist/core/ingestion/resolvers/utils.js +122 -0
- package/dist/core/ingestion/symbol-table.d.ts +21 -1
- package/dist/core/ingestion/symbol-table.js +40 -12
- package/dist/core/ingestion/tree-sitter-queries.d.ts +13 -10
- package/dist/core/ingestion/tree-sitter-queries.js +297 -7
- package/dist/core/ingestion/type-env.d.ts +49 -0
- package/dist/core/ingestion/type-env.js +611 -0
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
- package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/csharp.js +383 -0
- package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/go.js +467 -0
- package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
- package/dist/core/ingestion/type-extractors/index.js +31 -0
- package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
- package/dist/core/ingestion/type-extractors/jvm.js +681 -0
- package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/php.js +549 -0
- package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/python.js +406 -0
- package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/ruby.js +389 -0
- package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/rust.js +449 -0
- package/dist/core/ingestion/type-extractors/shared.d.ts +133 -0
- package/dist/core/ingestion/type-extractors/shared.js +703 -0
- package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/swift.js +137 -0
- package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
- package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
- package/dist/core/ingestion/type-extractors/typescript.js +494 -0
- package/dist/core/ingestion/utils.d.ts +103 -0
- package/dist/core/ingestion/utils.js +1085 -4
- package/dist/core/ingestion/workers/parse-worker.d.ts +51 -4
- package/dist/core/ingestion/workers/parse-worker.js +634 -222
- package/dist/core/ingestion/workers/worker-pool.js +8 -0
- package/dist/core/{kuzu → lbug}/csv-generator.d.ts +12 -10
- package/dist/core/{kuzu → lbug}/csv-generator.js +82 -101
- package/dist/core/{kuzu/kuzu-adapter.d.ts → lbug/lbug-adapter.d.ts} +20 -25
- package/dist/core/{kuzu/kuzu-adapter.js → lbug/lbug-adapter.js} +150 -122
- package/dist/core/{kuzu → lbug}/schema.d.ts +4 -4
- package/dist/core/{kuzu → lbug}/schema.js +23 -22
- package/dist/core/lbug/schema.test.d.ts +1 -0
- package/dist/core/search/bm25-index.d.ts +4 -4
- package/dist/core/search/bm25-index.js +12 -11
- package/dist/core/search/hybrid-search.d.ts +2 -2
- package/dist/core/search/hybrid-search.js +6 -6
- package/dist/core/tree-sitter/parser-loader.d.ts +1 -0
- package/dist/core/tree-sitter/parser-loader.js +19 -0
- package/dist/core/wiki/generator.d.ts +2 -2
- package/dist/core/wiki/generator.js +6 -6
- package/dist/core/wiki/graph-queries.d.ts +4 -4
- package/dist/core/wiki/graph-queries.js +7 -7
- package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
- package/dist/mcp/compatible-stdio-transport.js +200 -0
- package/dist/mcp/core/{kuzu-adapter.d.ts → lbug-adapter.d.ts} +11 -10
- package/dist/mcp/core/lbug-adapter.js +327 -0
- package/dist/mcp/local/local-backend.d.ts +21 -16
- package/dist/mcp/local/local-backend.js +306 -706
- package/dist/mcp/local/unity-parity-seed-loader.d.ts +6 -1
- package/dist/mcp/local/unity-parity-seed-loader.js +119 -9
- package/dist/mcp/local/unity-parity-seed-loader.test.js +95 -7
- package/dist/mcp/resources.js +2 -2
- package/dist/mcp/server.js +28 -13
- package/dist/mcp/staleness.js +2 -2
- package/dist/mcp/tools.js +12 -3
- package/dist/server/api.js +12 -12
- package/dist/server/mcp-http.d.ts +1 -1
- package/dist/server/mcp-http.js +1 -1
- package/dist/storage/git.js +4 -1
- package/dist/storage/repo-manager.d.ts +20 -2
- package/dist/storage/repo-manager.js +74 -4
- package/dist/types/pipeline.d.ts +1 -1
- package/hooks/claude/gitnexus-hook.cjs +149 -46
- package/hooks/claude/pre-tool-use.sh +2 -1
- package/hooks/claude/session-start.sh +0 -0
- package/package.json +20 -4
- package/scripts/patch-tree-sitter-swift.cjs +74 -0
- package/skills/gitnexus-cli.md +8 -8
- package/skills/gitnexus-debugging.md +1 -1
- package/skills/gitnexus-exploring.md +1 -1
- package/skills/gitnexus-guide.md +1 -1
- package/skills/gitnexus-impact-analysis.md +1 -1
- package/skills/gitnexus-pr-review.md +163 -0
- package/skills/gitnexus-refactoring.md +1 -1
- package/dist/cli/claude-hooks.d.ts +0 -22
- package/dist/cli/claude-hooks.js +0 -97
- package/dist/mcp/core/kuzu-adapter.js +0 -231
- /package/dist/core/{kuzu/csv-generator.test.d.ts → ingestion/type-extractors/types.js} +0 -0
- /package/dist/core/{kuzu/relationship-pair-buckets.test.d.ts → lbug/csv-generator.test.d.ts} +0 -0
- /package/dist/core/{kuzu → lbug}/csv-generator.test.js +0 -0
- /package/dist/core/{kuzu → lbug}/relationship-pair-buckets.d.ts +0 -0
- /package/dist/core/{kuzu → lbug}/relationship-pair-buckets.js +0 -0
- /package/dist/core/{kuzu/schema.test.d.ts → lbug/relationship-pair-buckets.test.d.ts} +0 -0
- /package/dist/core/{kuzu → lbug}/relationship-pair-buckets.test.js +0 -0
- /package/dist/core/{kuzu → lbug}/schema.test.js +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Graph-powered code intelligence for AI agents.** Index any codebase into a knowledge graph, then query it via MCP or CLI.
|
|
4
4
|
|
|
5
|
-
Works with **Cursor**, **Claude Code**, **
|
|
5
|
+
Works with **Cursor**, **Claude Code**, **Windsurf**, **Cline**, **OpenCode**, and any MCP-compatible tool.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/gitnexus)
|
|
8
8
|
[](https://polyformproject.org/licenses/noncommercial/1.0.0/)
|
|
@@ -19,31 +19,14 @@ AI coding tools don't understand your codebase structure. They edit a function w
|
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
# Index your repo (run from repo root)
|
|
22
|
-
npx gitnexus analyze
|
|
22
|
+
npx -y @veewo/gitnexus@latest analyze
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
That's it. This indexes the codebase,
|
|
25
|
+
That's it. This indexes the codebase, installs agent skills, registers Claude Code hooks, and creates `AGENTS.md` / `CLAUDE.md` context files — all in one command.
|
|
26
26
|
|
|
27
|
-
To configure MCP
|
|
27
|
+
To configure MCP for your editor, run `npx -y @veewo/gitnexus@latest setup` once — or set it up manually below.
|
|
28
28
|
|
|
29
|
-
`gitnexus setup`
|
|
30
|
-
- `--agent claude`: configure Claude MCP only
|
|
31
|
-
- `--agent opencode`: configure OpenCode MCP only
|
|
32
|
-
- `--agent codex`: configure Codex MCP only
|
|
33
|
-
|
|
34
|
-
It also supports two scopes:
|
|
35
|
-
- `global` (default): writes MCP to the selected agent's global config + installs global skills
|
|
36
|
-
- `project`: writes MCP to the selected agent's project-local config + installs repo-local skills
|
|
37
|
-
|
|
38
|
-
## Team Deployment and Distribution
|
|
39
|
-
|
|
40
|
-
For small-team rollout (single stable channel only), follow:
|
|
41
|
-
- [CLI Deployment and Distribution](../docs/cli-release-distribution.md)
|
|
42
|
-
|
|
43
|
-
Key links:
|
|
44
|
-
- [npm publish workflow](../.github/workflows/publish.yml)
|
|
45
|
-
- [CLI package config](./package.json)
|
|
46
|
-
- [Agent install + acceptance runbook](../INSTALL-GUIDE.md)
|
|
29
|
+
`gitnexus setup` auto-detects your editors and writes the correct global MCP config. You only need to run it once.
|
|
47
30
|
|
|
48
31
|
### Editor Support
|
|
49
32
|
|
|
@@ -51,7 +34,6 @@ Key links:
|
|
|
51
34
|
|--------|-----|--------|---------------------|---------|
|
|
52
35
|
| **Claude Code** | Yes | Yes | Yes (PreToolUse) | **Full** |
|
|
53
36
|
| **Cursor** | Yes | Yes | — | MCP + Skills |
|
|
54
|
-
| **Codex** | Yes | Yes | — | MCP + Skills |
|
|
55
37
|
| **Windsurf** | Yes | — | — | MCP |
|
|
56
38
|
| **OpenCode** | Yes | Yes | — | MCP + Skills |
|
|
57
39
|
|
|
@@ -90,25 +72,19 @@ Add to `~/.cursor/mcp.json` (global — works for all projects):
|
|
|
90
72
|
|
|
91
73
|
### OpenCode
|
|
92
74
|
|
|
93
|
-
Add to `~/.config/opencode/
|
|
75
|
+
Add to `~/.config/opencode/config.json`:
|
|
94
76
|
|
|
95
77
|
```json
|
|
96
78
|
{
|
|
97
79
|
"mcp": {
|
|
98
80
|
"gitnexus": {
|
|
99
|
-
"
|
|
100
|
-
"
|
|
81
|
+
"command": "npx",
|
|
82
|
+
"args": ["-y", "@veewo/gitnexus@latest", "mcp"]
|
|
101
83
|
}
|
|
102
84
|
}
|
|
103
85
|
}
|
|
104
86
|
```
|
|
105
87
|
|
|
106
|
-
### Codex
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
codex mcp add gitnexus -- npx -y @veewo/gitnexus@latest mcp
|
|
110
|
-
```
|
|
111
|
-
|
|
112
88
|
## How It Works
|
|
113
89
|
|
|
114
90
|
GitNexus builds a complete knowledge graph of your codebase through a multi-phase indexing pipeline:
|
|
@@ -120,7 +96,7 @@ GitNexus builds a complete knowledge graph of your codebase through a multi-phas
|
|
|
120
96
|
5. **Processes** — Traces execution flows from entry points through call chains
|
|
121
97
|
6. **Search** — Builds hybrid search indexes for fast retrieval
|
|
122
98
|
|
|
123
|
-
The result is a **
|
|
99
|
+
The result is a **LadybugDB graph database** stored locally in `.gitnexus/` with full-text search and semantic embeddings.
|
|
124
100
|
|
|
125
101
|
## MCP Tools
|
|
126
102
|
|
|
@@ -160,14 +136,11 @@ Your AI agent gets these tools automatically:
|
|
|
160
136
|
## CLI Commands
|
|
161
137
|
|
|
162
138
|
```bash
|
|
163
|
-
gitnexus setup
|
|
164
|
-
gitnexus
|
|
165
|
-
|
|
166
|
-
gitnexus analyze
|
|
167
|
-
gitnexus analyze --
|
|
168
|
-
gitnexus analyze --embeddings # Enable semantic embeddings (off by default)
|
|
169
|
-
gitnexus analyze --scope-prefix Assets/NEON/Code --scope-prefix Packages/com.veewo.* # Scoped multi-directory indexing
|
|
170
|
-
gitnexus analyze --scope-manifest .gitnexus/sync-manifest.txt --repo-alias neonspark-v1-subset # Scoped indexing + stable repo alias
|
|
139
|
+
gitnexus setup # Configure MCP for your editors (one-time)
|
|
140
|
+
npx -y @veewo/gitnexus@latest analyze [path] # Index a repository (or update stale index)
|
|
141
|
+
npx -y @veewo/gitnexus@latest analyze --force # Force full re-index
|
|
142
|
+
npx -y @veewo/gitnexus@latest analyze --embeddings # Enable embedding generation (slower, better search)
|
|
143
|
+
npx -y @veewo/gitnexus@latest analyze --verbose # Log skipped files when parsers are unavailable
|
|
171
144
|
gitnexus mcp # Start MCP server (stdio) — serves all indexed repos
|
|
172
145
|
gitnexus serve # Start local HTTP server (multi-repo) for web UI
|
|
173
146
|
gitnexus list # List all indexed repositories
|
|
@@ -176,45 +149,35 @@ gitnexus clean # Delete index for current repo
|
|
|
176
149
|
gitnexus clean --all --force # Delete all indexes
|
|
177
150
|
gitnexus wiki [path] # Generate LLM-powered docs from knowledge graph
|
|
178
151
|
gitnexus wiki --model <model> # Wiki with custom LLM model (default: gpt-4o-mini)
|
|
179
|
-
gitnexus unity-bindings <symbol> --target-path <path> [--json] # Experimental Unity C# <-> prefab/scene/asset cross-reference
|
|
180
|
-
gitnexus context <symbol> --unity-resources on # Include graph-native Unity resource data (opt-in)
|
|
181
|
-
gitnexus query <symbol> --unity-resources on # Enrich query symbol hits with Unity resource data (opt-in)
|
|
182
|
-
gitnexus benchmark-unity ../benchmarks/unity-baseline/v1 --profile quick --target-path ../benchmarks/fixtures/unity-mini
|
|
183
|
-
gitnexus benchmark-unity ../benchmarks/unity-baseline/v1 --profile full --target-path ../benchmarks/fixtures/unity-mini
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
For scoped indexing, `analyze` logs scope overlap dedupe counts and any normalized path collisions to help diagnose multi-directory merge safety.
|
|
187
|
-
|
|
188
|
-
Unity resource retrieval is opt-in on `query/context` via `unity_resources: off|on|auto` (default: `off`). Use `--unity-resources on` when you need `resourceBindings`, `serializedFields`, `resolvedReferences`, and `unityDiagnostics` in output.
|
|
189
|
-
|
|
190
|
-
## Unity Benchmark
|
|
191
|
-
|
|
192
|
-
Run reproducible Unity/C# accuracy and regression checks:
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
gitnexus benchmark-unity ../benchmarks/unity-baseline/v1 --profile quick --target-path ../benchmarks/fixtures/unity-mini
|
|
196
|
-
gitnexus benchmark-unity ../benchmarks/unity-baseline/v1 --profile full --target-path ../benchmarks/fixtures/unity-mini
|
|
197
152
|
```
|
|
198
153
|
|
|
199
|
-
|
|
154
|
+
## Multi-Repo Support
|
|
200
155
|
|
|
201
|
-
|
|
156
|
+
GitNexus supports indexing multiple repositories. Each `npx -y @veewo/gitnexus@latest analyze` registers the repo in a global registry (`~/.gitnexus/registry.json`). The MCP server serves all indexed repos automatically.
|
|
202
157
|
|
|
203
|
-
|
|
204
|
-
|--------|-----------|
|
|
205
|
-
| Query precision | `>= 0.90` |
|
|
206
|
-
| Query recall | `>= 0.85` |
|
|
207
|
-
| Context/impact F1 | `>= 0.80` |
|
|
208
|
-
| Smoke pass rate | `= 1.00` |
|
|
209
|
-
| Analyze time regression | `<= +15%` |
|
|
158
|
+
## Supported Languages
|
|
210
159
|
|
|
211
|
-
|
|
160
|
+
TypeScript, JavaScript, Python, Java, C, C++, C#, Go, Rust, PHP, Kotlin, Swift, Ruby
|
|
212
161
|
|
|
213
|
-
|
|
162
|
+
### Language Feature Matrix
|
|
214
163
|
|
|
215
|
-
|
|
164
|
+
| Language | Imports | Named Bindings | Exports | Heritage | Type Annotations | Constructor Inference | Config | Frameworks | Entry Points |
|
|
165
|
+
|----------|---------|----------------|---------|----------|-----------------|---------------------|--------|------------|-------------|
|
|
166
|
+
| TypeScript | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
167
|
+
| JavaScript | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ | ✓ | ✓ |
|
|
168
|
+
| Python | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
169
|
+
| Java | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
|
|
170
|
+
| Kotlin | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
|
|
171
|
+
| C# | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
172
|
+
| Go | ✓ | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
173
|
+
| Rust | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
|
|
174
|
+
| PHP | ✓ | ✓ | ✓ | — | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
175
|
+
| Ruby | ✓ | — | ✓ | ✓ | — | ✓ | — | ✓ | ✓ |
|
|
176
|
+
| Swift | — | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
177
|
+
| C | — | — | ✓ | — | ✓ | ✓ | — | ✓ | ✓ |
|
|
178
|
+
| C++ | — | — | ✓ | ✓ | ✓ | ✓ | — | ✓ | ✓ |
|
|
216
179
|
|
|
217
|
-
|
|
180
|
+
**Imports** — cross-file import resolution · **Named Bindings** — `import { X as Y }` / re-export tracking · **Exports** — public/exported symbol detection · **Heritage** — class inheritance, interfaces, mixins · **Type Annotations** — explicit type extraction for receiver resolution · **Constructor Inference** — infer receiver type from constructor calls (`self`/`this` resolution included for all languages) · **Config** — language toolchain config parsing (tsconfig, go.mod, etc.) · **Frameworks** — AST-based framework pattern detection · **Entry Points** — entry point scoring heuristics
|
|
218
181
|
|
|
219
182
|
## Agent Skills
|
|
220
183
|
|
|
@@ -225,13 +188,7 @@ GitNexus ships with skill files that teach AI agents how to use the tools effect
|
|
|
225
188
|
- **Impact Analysis** — Analyze blast radius before changes
|
|
226
189
|
- **Refactoring** — Plan safe refactors using dependency mapping
|
|
227
190
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
- `gitnexus setup` controls skill scope:
|
|
231
|
-
- requires `--agent <claude|opencode|codex>`
|
|
232
|
-
- default `global`: installs to `~/.agents/skills/gitnexus/`
|
|
233
|
-
- `--scope project`: installs to `.agents/skills/gitnexus/` in current repo
|
|
234
|
-
- `gitnexus analyze` always updates `AGENTS.md` / `CLAUDE.md`; skill install follows configured setup scope.
|
|
191
|
+
Installed automatically by both `npx -y @veewo/gitnexus@latest analyze` (per-repo) and `gitnexus setup` (global).
|
|
235
192
|
|
|
236
193
|
## Requirements
|
|
237
194
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { closeLbug } from '../../mcp/core/lbug-adapter.js';
|
|
2
2
|
import { LocalBackend } from '../../mcp/local/local-backend.js';
|
|
3
3
|
export async function createAgentContextToolRunner() {
|
|
4
4
|
const backend = new LocalBackend();
|
|
@@ -12,7 +12,7 @@ export async function createAgentContextToolRunner() {
|
|
|
12
12
|
impact: (params) => backend.callTool('impact', params),
|
|
13
13
|
cypher: (params) => backend.callTool('cypher', params),
|
|
14
14
|
close: async () => {
|
|
15
|
-
await
|
|
15
|
+
await closeLbug();
|
|
16
16
|
},
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -2,7 +2,7 @@ import fs from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { listRegisteredRepos } from '../storage/repo-manager.js';
|
|
5
|
-
import {
|
|
5
|
+
import { closeLbug, executeQuery, initLbug } from '../mcp/core/lbug-adapter.js';
|
|
6
6
|
const ALLOWED_PREFIXES = ['Assets/NEON/Code/', 'Packages/com.veewo.', 'Packages/com.neonspark.'];
|
|
7
7
|
export function filterNeonsparkPaths(rows) {
|
|
8
8
|
return rows.filter((r) => {
|
|
@@ -25,7 +25,7 @@ export async function extractCandidates(repoName, outFile) {
|
|
|
25
25
|
const repo = repos.find((r) => r.name === repoName);
|
|
26
26
|
if (!repo)
|
|
27
27
|
throw new Error(`repo not indexed: ${repoName}`);
|
|
28
|
-
await
|
|
28
|
+
await initLbug(repoName, path.join(repo.storagePath, 'lbug'));
|
|
29
29
|
try {
|
|
30
30
|
const rows = await executeQuery(repoName, `
|
|
31
31
|
MATCH (s:Class)
|
|
@@ -67,7 +67,7 @@ export async function extractCandidates(repoName, outFile) {
|
|
|
67
67
|
return normalized.length;
|
|
68
68
|
}
|
|
69
69
|
finally {
|
|
70
|
-
await
|
|
70
|
+
await closeLbug(repoName);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
export function parseCandidatesCliArgs(argv) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { closeLbug } from '../mcp/core/lbug-adapter.js';
|
|
2
2
|
import { LocalBackend } from '../mcp/local/local-backend.js';
|
|
3
3
|
export async function createToolRunner() {
|
|
4
4
|
const backend = new LocalBackend();
|
|
@@ -11,7 +11,7 @@ export async function createToolRunner() {
|
|
|
11
11
|
context: (params) => backend.callTool('context', params),
|
|
12
12
|
impact: (params) => backend.callTool('impact', params),
|
|
13
13
|
close: async () => {
|
|
14
|
-
await
|
|
14
|
+
await closeLbug();
|
|
15
15
|
},
|
|
16
16
|
};
|
|
17
17
|
}
|
package/dist/cli/ai-context.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* AGENTS.md is the standard read by Cursor, Windsurf, OpenCode, Codex, Cline, etc.
|
|
6
6
|
* CLAUDE.md is for Claude Code which only reads that file.
|
|
7
7
|
*/
|
|
8
|
+
import { type GeneratedSkillInfo } from './skill-gen.js';
|
|
8
9
|
type SkillScope = 'project' | 'global';
|
|
9
10
|
interface RepoStats {
|
|
10
11
|
files?: number;
|
|
@@ -19,7 +20,7 @@ interface RepoStats {
|
|
|
19
20
|
*/
|
|
20
21
|
export declare function generateAIContextFiles(repoPath: string, _storagePath: string, projectName: string, stats: RepoStats, options?: {
|
|
21
22
|
skillScope?: SkillScope;
|
|
22
|
-
}): Promise<{
|
|
23
|
+
}, generatedSkills?: GeneratedSkillInfo[]): Promise<{
|
|
23
24
|
files: string[];
|
|
24
25
|
}>;
|
|
25
26
|
export {};
|
package/dist/cli/ai-context.js
CHANGED
|
@@ -16,17 +16,21 @@ const GITNEXUS_END_MARKER = '<!-- gitnexus:end -->';
|
|
|
16
16
|
/**
|
|
17
17
|
* Generate the full GitNexus context content.
|
|
18
18
|
*
|
|
19
|
-
* Design principles (learned from real agent behavior):
|
|
20
|
-
* -
|
|
21
|
-
* -
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
24
|
-
* -
|
|
19
|
+
* Design principles (learned from real agent behavior and industry research):
|
|
20
|
+
* - Inline critical workflows — skills are skipped 56% of the time (Vercel eval data)
|
|
21
|
+
* - Use RFC 2119 language (MUST, NEVER, ALWAYS) — models follow imperative rules
|
|
22
|
+
* - Three-tier boundaries (Always/When/Never) — proven to change model behavior
|
|
23
|
+
* - Keep under 120 lines — adherence degrades past 150 lines
|
|
24
|
+
* - Exact tool commands with parameters — vague directives get ignored
|
|
25
|
+
* - Self-review checklist — forces model to verify its own work
|
|
25
26
|
*/
|
|
26
|
-
function generateGitNexusContent(projectName, stats, skillScope) {
|
|
27
|
+
function generateGitNexusContent(projectName, stats, skillScope, generatedSkills) {
|
|
27
28
|
const skillRoot = skillScope === 'global'
|
|
28
29
|
? '~/.agents/skills/gitnexus'
|
|
29
30
|
: '.agents/skills/gitnexus';
|
|
31
|
+
const generatedRows = (generatedSkills && generatedSkills.length > 0)
|
|
32
|
+
? `\n${generatedSkills.map((s) => `| Work in the ${s.label} area (${s.symbolCount} symbols) | \`.claude/skills/generated/${s.name}/SKILL.md\` |`).join('\n')}`
|
|
33
|
+
: '';
|
|
30
34
|
return `${GITNEXUS_START_MARKER}
|
|
31
35
|
# GitNexus MCP
|
|
32
36
|
|
|
@@ -38,7 +42,7 @@ This project is indexed by GitNexus as **${projectName}** (${stats.nodes || 0} s
|
|
|
38
42
|
2. **Match your task to a skill below** and **read that skill file**
|
|
39
43
|
3. **Follow the skill's workflow and checklist**
|
|
40
44
|
|
|
41
|
-
> If step 1 warns the index is stale, ask user whether to rebuild index via \`npx -y gitnexus analyze\` first (it reuses previous analyze scope/options by default; add \`--no-reuse-options\` to reset). If user declines, explicitly warn that retrieval may not reflect current codebase. For build/analyze/test commands, use a 10-30 minute timeout; on failure/timeout, report exact tool output and do not auto-retry or silently fall back to glob/grep.
|
|
45
|
+
> If step 1 warns the index is stale, ask user whether to rebuild index via \`npx -y @veewo/gitnexus@latest analyze\` first (it reuses previous analyze scope/options by default; add \`--no-reuse-options\` to reset). If user declines, explicitly warn that retrieval may not reflect current codebase. For build/analyze/test commands, use a 10-30 minute timeout; on failure/timeout, report exact tool output and do not auto-retry or silently fall back to glob/grep.
|
|
42
46
|
|
|
43
47
|
## Skills
|
|
44
48
|
|
|
@@ -49,7 +53,7 @@ This project is indexed by GitNexus as **${projectName}** (${stats.nodes || 0} s
|
|
|
49
53
|
| Trace bugs / "Why is X failing?" | \`${skillRoot}/gitnexus-debugging/SKILL.md\` |
|
|
50
54
|
| Rename / extract / split / refactor | \`${skillRoot}/gitnexus-refactoring/SKILL.md\` |
|
|
51
55
|
| Tools, resources, schema reference | \`${skillRoot}/gitnexus-guide/SKILL.md\` |
|
|
52
|
-
| Index, status, clean, wiki CLI commands | \`${skillRoot}/gitnexus-cli/SKILL.md\`
|
|
56
|
+
| Index, status, clean, wiki CLI commands | \`${skillRoot}/gitnexus-cli/SKILL.md\` |${generatedRows}
|
|
53
57
|
|
|
54
58
|
${GITNEXUS_END_MARKER}`;
|
|
55
59
|
}
|
|
@@ -81,7 +85,7 @@ async function upsertGitNexusSection(filePath, content) {
|
|
|
81
85
|
// Check if GitNexus section already exists
|
|
82
86
|
const startIdx = existingContent.indexOf(GITNEXUS_START_MARKER);
|
|
83
87
|
const endIdx = existingContent.indexOf(GITNEXUS_END_MARKER);
|
|
84
|
-
if (startIdx !== -1 && endIdx !== -1) {
|
|
88
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
85
89
|
// Replace existing section
|
|
86
90
|
const before = existingContent.substring(0, startIdx);
|
|
87
91
|
const after = existingContent.substring(endIdx + GITNEXUS_END_MARKER.length);
|
|
@@ -167,9 +171,9 @@ Use GitNexus tools to accomplish this task.
|
|
|
167
171
|
/**
|
|
168
172
|
* Generate AI context files after indexing
|
|
169
173
|
*/
|
|
170
|
-
export async function generateAIContextFiles(repoPath, _storagePath, projectName, stats, options) {
|
|
174
|
+
export async function generateAIContextFiles(repoPath, _storagePath, projectName, stats, options, generatedSkills) {
|
|
171
175
|
const skillScope = options?.skillScope === 'global' ? 'global' : 'project';
|
|
172
|
-
const content = generateGitNexusContent(projectName, stats, skillScope);
|
|
176
|
+
const content = generateGitNexusContent(projectName, stats, skillScope, generatedSkills);
|
|
173
177
|
const createdFiles = [];
|
|
174
178
|
// Create AGENTS.md (standard for Cursor, Windsurf, OpenCode, Codex, Cline, etc.)
|
|
175
179
|
const agentsPath = path.join(repoPath, 'AGENTS.md');
|
package/dist/cli/analyze.d.ts
CHANGED
|
@@ -11,5 +11,7 @@ export interface AnalyzeOptions {
|
|
|
11
11
|
scopeManifest?: string;
|
|
12
12
|
scopePrefix?: string[];
|
|
13
13
|
reuseOptions?: boolean;
|
|
14
|
+
skills?: boolean;
|
|
15
|
+
verbose?: boolean;
|
|
14
16
|
}
|
|
15
17
|
export declare const analyzeCommand: (inputPath?: string, options?: AnalyzeOptions) => Promise<void>;
|
package/dist/cli/analyze.js
CHANGED
|
@@ -8,20 +8,19 @@ import { execFileSync } from 'child_process';
|
|
|
8
8
|
import v8 from 'v8';
|
|
9
9
|
import cliProgress from 'cli-progress';
|
|
10
10
|
import { runPipelineFromRepo } from '../core/ingestion/pipeline.js';
|
|
11
|
-
import {
|
|
11
|
+
import { initLbug, loadGraphToLbug, getLbugStats, executeQuery, executeWithReusedStatement, closeLbug, createFTSIndex, loadCachedEmbeddings } from '../core/lbug/lbug-adapter.js';
|
|
12
12
|
// Embedding imports are lazy (dynamic import) so onnxruntime-node is never
|
|
13
13
|
// loaded when embeddings are not requested. This avoids crashes on Node
|
|
14
14
|
// versions whose ABI is not yet supported by the native binary (#89).
|
|
15
15
|
// disposeEmbedder intentionally not called — ONNX Runtime segfaults on cleanup (see #38)
|
|
16
|
-
import { getStoragePaths, saveMeta, loadMeta, addToGitignore, registerRepo, getGlobalRegistryPath, loadCLIConfig } from '../storage/repo-manager.js';
|
|
16
|
+
import { getStoragePaths, saveMeta, loadMeta, addToGitignore, registerRepo, getGlobalRegistryPath, loadCLIConfig, cleanupOldKuzuFiles } from '../storage/repo-manager.js';
|
|
17
17
|
import { getCurrentCommit, isGitRepo, getGitRoot } from '../storage/git.js';
|
|
18
18
|
import { generateAIContextFiles } from './ai-context.js';
|
|
19
|
+
import { generateSkillFiles } from './skill-gen.js';
|
|
19
20
|
import fs from 'fs/promises';
|
|
20
|
-
import { registerClaudeHook } from './claude-hooks.js';
|
|
21
21
|
import { resolveEffectiveAnalyzeOptions } from './analyze-options.js';
|
|
22
22
|
import { formatFallbackSummary, formatUnityDiagnosticsSummary } from './analyze-summary.js';
|
|
23
23
|
import { resolveChildProcessExit } from './exit-code.js';
|
|
24
|
-
import { shouldCloseKuzuOnAnalyzeExit } from './analyze-close-policy.js';
|
|
25
24
|
import { toPipelineRuntimeSummary } from './analyze-runtime-summary.js';
|
|
26
25
|
const HEAP_MB = 8192;
|
|
27
26
|
const HEAP_FLAG = `--max-old-space-size=${HEAP_MB}`;
|
|
@@ -60,7 +59,7 @@ const PHASE_LABELS = {
|
|
|
60
59
|
communities: 'Detecting communities',
|
|
61
60
|
processes: 'Detecting processes',
|
|
62
61
|
complete: 'Pipeline complete',
|
|
63
|
-
|
|
62
|
+
lbug: 'Loading into LadybugDB',
|
|
64
63
|
fts: 'Creating search indexes',
|
|
65
64
|
embeddings: 'Generating embeddings',
|
|
66
65
|
done: 'Done',
|
|
@@ -68,6 +67,9 @@ const PHASE_LABELS = {
|
|
|
68
67
|
export const analyzeCommand = async (inputPath, options) => {
|
|
69
68
|
if (ensureHeap())
|
|
70
69
|
return;
|
|
70
|
+
if (options?.verbose) {
|
|
71
|
+
process.env.GITNEXUS_VERBOSE = '1';
|
|
72
|
+
}
|
|
71
73
|
console.log('\n GitNexus Analyzer\n');
|
|
72
74
|
let repoPath;
|
|
73
75
|
if (inputPath) {
|
|
@@ -87,7 +89,13 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
87
89
|
process.exitCode = 1;
|
|
88
90
|
return;
|
|
89
91
|
}
|
|
90
|
-
const { storagePath,
|
|
92
|
+
const { storagePath, lbugPath } = getStoragePaths(repoPath);
|
|
93
|
+
// Clean up stale KuzuDB files from before the LadybugDB migration.
|
|
94
|
+
// If kuzu existed but lbug doesn't, we're doing a migration re-index — say so.
|
|
95
|
+
const kuzuResult = await cleanupOldKuzuFiles(storagePath);
|
|
96
|
+
if (kuzuResult.found && kuzuResult.needsReindex) {
|
|
97
|
+
console.log(' Migrating from KuzuDB to LadybugDB — rebuilding index...\n');
|
|
98
|
+
}
|
|
91
99
|
const currentCommit = getCurrentCommit(repoPath);
|
|
92
100
|
const existingMeta = await loadMeta(storagePath);
|
|
93
101
|
let includeExtensions = [];
|
|
@@ -113,7 +121,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
113
121
|
process.exitCode = 1;
|
|
114
122
|
return;
|
|
115
123
|
}
|
|
116
|
-
if (existingMeta && !options?.force && existingMeta.lastCommit === currentCommit) {
|
|
124
|
+
if (existingMeta && !options?.force && existingMeta.lastCommit === currentCommit && !options?.skills) {
|
|
117
125
|
const hasScopePrefixInput = Array.isArray(options?.scopePrefix)
|
|
118
126
|
? options.scopePrefix.length > 0
|
|
119
127
|
: Boolean(options?.scopePrefix);
|
|
@@ -136,6 +144,9 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
136
144
|
return;
|
|
137
145
|
}
|
|
138
146
|
}
|
|
147
|
+
if (process.env.GITNEXUS_NO_GITIGNORE) {
|
|
148
|
+
console.log(' GITNEXUS_NO_GITIGNORE is set — skipping .gitignore (still reading .gitnexusignore)\n');
|
|
149
|
+
}
|
|
139
150
|
// Single progress bar for entire pipeline
|
|
140
151
|
const bar = new cliProgress.SingleBar({
|
|
141
152
|
format: ' {bar} {percentage}% | {phase}',
|
|
@@ -156,11 +167,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
156
167
|
aborted = true;
|
|
157
168
|
bar.stop();
|
|
158
169
|
console.log('\n Interrupted — cleaning up...');
|
|
159
|
-
|
|
160
|
-
process.exit(130);
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
closeKuzu().catch(() => { }).finally(() => process.exit(130));
|
|
170
|
+
closeLbug().catch(() => { }).finally(() => process.exit(130));
|
|
164
171
|
};
|
|
165
172
|
process.on('SIGINT', sigintHandler);
|
|
166
173
|
// Route all console output through bar.log() so the bar doesn't stamp itself
|
|
@@ -206,15 +213,15 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
206
213
|
if (embeddingsEnabled && existingMeta && !options?.force) {
|
|
207
214
|
try {
|
|
208
215
|
updateBar(0, 'Caching embeddings...');
|
|
209
|
-
await
|
|
216
|
+
await initLbug(lbugPath);
|
|
210
217
|
const cached = await loadCachedEmbeddings();
|
|
211
218
|
cachedEmbeddingNodeIds = cached.embeddingNodeIds;
|
|
212
219
|
cachedEmbeddings = cached.embeddings;
|
|
213
|
-
await
|
|
220
|
+
await closeLbug();
|
|
214
221
|
}
|
|
215
222
|
catch {
|
|
216
223
|
try {
|
|
217
|
-
await
|
|
224
|
+
await closeLbug();
|
|
218
225
|
}
|
|
219
226
|
catch { }
|
|
220
227
|
}
|
|
@@ -239,28 +246,29 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
239
246
|
process.exitCode = 1;
|
|
240
247
|
return;
|
|
241
248
|
}
|
|
242
|
-
// ── Phase 2:
|
|
243
|
-
updateBar(60, 'Loading into
|
|
244
|
-
await
|
|
245
|
-
const
|
|
246
|
-
for (const f of
|
|
249
|
+
// ── Phase 2: LadybugDB (60–85%) ──────────────────────────────────────
|
|
250
|
+
updateBar(60, 'Loading into LadybugDB...');
|
|
251
|
+
await closeLbug();
|
|
252
|
+
const lbugFiles = [lbugPath, `${lbugPath}.wal`, `${lbugPath}.lock`];
|
|
253
|
+
for (const f of lbugFiles) {
|
|
247
254
|
try {
|
|
248
255
|
await fs.rm(f, { recursive: true, force: true });
|
|
249
256
|
}
|
|
250
257
|
catch { }
|
|
251
258
|
}
|
|
252
|
-
const
|
|
253
|
-
await
|
|
254
|
-
let
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
const progress = Math.min(84, 60 + Math.round((
|
|
259
|
+
const t0Lbug = Date.now();
|
|
260
|
+
await initLbug(lbugPath);
|
|
261
|
+
let lbugMsgCount = 0;
|
|
262
|
+
const lbugResult = await loadGraphToLbug(pipelineResult.graph, pipelineResult.repoPath, storagePath, (msg) => {
|
|
263
|
+
lbugMsgCount++;
|
|
264
|
+
const progress = Math.min(84, 60 + Math.round((lbugMsgCount / (lbugMsgCount + 10)) * 24));
|
|
258
265
|
updateBar(progress, msg);
|
|
259
266
|
});
|
|
267
|
+
const pipelineForSkills = pipelineResult;
|
|
260
268
|
const pipelineRuntime = toPipelineRuntimeSummary(pipelineResult);
|
|
261
269
|
pipelineResult = undefined;
|
|
262
|
-
const
|
|
263
|
-
const
|
|
270
|
+
const lbugTime = ((Date.now() - t0Lbug) / 1000).toFixed(1);
|
|
271
|
+
const lbugWarnings = lbugResult.warnings;
|
|
264
272
|
// ── Phase 3: FTS (85–90%) ─────────────────────────────────────────
|
|
265
273
|
updateBar(85, 'Creating search indexes...');
|
|
266
274
|
const t0Fts = Date.now();
|
|
@@ -289,7 +297,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
289
297
|
}
|
|
290
298
|
}
|
|
291
299
|
// ── Phase 4: Embeddings (90–98%) ──────────────────────────────────
|
|
292
|
-
const stats = await
|
|
300
|
+
const stats = await getLbugStats();
|
|
293
301
|
let embeddingTime = '0.0';
|
|
294
302
|
let embeddingSkipped = true;
|
|
295
303
|
let embeddingSkipReason = 'off (use --embeddings to enable)';
|
|
@@ -314,6 +322,13 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
314
322
|
}
|
|
315
323
|
// ── Phase 5: Finalize (98–100%) ───────────────────────────────────
|
|
316
324
|
updateBar(98, 'Saving metadata...');
|
|
325
|
+
// Count embeddings in the index (cached + newly generated)
|
|
326
|
+
let embeddingCount = 0;
|
|
327
|
+
try {
|
|
328
|
+
const embResult = await executeQuery(`MATCH (e:CodeEmbedding) RETURN count(e) AS cnt`);
|
|
329
|
+
embeddingCount = embResult?.[0]?.cnt ?? 0;
|
|
330
|
+
}
|
|
331
|
+
catch { /* table may not exist if embeddings never ran */ }
|
|
317
332
|
const meta = {
|
|
318
333
|
repoPath,
|
|
319
334
|
lastCommit: currentCommit,
|
|
@@ -330,13 +345,13 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
330
345
|
edges: stats.edges,
|
|
331
346
|
communities: pipelineRuntime.communityResult?.stats.totalCommunities,
|
|
332
347
|
processes: pipelineRuntime.processResult?.stats.totalProcesses,
|
|
348
|
+
embeddings: embeddingCount,
|
|
333
349
|
},
|
|
334
350
|
};
|
|
335
351
|
await saveMeta(storagePath, meta);
|
|
336
352
|
await persistUnityParitySeed(storagePath, pipelineRuntime.unityResult?.paritySeed);
|
|
337
353
|
const registeredRepo = await registerRepo(repoPath, meta, { repoAlias });
|
|
338
354
|
await addToGitignore(repoPath);
|
|
339
|
-
const hookResult = await registerClaudeHook();
|
|
340
355
|
const projectName = path.basename(repoPath);
|
|
341
356
|
let aggregatedClusterCount = 0;
|
|
342
357
|
if (pipelineRuntime.communityResult?.communities) {
|
|
@@ -347,6 +362,12 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
347
362
|
}
|
|
348
363
|
aggregatedClusterCount = Array.from(groups.values()).filter(count => count >= 5).length;
|
|
349
364
|
}
|
|
365
|
+
let generatedSkills = [];
|
|
366
|
+
if (options?.skills && pipelineForSkills.communityResult) {
|
|
367
|
+
updateBar(99, 'Generating skill files...');
|
|
368
|
+
const skillResult = await generateSkillFiles(repoPath, projectName, pipelineForSkills);
|
|
369
|
+
generatedSkills = skillResult.skills;
|
|
370
|
+
}
|
|
350
371
|
const aiContext = await generateAIContextFiles(repoPath, storagePath, projectName, {
|
|
351
372
|
files: pipelineRuntime.totalFileCount,
|
|
352
373
|
nodes: stats.nodes,
|
|
@@ -356,10 +377,8 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
356
377
|
processes: pipelineRuntime.processResult?.stats.totalProcesses,
|
|
357
378
|
}, {
|
|
358
379
|
skillScope: ((await loadCLIConfig()).setupScope === 'global') ? 'global' : 'project',
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
await closeKuzu();
|
|
362
|
-
}
|
|
380
|
+
}, generatedSkills);
|
|
381
|
+
await closeLbug();
|
|
363
382
|
// Note: we intentionally do NOT call disposeEmbedder() here.
|
|
364
383
|
// ONNX Runtime's native cleanup segfaults on macOS and some Linux configs.
|
|
365
384
|
// Since the process exits immediately after, Node.js reclaims everything.
|
|
@@ -399,7 +418,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
399
418
|
console.log(` ${line}`);
|
|
400
419
|
}
|
|
401
420
|
console.log(` ${stats.nodes.toLocaleString()} nodes | ${stats.edges.toLocaleString()} edges | ${pipelineRuntime.communityResult?.stats.totalCommunities || 0} clusters | ${pipelineRuntime.processResult?.stats.totalProcesses || 0} flows`);
|
|
402
|
-
console.log(`
|
|
421
|
+
console.log(` LadybugDB ${lbugTime}s | FTS ${ftsTime}s | Embeddings ${embeddingSkipped ? embeddingSkipReason : embeddingTime + 's'}`);
|
|
403
422
|
if (includeExtensions.length > 0) {
|
|
404
423
|
console.log(` File filter: ${includeExtensions.join(', ')}`);
|
|
405
424
|
}
|
|
@@ -407,16 +426,19 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
407
426
|
if (aiContext.files.length > 0) {
|
|
408
427
|
console.log(` Context: ${aiContext.files.join(', ')}`);
|
|
409
428
|
}
|
|
410
|
-
if (
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const fallbackLines = formatFallbackSummary(
|
|
429
|
+
if (lbugWarnings.length > 0) {
|
|
430
|
+
const totalFallback = lbugWarnings.reduce((sum, warning) => {
|
|
431
|
+
const match = warning.match(/\((\d+) edges\)/);
|
|
432
|
+
return sum + (match ? Number.parseInt(match[1], 10) : 0);
|
|
433
|
+
}, 0);
|
|
434
|
+
const fallbackLines = formatFallbackSummary(lbugWarnings, {
|
|
435
|
+
attempted: totalFallback,
|
|
436
|
+
succeeded: totalFallback,
|
|
437
|
+
failed: 0,
|
|
438
|
+
});
|
|
416
439
|
for (const line of fallbackLines) {
|
|
417
440
|
console.log(` ${line}`);
|
|
418
441
|
}
|
|
419
|
-
console.log(' Note: schema pair coverage should be updated when fallback failures are non-zero');
|
|
420
442
|
}
|
|
421
443
|
try {
|
|
422
444
|
await fs.access(getGlobalRegistryPath());
|
|
@@ -425,12 +447,10 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
425
447
|
console.log('\n Tip: Run `gitnexus setup` to configure MCP for your editor.');
|
|
426
448
|
}
|
|
427
449
|
console.log('');
|
|
428
|
-
//
|
|
429
|
-
//
|
|
430
|
-
//
|
|
431
|
-
|
|
432
|
-
process.exit(0);
|
|
433
|
-
}
|
|
450
|
+
// LadybugDB's native module holds open handles that prevent Node from exiting.
|
|
451
|
+
// ONNX Runtime also registers native atexit hooks that segfault on some
|
|
452
|
+
// platforms (#38, #40). Force-exit to ensure clean termination.
|
|
453
|
+
process.exit(0);
|
|
434
454
|
};
|
|
435
455
|
async function persistUnityParitySeed(storagePath, seed) {
|
|
436
456
|
const seedPath = path.join(storagePath, 'unity-parity-seed.json');
|
package/dist/cli/augment.js
CHANGED
|
@@ -19,7 +19,7 @@ export async function augmentCommand(pattern) {
|
|
|
19
19
|
const result = await augment(pattern, process.cwd());
|
|
20
20
|
if (result) {
|
|
21
21
|
// IMPORTANT: Write to stderr, NOT stdout.
|
|
22
|
-
//
|
|
22
|
+
// LadybugDB's native module captures stdout fd at OS level during init,
|
|
23
23
|
// which makes stdout permanently broken in subprocess contexts.
|
|
24
24
|
// stderr is never captured, so it works reliably everywhere.
|
|
25
25
|
// The hook reads from the subprocess's stderr.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Eval Server — Lightweight HTTP server for SWE-bench evaluation
|
|
3
3
|
*
|
|
4
|
-
* Keeps
|
|
4
|
+
* Keeps LadybugDB warm in memory so tool calls from the agent are near-instant.
|
|
5
5
|
* Designed to run inside Docker containers during SWE-bench evaluation.
|
|
6
6
|
*
|
|
7
7
|
* KEY DESIGN: Returns LLM-friendly text, not raw JSON.
|
|
@@ -27,4 +27,11 @@ export interface EvalServerOptions {
|
|
|
27
27
|
port?: string;
|
|
28
28
|
idleTimeout?: string;
|
|
29
29
|
}
|
|
30
|
+
export declare function formatQueryResult(result: any): string;
|
|
31
|
+
export declare function formatContextResult(result: any): string;
|
|
32
|
+
export declare function formatImpactResult(result: any): string;
|
|
33
|
+
export declare function formatCypherResult(result: any): string;
|
|
34
|
+
export declare function formatDetectChangesResult(result: any): string;
|
|
35
|
+
export declare function formatListReposResult(result: any): string;
|
|
30
36
|
export declare function evalServerCommand(options?: EvalServerOptions): Promise<void>;
|
|
37
|
+
export declare const MAX_BODY_SIZE: number;
|