gitnexus 1.1.5 → 1.1.7
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/dist/cli/ai-context.js +42 -62
- package/dist/mcp/local/local-backend.d.ts +0 -1
- package/dist/mcp/local/local-backend.js +28 -127
- package/dist/mcp/resources.js +12 -3
- package/dist/mcp/server.js +45 -2
- package/dist/mcp/tools.js +22 -40
- package/package.json +1 -1
- package/skills/debugging.md +41 -64
- package/skills/exploring.md +38 -91
- package/skills/impact-analysis.md +41 -70
- package/skills/refactoring.md +57 -75
package/dist/cli/ai-context.js
CHANGED
|
@@ -14,88 +14,68 @@ const __dirname = path.dirname(__filename);
|
|
|
14
14
|
const GITNEXUS_START_MARKER = '<!-- gitnexus:start -->';
|
|
15
15
|
const GITNEXUS_END_MARKER = '<!-- gitnexus:end -->';
|
|
16
16
|
/**
|
|
17
|
-
* Generate the full GitNexus context content
|
|
17
|
+
* Generate the full GitNexus context content.
|
|
18
|
+
*
|
|
19
|
+
* Design principles (learned from real agent behavior):
|
|
20
|
+
* - AGENTS.md is the ROUTER — it tells the agent WHICH skill to use
|
|
21
|
+
* - Skills contain the actual workflows — AGENTS.md does NOT duplicate them
|
|
22
|
+
* - Use MUST/ALWAYS language — agents skip "examples" and "suggestions"
|
|
23
|
+
* - Keep reference material (tools, resources, schema) in AGENTS.md as a quick lookup
|
|
18
24
|
*/
|
|
19
25
|
function generateGitNexusContent(projectName, stats) {
|
|
20
26
|
const clusterCount = stats.clusters || stats.communities || 0;
|
|
21
27
|
return `${GITNEXUS_START_MARKER}
|
|
22
28
|
# GitNexus MCP
|
|
23
29
|
|
|
24
|
-
This project is indexed as **${projectName}**
|
|
30
|
+
This project is indexed by GitNexus as **${projectName}** (${stats.nodes || 0} symbols, ${stats.edges || 0} relationships, ${clusterCount} clusters, ${stats.processes || 0} processes).
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
GitNexus adds a knowledge graph layer to this codebase — use it to understand architecture, trace call chains, analyze blast radius, and navigate code by meaning rather than just filenames. It complements your existing tools (read, grep, etc.) with structural and semantic intelligence.
|
|
27
33
|
|
|
28
|
-
|
|
29
|
-
|--------|-------|
|
|
30
|
-
| Files | ${stats.files || 0} |
|
|
31
|
-
| Symbols | ${stats.nodes || 0} |
|
|
32
|
-
| Relationships | ${stats.edges || 0} |
|
|
33
|
-
| Clusters | ${clusterCount} |
|
|
34
|
-
| Processes | ${stats.processes || 0} |
|
|
34
|
+
IMPORTANT: GitNexus MCP tool usage is highly encouraged, especially for gathering deep and accurate codebase knowledge.
|
|
35
35
|
|
|
36
|
-
> **Staleness:**
|
|
36
|
+
> **Staleness:** The \`gitnexus://repo/{name}/context\` resource warns when the index is out of date. Refresh with \`npx gitnexus analyze\` in the terminal.
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Skills
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
1. READ gitnexus://repos → Discover all indexed repos
|
|
42
|
-
2. READ gitnexus://repo/${projectName}/context → Get codebase overview (~150 tokens)
|
|
43
|
-
3. READ gitnexus://repo/${projectName}/clusters → See all functional clusters
|
|
44
|
-
4. gitnexus_search({query: "...", repo: "${projectName}"}) → Find code by query
|
|
45
|
-
\`\`\`
|
|
40
|
+
For these tasks, read the matching skill and follow its workflow:
|
|
46
41
|
|
|
47
|
-
|
|
42
|
+
| Task | Skill | Path |
|
|
43
|
+
|------|-------|------|
|
|
44
|
+
| Understand architecture / "How does X work?" | **Exploring** | \`.claude/skills/gitnexus/exploring/SKILL.md\` |
|
|
45
|
+
| Blast radius / "What breaks if I change X?" | **Impact Analysis** | \`.claude/skills/gitnexus/impact-analysis/SKILL.md\` |
|
|
46
|
+
| Trace bugs / "Why is X failing?" | **Debugging** | \`.claude/skills/gitnexus/debugging/SKILL.md\` |
|
|
47
|
+
| Rename / extract / split / refactor | **Refactoring** | \`.claude/skills/gitnexus/refactoring/SKILL.md\` |
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|----------|---------|
|
|
51
|
-
| \`gitnexus://repos\` | List all indexed repositories |
|
|
52
|
-
| \`gitnexus://repo/${projectName}/context\` | Codebase stats, tools, and resources overview |
|
|
53
|
-
| \`gitnexus://repo/${projectName}/clusters\` | All clusters with symbol counts and cohesion |
|
|
54
|
-
| \`gitnexus://repo/${projectName}/cluster/{name}\` | Cluster members and details |
|
|
55
|
-
| \`gitnexus://repo/${projectName}/processes\` | All execution flows with types |
|
|
56
|
-
| \`gitnexus://repo/${projectName}/process/{name}\` | Full process trace with steps |
|
|
57
|
-
| \`gitnexus://repo/${projectName}/schema\` | Graph schema for Cypher queries |
|
|
58
|
-
|
|
59
|
-
## Available Tools
|
|
60
|
-
|
|
61
|
-
| Tool | Purpose | When to Use |
|
|
62
|
-
|------|---------|-------------|
|
|
63
|
-
| \`list_repos\` | Discover indexed repos | First step with multiple repos |
|
|
64
|
-
| \`search\` | Semantic + keyword search | Finding code by query |
|
|
65
|
-
| \`overview\` | List clusters & processes | Understanding architecture |
|
|
66
|
-
| \`explore\` | Deep dive on symbol/cluster/process | Detailed investigation |
|
|
67
|
-
| \`impact\` | Blast radius analysis | Before making changes |
|
|
68
|
-
| \`cypher\` | Raw graph queries | Complex analysis |
|
|
69
|
-
| \`analyze\` | Re-index repository | When index is stale or after major code changes |
|
|
70
|
-
|
|
71
|
-
> **Multi-repo:** When multiple repos are indexed, pass \`repo: "${projectName}"\` to target this project.
|
|
72
|
-
|
|
73
|
-
## Workflow Examples
|
|
74
|
-
|
|
75
|
-
### Exploring the Codebase
|
|
76
|
-
\`\`\`
|
|
77
|
-
READ gitnexus://repos → Discover repos
|
|
78
|
-
READ gitnexus://repo/${projectName}/context → Stats and overview (check for staleness)
|
|
79
|
-
READ gitnexus://repo/${projectName}/clusters → Find relevant cluster by name
|
|
80
|
-
READ gitnexus://repo/${projectName}/cluster/{name} → See members of that cluster
|
|
81
|
-
gitnexus_explore({name: "<symbol_name>", type: "symbol", repo: "${projectName}"})
|
|
82
|
-
\`\`\`
|
|
49
|
+
## Tools
|
|
83
50
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
51
|
+
| Tool | What it gives you |
|
|
52
|
+
|------|-------------------|
|
|
53
|
+
| \`search\` | Semantic + keyword code search with cluster context |
|
|
54
|
+
| \`explore\` | Symbol deep dive — callers, callees, cluster membership, processes |
|
|
55
|
+
| \`impact\` | Blast radius — what breaks at depth 1/2/3 with confidence scores |
|
|
56
|
+
| \`overview\` | All clusters and processes at a glance |
|
|
57
|
+
| \`cypher\` | Raw graph queries (read \`gitnexus://repo/{name}/schema\` first) |
|
|
58
|
+
| \`list_repos\` | Discover indexed repos |
|
|
59
|
+
|
|
60
|
+
## Resources
|
|
61
|
+
|
|
62
|
+
Lightweight reads (~100-500 tokens) for navigation:
|
|
63
|
+
|
|
64
|
+
| Resource | Content |
|
|
65
|
+
|----------|---------|
|
|
66
|
+
| \`gitnexus://repo/{name}/context\` | Stats, staleness check |
|
|
67
|
+
| \`gitnexus://repo/{name}/clusters\` | All clusters with cohesion scores |
|
|
68
|
+
| \`gitnexus://repo/{name}/cluster/{clusterName}\` | Cluster members |
|
|
69
|
+
| \`gitnexus://repo/{name}/processes\` | All execution flows |
|
|
70
|
+
| \`gitnexus://repo/{name}/process/{processName}\` | Step-by-step trace |
|
|
71
|
+
| \`gitnexus://repo/{name}/schema\` | Graph schema for Cypher |
|
|
90
72
|
|
|
91
73
|
## Graph Schema
|
|
92
74
|
|
|
93
75
|
**Nodes:** File, Function, Class, Interface, Method, Community, Process
|
|
94
|
-
|
|
95
|
-
**Relationships:** CALLS, IMPORTS, EXTENDS, IMPLEMENTS, DEFINES, MEMBER_OF, STEP_IN_PROCESS
|
|
76
|
+
**Edges (via CodeRelation.type):** CALLS, IMPORTS, EXTENDS, IMPLEMENTS, DEFINES, MEMBER_OF, STEP_IN_PROCESS
|
|
96
77
|
|
|
97
78
|
\`\`\`cypher
|
|
98
|
-
// Example: Find callers of a function
|
|
99
79
|
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
|
|
100
80
|
RETURN caller.name, caller.filePath
|
|
101
81
|
\`\`\`
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import { initKuzu, executeQuery, closeKuzu, isKuzuReady } from '../core/kuzu-adapter.js';
|
|
10
10
|
import { embedQuery, getEmbeddingDims, disposeEmbedder } from '../core/embedder.js';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
11
|
+
// git utilities available if needed
|
|
12
|
+
// import { isGitRepo, getCurrentCommit, getGitRoot } from '../../storage/git.js';
|
|
13
|
+
import { listRegisteredRepos, } from '../../storage/repo-manager.js';
|
|
14
|
+
// AI context generation is CLI-only (gitnexus analyze)
|
|
15
|
+
// import { generateAIContextFiles } from '../../cli/ai-context.js';
|
|
14
16
|
/**
|
|
15
17
|
* Quick test-file detection for filtering impact results.
|
|
16
18
|
* Matches common test file patterns across all supported languages.
|
|
@@ -175,8 +177,6 @@ export class LocalBackend {
|
|
|
175
177
|
return this.explore(repo, params);
|
|
176
178
|
case 'impact':
|
|
177
179
|
return this.impact(repo, params);
|
|
178
|
-
case 'analyze':
|
|
179
|
-
return this.analyze(repo, params);
|
|
180
180
|
default:
|
|
181
181
|
throw new Error(`Unknown tool: ${method}`);
|
|
182
182
|
}
|
|
@@ -255,10 +255,12 @@ export class LocalBackend {
|
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
257
|
// Add relationships if depth is 'full' and we have a node ID
|
|
258
|
+
// Only include connections with actual name/path data (skip MEMBER_OF, STEP_IN_PROCESS noise)
|
|
258
259
|
if (depth === 'full' && result.nodeId) {
|
|
259
260
|
try {
|
|
260
261
|
const relQuery = `
|
|
261
262
|
MATCH (n {id: '${result.nodeId.replace(/'/g, "''")}'})-[r:CodeRelation]->(m)
|
|
263
|
+
WHERE r.type IN ['CALLS', 'IMPORTS', 'DEFINES', 'EXTENDS', 'IMPLEMENTS']
|
|
262
264
|
RETURN r.type AS type, m.name AS targetName, m.filePath AS targetPath
|
|
263
265
|
LIMIT 5
|
|
264
266
|
`;
|
|
@@ -490,15 +492,19 @@ export class LocalBackend {
|
|
|
490
492
|
await this.ensureInitialized(repo.id);
|
|
491
493
|
const { name, type } = params;
|
|
492
494
|
if (type === 'symbol') {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
495
|
+
// If name contains a path separator or ':', treat it as a qualified lookup
|
|
496
|
+
const isQualified = name.includes('/') || name.includes(':');
|
|
497
|
+
const symbolQuery = isQualified
|
|
498
|
+
? `MATCH (n) WHERE n.id = '${name.replace(/'/g, "''")}' OR (n.name = '${name.replace(/'/g, "''")}')
|
|
499
|
+
RETURN n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
|
|
500
|
+
LIMIT 5`
|
|
501
|
+
: `MATCH (n) WHERE n.name = '${name.replace(/'/g, "''")}'
|
|
502
|
+
RETURN n.id AS id, n.name AS name, labels(n)[0] AS type, n.filePath AS filePath, n.startLine AS startLine, n.endLine AS endLine
|
|
503
|
+
LIMIT 5`;
|
|
499
504
|
const symbols = await executeQuery(repo.id, symbolQuery);
|
|
500
505
|
if (symbols.length === 0)
|
|
501
506
|
return { error: `Symbol '${name}' not found` };
|
|
507
|
+
// Use the first match for detailed exploration
|
|
502
508
|
const sym = symbols[0];
|
|
503
509
|
const symId = sym.id || sym[0];
|
|
504
510
|
const callersQuery = `
|
|
@@ -519,7 +525,7 @@ export class LocalBackend {
|
|
|
519
525
|
LIMIT 1
|
|
520
526
|
`;
|
|
521
527
|
const communities = await executeQuery(repo.id, communityQuery);
|
|
522
|
-
|
|
528
|
+
const result = {
|
|
523
529
|
symbol: {
|
|
524
530
|
id: symId,
|
|
525
531
|
name: sym.name || sym[1],
|
|
@@ -535,6 +541,16 @@ export class LocalBackend {
|
|
|
535
541
|
heuristicLabel: communities[0].heuristicLabel || communities[0][1],
|
|
536
542
|
} : null,
|
|
537
543
|
};
|
|
544
|
+
// If multiple symbols share the same name, show alternatives so the agent can disambiguate
|
|
545
|
+
if (symbols.length > 1) {
|
|
546
|
+
result.alternatives = symbols.slice(1).map((s) => ({
|
|
547
|
+
id: s.id || s[0],
|
|
548
|
+
type: s.type || s[2],
|
|
549
|
+
filePath: s.filePath || s[3],
|
|
550
|
+
}));
|
|
551
|
+
result.hint = `Multiple symbols named '${name}' found. Showing details for ${result.symbol.filePath}. Use the full node ID to explore a specific alternative.`;
|
|
552
|
+
}
|
|
553
|
+
return result;
|
|
538
554
|
}
|
|
539
555
|
if (type === 'cluster') {
|
|
540
556
|
const escaped = name.replace(/'/g, "''");
|
|
@@ -694,121 +710,6 @@ export class LocalBackend {
|
|
|
694
710
|
byDepth: grouped,
|
|
695
711
|
};
|
|
696
712
|
}
|
|
697
|
-
async analyze(repo, params) {
|
|
698
|
-
let repoPath;
|
|
699
|
-
if (params.path) {
|
|
700
|
-
repoPath = path.resolve(params.path);
|
|
701
|
-
}
|
|
702
|
-
else {
|
|
703
|
-
repoPath = repo.repoPath;
|
|
704
|
-
}
|
|
705
|
-
if (!isGitRepo(repoPath)) {
|
|
706
|
-
return { error: 'Not a git repository' };
|
|
707
|
-
}
|
|
708
|
-
const { storagePath, kuzuPath } = getRepoStoragePaths(repoPath);
|
|
709
|
-
const currentCommit = getCurrentCommit(repoPath);
|
|
710
|
-
const existingMeta = await loadRepoMeta(storagePath);
|
|
711
|
-
if (existingMeta && !params.force && existingMeta.lastCommit === currentCommit) {
|
|
712
|
-
return { status: 'up_to_date', message: 'Repository already up to date.' };
|
|
713
|
-
}
|
|
714
|
-
// Close this repo's MCP connection before pipeline takes over
|
|
715
|
-
await closeKuzu(repo.id);
|
|
716
|
-
this.initializedRepos.delete(repo.id);
|
|
717
|
-
try {
|
|
718
|
-
const { runPipelineFromRepo } = await import('../../core/ingestion/pipeline.js');
|
|
719
|
-
const coreKuzu = await import('../../core/kuzu/kuzu-adapter.js');
|
|
720
|
-
console.error('GitNexus: Running indexing pipeline...');
|
|
721
|
-
const pipelineResult = await runPipelineFromRepo(repoPath, (progress) => {
|
|
722
|
-
if (progress.percent % 20 === 0) {
|
|
723
|
-
console.error(`GitNexus: ${progress.phase} ${progress.percent}%`);
|
|
724
|
-
}
|
|
725
|
-
});
|
|
726
|
-
console.error('GitNexus: Loading graph into KuzuDB...');
|
|
727
|
-
await coreKuzu.initKuzu(kuzuPath);
|
|
728
|
-
await coreKuzu.loadGraphToKuzu(pipelineResult.graph, pipelineResult.fileContents, storagePath);
|
|
729
|
-
console.error('GitNexus: Creating FTS indexes...');
|
|
730
|
-
try {
|
|
731
|
-
await coreKuzu.createFTSIndex('File', 'file_fts', ['name', 'content']);
|
|
732
|
-
await coreKuzu.createFTSIndex('Function', 'function_fts', ['name', 'content']);
|
|
733
|
-
await coreKuzu.createFTSIndex('Class', 'class_fts', ['name', 'content']);
|
|
734
|
-
await coreKuzu.createFTSIndex('Method', 'method_fts', ['name', 'content']);
|
|
735
|
-
}
|
|
736
|
-
catch (e) {
|
|
737
|
-
console.error('GitNexus: Some FTS indexes may not have been created:', e.message);
|
|
738
|
-
}
|
|
739
|
-
if (!params.skipEmbeddings) {
|
|
740
|
-
try {
|
|
741
|
-
console.error('GitNexus: Generating embeddings...');
|
|
742
|
-
const { runEmbeddingPipeline } = await import('../../core/embeddings/embedding-pipeline.js');
|
|
743
|
-
await runEmbeddingPipeline(coreKuzu.executeQuery, coreKuzu.executeWithReusedStatement, (progress) => {
|
|
744
|
-
if (progress.percent % 25 === 0) {
|
|
745
|
-
console.error(`GitNexus: Embeddings ${progress.percent}%`);
|
|
746
|
-
}
|
|
747
|
-
});
|
|
748
|
-
}
|
|
749
|
-
catch (e) {
|
|
750
|
-
console.error('GitNexus: Embedding generation failed (non-fatal):', e.message);
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
const stats = await coreKuzu.getKuzuStats();
|
|
754
|
-
const newMeta = {
|
|
755
|
-
repoPath,
|
|
756
|
-
lastCommit: currentCommit,
|
|
757
|
-
indexedAt: new Date().toISOString(),
|
|
758
|
-
stats: {
|
|
759
|
-
files: pipelineResult.fileContents.size,
|
|
760
|
-
nodes: stats.nodes,
|
|
761
|
-
edges: stats.edges,
|
|
762
|
-
communities: pipelineResult.communityResult?.stats.totalCommunities,
|
|
763
|
-
processes: pipelineResult.processResult?.stats.totalProcesses,
|
|
764
|
-
},
|
|
765
|
-
};
|
|
766
|
-
await saveRepoMeta(storagePath, newMeta);
|
|
767
|
-
await addToGitignore(repoPath);
|
|
768
|
-
// Register in global registry
|
|
769
|
-
await registerRepo(repoPath, newMeta);
|
|
770
|
-
const projectName = path.basename(repoPath);
|
|
771
|
-
await generateAIContextFiles(repoPath, storagePath, projectName, {
|
|
772
|
-
files: pipelineResult.fileContents.size,
|
|
773
|
-
nodes: stats.nodes,
|
|
774
|
-
edges: stats.edges,
|
|
775
|
-
communities: pipelineResult.communityResult?.stats.totalCommunities,
|
|
776
|
-
processes: pipelineResult.processResult?.stats.totalProcesses,
|
|
777
|
-
});
|
|
778
|
-
await coreKuzu.closeKuzu();
|
|
779
|
-
// Update in-memory state
|
|
780
|
-
const handle = {
|
|
781
|
-
id: repo.id,
|
|
782
|
-
name: projectName,
|
|
783
|
-
repoPath,
|
|
784
|
-
storagePath,
|
|
785
|
-
kuzuPath,
|
|
786
|
-
indexedAt: newMeta.indexedAt,
|
|
787
|
-
lastCommit: newMeta.lastCommit,
|
|
788
|
-
stats: newMeta.stats,
|
|
789
|
-
};
|
|
790
|
-
this.repos.set(repo.id, handle);
|
|
791
|
-
this.contextCache.set(repo.id, {
|
|
792
|
-
projectName,
|
|
793
|
-
stats: {
|
|
794
|
-
fileCount: newMeta.stats.files || 0,
|
|
795
|
-
functionCount: newMeta.stats.nodes || 0,
|
|
796
|
-
communityCount: newMeta.stats.communities || 0,
|
|
797
|
-
processCount: newMeta.stats.processes || 0,
|
|
798
|
-
},
|
|
799
|
-
});
|
|
800
|
-
console.error('GitNexus: Indexing complete!');
|
|
801
|
-
return {
|
|
802
|
-
status: 'success',
|
|
803
|
-
message: `Repository indexed successfully.`,
|
|
804
|
-
stats: newMeta.stats,
|
|
805
|
-
};
|
|
806
|
-
}
|
|
807
|
-
catch (e) {
|
|
808
|
-
console.error('GitNexus: Indexing failed:', e.message);
|
|
809
|
-
return { error: `Indexing failed: ${e.message}` };
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
713
|
async disconnect() {
|
|
813
714
|
await closeKuzu(); // close all connections
|
|
814
715
|
await disposeEmbedder();
|
package/dist/mcp/resources.js
CHANGED
|
@@ -132,7 +132,6 @@ function getReposResource(backend) {
|
|
|
132
132
|
if (repo.stats) {
|
|
133
133
|
lines.push(` files: ${repo.stats.files || 0}`);
|
|
134
134
|
lines.push(` symbols: ${repo.stats.nodes || 0}`);
|
|
135
|
-
lines.push(` clusters: ${repo.stats.communities || 0}`);
|
|
136
135
|
lines.push(` processes: ${repo.stats.processes || 0}`);
|
|
137
136
|
}
|
|
138
137
|
}
|
|
@@ -158,6 +157,15 @@ async function getContextResource(backend, repoName) {
|
|
|
158
157
|
const repoPath = repo.repoPath;
|
|
159
158
|
const lastCommit = repo.lastCommit || 'HEAD';
|
|
160
159
|
const staleness = repoPath ? checkStaleness(repoPath, lastCommit) : { isStale: false, commitsBehind: 0 };
|
|
160
|
+
// Get aggregated cluster count (matches what overview/clusters resource shows)
|
|
161
|
+
let clusterCount = context.stats.communityCount;
|
|
162
|
+
try {
|
|
163
|
+
const overview = await backend.callTool('overview', { showClusters: true, showProcesses: false, limit: 100, repo: repoName });
|
|
164
|
+
if (overview.clusters) {
|
|
165
|
+
clusterCount = overview.clusters.length;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch { /* fall back to raw count */ }
|
|
161
169
|
const lines = [
|
|
162
170
|
`project: ${context.projectName}`,
|
|
163
171
|
];
|
|
@@ -169,7 +177,7 @@ async function getContextResource(backend, repoName) {
|
|
|
169
177
|
lines.push('stats:');
|
|
170
178
|
lines.push(` files: ${context.stats.fileCount}`);
|
|
171
179
|
lines.push(` symbols: ${context.stats.functionCount}`);
|
|
172
|
-
lines.push(` clusters: ${
|
|
180
|
+
lines.push(` clusters: ${clusterCount}`);
|
|
173
181
|
lines.push(` processes: ${context.stats.processCount}`);
|
|
174
182
|
lines.push('');
|
|
175
183
|
lines.push('tools_available:');
|
|
@@ -179,7 +187,8 @@ async function getContextResource(backend, repoName) {
|
|
|
179
187
|
lines.push(' - impact: Blast radius analysis');
|
|
180
188
|
lines.push(' - overview: List all clusters and processes');
|
|
181
189
|
lines.push(' - cypher: Raw graph queries');
|
|
182
|
-
lines.push('
|
|
190
|
+
lines.push('');
|
|
191
|
+
lines.push('re_index: Run `npx gitnexus analyze` in terminal if data is stale');
|
|
183
192
|
lines.push('');
|
|
184
193
|
lines.push('resources_available:');
|
|
185
194
|
lines.push(' - gitnexus://repos: All indexed repositories');
|
package/dist/mcp/server.js
CHANGED
|
@@ -15,6 +15,47 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
15
15
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
16
16
|
import { GITNEXUS_TOOLS } from './tools.js';
|
|
17
17
|
import { getResourceDefinitions, getResourceTemplates, readResource } from './resources.js';
|
|
18
|
+
/**
|
|
19
|
+
* Next-step hints appended to tool responses.
|
|
20
|
+
*
|
|
21
|
+
* Agents often stop after one tool call. These hints guide them to the
|
|
22
|
+
* logical next action, creating a self-guiding workflow without hooks.
|
|
23
|
+
*
|
|
24
|
+
* Design: Each hint is a short, actionable instruction (not a suggestion).
|
|
25
|
+
* The hint references the specific tool/resource to use next.
|
|
26
|
+
*/
|
|
27
|
+
function getNextStepHint(toolName, args) {
|
|
28
|
+
const repo = args?.repo;
|
|
29
|
+
const repoParam = repo ? `, repo: "${repo}"` : '';
|
|
30
|
+
const repoPath = repo || '{name}';
|
|
31
|
+
switch (toolName) {
|
|
32
|
+
case 'list_repos':
|
|
33
|
+
return `\n\n---\n**Next:** READ gitnexus://repo/{name}/context for any repo above to get its overview and check staleness.`;
|
|
34
|
+
case 'search':
|
|
35
|
+
return `\n\n---\n**Next:** To understand a result in context, use explore({name: "<symbol_name>", type: "symbol"${repoParam}}) to see its callers, callees, and cluster membership.`;
|
|
36
|
+
case 'explore': {
|
|
37
|
+
const exploreType = args?.type || 'symbol';
|
|
38
|
+
if (exploreType === 'symbol') {
|
|
39
|
+
return `\n\n---\n**Next:** If planning changes, use impact({target: "${args?.name || '<name>'}", direction: "upstream"${repoParam}}) to check blast radius. To see execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
40
|
+
}
|
|
41
|
+
if (exploreType === 'cluster') {
|
|
42
|
+
return `\n\n---\n**Next:** To drill into a specific symbol, use explore({name: "<symbol_name>", type: "symbol"${repoParam}}). To see execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
43
|
+
}
|
|
44
|
+
if (exploreType === 'process') {
|
|
45
|
+
return `\n\n---\n**Next:** To explore any step in detail, use explore({name: "<step_name>", type: "symbol"${repoParam}}).`;
|
|
46
|
+
}
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
case 'overview':
|
|
50
|
+
return `\n\n---\n**Next:** To drill into a cluster, READ gitnexus://repo/${repoPath}/cluster/{name} or use explore({name: "<cluster_name>", type: "cluster"${repoParam}}).`;
|
|
51
|
+
case 'impact':
|
|
52
|
+
return `\n\n---\n**Next:** Review d=1 items first (WILL BREAK). To check affected execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
53
|
+
case 'cypher':
|
|
54
|
+
return `\n\n---\n**Next:** To explore a result symbol, use explore({name: "<name>", type: "symbol"${repoParam}}). For schema reference, READ gitnexus://repo/${repoPath}/schema.`;
|
|
55
|
+
default:
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
18
59
|
export async function startMCPServer(backend) {
|
|
19
60
|
const server = new Server({
|
|
20
61
|
name: 'gitnexus',
|
|
@@ -84,16 +125,18 @@ export async function startMCPServer(backend) {
|
|
|
84
125
|
inputSchema: tool.inputSchema,
|
|
85
126
|
})),
|
|
86
127
|
}));
|
|
87
|
-
// Handle tool calls
|
|
128
|
+
// Handle tool calls — append next-step hints to guide agent workflow
|
|
88
129
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
89
130
|
const { name, arguments: args } = request.params;
|
|
90
131
|
try {
|
|
91
132
|
const result = await backend.callTool(name, args);
|
|
133
|
+
const resultText = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
|
134
|
+
const hint = getNextStepHint(name, args);
|
|
92
135
|
return {
|
|
93
136
|
content: [
|
|
94
137
|
{
|
|
95
138
|
type: 'text',
|
|
96
|
-
text:
|
|
139
|
+
text: resultText + hint,
|
|
97
140
|
},
|
|
98
141
|
],
|
|
99
142
|
};
|
package/dist/mcp/tools.js
CHANGED
|
@@ -10,7 +10,9 @@ export const GITNEXUS_TOOLS = [
|
|
|
10
10
|
description: `List all indexed repositories available to GitNexus.
|
|
11
11
|
|
|
12
12
|
Returns each repo's name, path, indexed date, last commit, and stats.
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
WHEN TO USE: First step when multiple repos are indexed, or to discover available repos.
|
|
15
|
+
AFTER THIS: READ gitnexus://repo/{name}/context for the repo you want to work with.
|
|
14
16
|
|
|
15
17
|
When multiple repos are indexed, you MUST specify the "repo" parameter
|
|
16
18
|
on other tools (search, explore, impact, etc.) to target the correct one.`,
|
|
@@ -20,43 +22,15 @@ on other tools (search, explore, impact, etc.) to target the correct one.`,
|
|
|
20
22
|
required: [],
|
|
21
23
|
},
|
|
22
24
|
},
|
|
23
|
-
{
|
|
24
|
-
name: 'analyze',
|
|
25
|
-
description: `Index or re-index a repository. Runs the full pipeline in-process.
|
|
26
|
-
|
|
27
|
-
Creates .gitnexus/ in repo root with:
|
|
28
|
-
- Knowledge graph (functions, classes, calls, imports)
|
|
29
|
-
- Full-text search indexes
|
|
30
|
-
- Community detection (Leiden)
|
|
31
|
-
- Process tracing
|
|
32
|
-
- Embeddings for semantic search
|
|
33
|
-
|
|
34
|
-
Also registers the repo in the global registry so the MCP server can serve it.
|
|
35
|
-
|
|
36
|
-
Run this when:
|
|
37
|
-
- First time using GitNexus on a repo
|
|
38
|
-
- After major code changes
|
|
39
|
-
- When staleness warning appears in gitnexus://context
|
|
40
|
-
- When 'not indexed' error appears
|
|
41
|
-
|
|
42
|
-
Note: This may take 30-120 seconds for large repos.`,
|
|
43
|
-
inputSchema: {
|
|
44
|
-
type: 'object',
|
|
45
|
-
properties: {
|
|
46
|
-
path: { type: 'string', description: 'Repo path (default: current directory)' },
|
|
47
|
-
force: { type: 'boolean', description: 'Re-index even if exists', default: false },
|
|
48
|
-
skipEmbeddings: { type: 'boolean', description: 'Skip embedding generation (faster)', default: false },
|
|
49
|
-
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
50
|
-
},
|
|
51
|
-
required: [],
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
25
|
{
|
|
55
26
|
name: 'search',
|
|
56
27
|
description: `Hybrid search (keyword + semantic) across the codebase.
|
|
57
28
|
Returns code nodes with cluster context and optional graph connections.
|
|
58
29
|
|
|
59
|
-
|
|
30
|
+
WHEN TO USE: Finding code by concept, name, or keyword. Use alongside grep/IDE search for richer results.
|
|
31
|
+
AFTER THIS: Use explore() on interesting results to see callers/callees and cluster membership.
|
|
32
|
+
|
|
33
|
+
Complements grep/IDE search by adding:
|
|
60
34
|
- Cluster context (which functional area each result belongs to)
|
|
61
35
|
- Relationship data (callers/callees with depth=full)
|
|
62
36
|
- Hybrid ranking (BM25 + semantic via Reciprocal Rank Fusion)
|
|
@@ -77,6 +51,9 @@ RETURNS: Array of {name, type, filePath, cluster?, connections[]?, fusedScore, s
|
|
|
77
51
|
name: 'cypher',
|
|
78
52
|
description: `Execute Cypher query against the code knowledge graph.
|
|
79
53
|
|
|
54
|
+
WHEN TO USE: Complex structural queries that search/explore can't answer. READ gitnexus://repo/{name}/schema first for the full schema.
|
|
55
|
+
AFTER THIS: Use explore() on result symbols for deeper context.
|
|
56
|
+
|
|
80
57
|
SCHEMA:
|
|
81
58
|
- Nodes: File, Folder, Function, Class, Interface, Method, Community, Process
|
|
82
59
|
- Edges via CodeRelation.type: CALLS, IMPORTS, EXTENDS, IMPLEMENTS, CONTAINS, DEFINES, MEMBER_OF, STEP_IN_PROCESS
|
|
@@ -108,13 +85,16 @@ TIPS:
|
|
|
108
85
|
name: 'explore',
|
|
109
86
|
description: `Deep dive on a symbol, cluster, or process.
|
|
110
87
|
|
|
88
|
+
WHEN TO USE: After search() to understand context, or to drill into a specific node.
|
|
89
|
+
AFTER THIS (symbol): Use impact() if planning changes, or READ process resource to see execution flows.
|
|
90
|
+
AFTER THIS (cluster): Use explore() on specific members, or READ processes resource.
|
|
91
|
+
AFTER THIS (process): Use explore() on individual steps for detail.
|
|
92
|
+
|
|
111
93
|
TYPE: symbol | cluster | process
|
|
112
94
|
|
|
113
95
|
For SYMBOL: Shows cluster membership, process participation, callers/callees
|
|
114
96
|
For CLUSTER: Shows members, cohesion score, processes touching it
|
|
115
|
-
For PROCESS: Shows step-by-step trace, clusters traversed, entry/terminal points
|
|
116
|
-
|
|
117
|
-
Use after search to understand context of a specific node.`,
|
|
97
|
+
For PROCESS: Shows step-by-step trace, clusters traversed, entry/terminal points`,
|
|
118
98
|
inputSchema: {
|
|
119
99
|
type: 'object',
|
|
120
100
|
properties: {
|
|
@@ -129,12 +109,13 @@ Use after search to understand context of a specific node.`,
|
|
|
129
109
|
name: 'overview',
|
|
130
110
|
description: `Get codebase map showing all clusters and processes.
|
|
131
111
|
|
|
112
|
+
WHEN TO USE: Understanding overall architecture. Prefer READ gitnexus://repo/{name}/clusters resource for a lighter-weight alternative.
|
|
113
|
+
AFTER THIS: Drill into a specific cluster with explore({type: "cluster"}) or search() for specific code.
|
|
114
|
+
|
|
132
115
|
Returns:
|
|
133
116
|
- All communities (clusters) with member counts and cohesion scores
|
|
134
117
|
- All processes with step counts and types (intra/cross-community)
|
|
135
|
-
- High-level architectural view
|
|
136
|
-
|
|
137
|
-
Use to understand overall codebase structure before diving deep.`,
|
|
118
|
+
- High-level architectural view`,
|
|
138
119
|
inputSchema: {
|
|
139
120
|
type: 'object',
|
|
140
121
|
properties: {
|
|
@@ -151,7 +132,8 @@ Use to understand overall codebase structure before diving deep.`,
|
|
|
151
132
|
description: `Analyze the impact of changing a code element.
|
|
152
133
|
Returns all nodes affected by modifying the target, with distance, edge type, and confidence.
|
|
153
134
|
|
|
154
|
-
USE
|
|
135
|
+
WHEN TO USE: Before making code changes, especially refactoring, renaming, or modifying shared code. Shows what would be affected.
|
|
136
|
+
AFTER THIS: Review d=1 items (WILL BREAK). READ gitnexus://repo/{name}/processes to check affected flows. If risk > MEDIUM, warn the user.
|
|
155
137
|
|
|
156
138
|
Output includes:
|
|
157
139
|
- Affected processes (with step positions)
|
package/package.json
CHANGED
package/skills/debugging.md
CHANGED
|
@@ -5,78 +5,64 @@ description: Trace bugs through call chains using knowledge graph
|
|
|
5
5
|
|
|
6
6
|
# Debugging with GitNexus
|
|
7
7
|
|
|
8
|
-
## Quick Start
|
|
9
|
-
```
|
|
10
|
-
0. READ gitnexus://repos → Discover indexed repos
|
|
11
|
-
1. If "Index is stale" → gitnexus_analyze({repo: "my-app"})
|
|
12
|
-
2. gitnexus_search({query: "...", repo: "my-app"}) → Find code related to error
|
|
13
|
-
3. gitnexus_explore({name, type: "symbol", repo: "my-app"}) → Get callers and callees
|
|
14
|
-
4. READ gitnexus://repo/my-app/process/{name} → Trace execution flow
|
|
15
|
-
```
|
|
16
|
-
|
|
17
8
|
## When to Use
|
|
18
9
|
- "Why is this function failing?"
|
|
19
10
|
- "Trace where this error comes from"
|
|
20
11
|
- "Who calls this method?"
|
|
21
|
-
- "
|
|
12
|
+
- "This endpoint returns 500"
|
|
13
|
+
- Investigating bugs, errors, or unexpected behavior
|
|
14
|
+
|
|
15
|
+
## Workflow
|
|
22
16
|
|
|
23
|
-
## Workflow Checklist
|
|
24
17
|
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- [ ] Identify the suspect function
|
|
30
|
-
- [ ] gitnexus_explore to see callers/callees
|
|
31
|
-
- [ ] READ gitnexus://repo/{name}/process/{name} if suspect is in a process
|
|
32
|
-
- [ ] READ gitnexus://repo/{name}/schema for Cypher query help
|
|
33
|
-
- [ ] gitnexus_cypher for custom traces
|
|
18
|
+
1. gitnexus_search({query: "<error or symptom>"}) → Find related code
|
|
19
|
+
2. gitnexus_explore({name: "<suspect>", type: "symbol"}) → See callers/callees
|
|
20
|
+
3. READ gitnexus://repo/{name}/process/{name} → Trace execution flow
|
|
21
|
+
4. gitnexus_cypher({query: "MATCH path..."}) → Custom traces if needed
|
|
34
22
|
```
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Graph schema for writing Cypher queries:
|
|
40
|
-
```yaml
|
|
41
|
-
nodes: [Function, Class, Method, File, Community, Process]
|
|
42
|
-
relationships: [CALLS, IMPORTS, EXTENDS, IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS]
|
|
43
|
-
example_queries:
|
|
44
|
-
find_callers: |
|
|
45
|
-
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "X"})
|
|
46
|
-
RETURN caller.name
|
|
47
|
-
```
|
|
24
|
+
> If "Index is stale" → run `npx gitnexus analyze` in terminal.
|
|
25
|
+
|
|
26
|
+
## Checklist
|
|
48
27
|
|
|
49
|
-
### gitnexus://repo/{name}/process/{processName}
|
|
50
|
-
Trace execution flow to find where bug might occur:
|
|
51
|
-
```yaml
|
|
52
|
-
name: CheckoutFlow
|
|
53
|
-
trace:
|
|
54
|
-
1: handleCheckout
|
|
55
|
-
2: validateCart
|
|
56
|
-
3: processPayment ← bug here?
|
|
57
|
-
4: sendConfirmation
|
|
58
28
|
```
|
|
29
|
+
- [ ] Understand the symptom (error message, unexpected behavior)
|
|
30
|
+
- [ ] gitnexus_search for error text or related code
|
|
31
|
+
- [ ] Identify the suspect function
|
|
32
|
+
- [ ] gitnexus_explore to see callers and callees
|
|
33
|
+
- [ ] Trace execution flow via process resource if applicable
|
|
34
|
+
- [ ] gitnexus_cypher for custom call chain traces if needed
|
|
35
|
+
- [ ] Read source files to confirm root cause
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Debugging Patterns
|
|
39
|
+
|
|
40
|
+
| Symptom | GitNexus Approach |
|
|
41
|
+
|---------|-------------------|
|
|
42
|
+
| Error message | `gitnexus_search` for error text → `explore` throw sites |
|
|
43
|
+
| Wrong return value | `explore` the function → trace callees for data flow |
|
|
44
|
+
| Intermittent failure | `explore` → look for external calls, async deps |
|
|
45
|
+
| Performance issue | `explore` → find symbols with many callers (hot paths) |
|
|
46
|
+
| Recent regression | `gitnexus_impact` on recently changed symbols |
|
|
59
47
|
|
|
60
|
-
##
|
|
48
|
+
## Tools
|
|
61
49
|
|
|
62
|
-
|
|
63
|
-
Find code related to error or symptom:
|
|
50
|
+
**gitnexus_search** — find code related to error:
|
|
64
51
|
```
|
|
65
|
-
gitnexus_search({query: "payment validation error", depth: "full"
|
|
52
|
+
gitnexus_search({query: "payment validation error", depth: "full"})
|
|
53
|
+
→ validatePayment, handlePaymentError, PaymentException
|
|
66
54
|
```
|
|
67
55
|
|
|
68
|
-
|
|
69
|
-
Get symbol context:
|
|
56
|
+
**gitnexus_explore** — full context for a suspect:
|
|
70
57
|
```
|
|
71
|
-
gitnexus_explore({name: "validatePayment", type: "symbol"
|
|
58
|
+
gitnexus_explore({name: "validatePayment", type: "symbol"})
|
|
72
59
|
→ Callers: processCheckout, webhookHandler
|
|
73
|
-
→ Callees: verifyCard, fetchRates
|
|
60
|
+
→ Callees: verifyCard, fetchRates (external API!)
|
|
61
|
+
→ Cluster: Payment
|
|
74
62
|
```
|
|
75
63
|
|
|
76
|
-
|
|
77
|
-
Custom graph queries for tracing:
|
|
64
|
+
**gitnexus_cypher** — custom call chain traces:
|
|
78
65
|
```cypher
|
|
79
|
-
// Trace call chain (2 hops)
|
|
80
66
|
MATCH path = (a)-[:CodeRelation {type: 'CALLS'}*1..2]->(b:Function {name: "validatePayment"})
|
|
81
67
|
RETURN [n IN nodes(path) | n.name] AS chain
|
|
82
68
|
```
|
|
@@ -84,23 +70,14 @@ RETURN [n IN nodes(path) | n.name] AS chain
|
|
|
84
70
|
## Example: "Payment endpoint returns 500 intermittently"
|
|
85
71
|
|
|
86
72
|
```
|
|
87
|
-
1. gitnexus_search({query: "payment error handling"
|
|
73
|
+
1. gitnexus_search({query: "payment error handling"})
|
|
88
74
|
→ validatePayment, handlePaymentError, PaymentException
|
|
89
75
|
|
|
90
|
-
2. gitnexus_explore({name: "validatePayment", type: "symbol"
|
|
76
|
+
2. gitnexus_explore({name: "validatePayment", type: "symbol"})
|
|
91
77
|
→ Callees: verifyCard, fetchRates (external API!)
|
|
92
78
|
|
|
93
79
|
3. READ gitnexus://repo/my-app/process/CheckoutFlow
|
|
94
|
-
→ Step 3: validatePayment → calls external
|
|
80
|
+
→ Step 3: validatePayment → calls fetchRates (external)
|
|
95
81
|
|
|
96
82
|
4. Root cause: fetchRates calls external API without proper timeout
|
|
97
83
|
```
|
|
98
|
-
|
|
99
|
-
## Debugging Patterns
|
|
100
|
-
|
|
101
|
-
| Symptom | Approach |
|
|
102
|
-
|---------|----------|
|
|
103
|
-
| Error message | Search for error text, trace throw sites |
|
|
104
|
-
| Wrong return value | Trace data flow through callees |
|
|
105
|
-
| Intermittent failure | Look for external calls, timeouts |
|
|
106
|
-
| Performance issue | Find hot paths via callers count |
|
package/skills/exploring.md
CHANGED
|
@@ -3,124 +3,71 @@ name: gitnexus-exploring
|
|
|
3
3
|
description: Navigate unfamiliar code using GitNexus knowledge graph
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Exploring Codebases
|
|
7
|
-
|
|
8
|
-
## Quick Start
|
|
9
|
-
```
|
|
10
|
-
0. READ gitnexus://repos → Discover indexed repos (use repo param if multiple)
|
|
11
|
-
1. If "Index is stale" → gitnexus_analyze({repo: "my-app"})
|
|
12
|
-
2. READ gitnexus://repo/{name}/context → Get codebase overview (~150 tokens)
|
|
13
|
-
3. READ gitnexus://repo/{name}/clusters → See all functional clusters
|
|
14
|
-
4. READ gitnexus://repo/{name}/cluster/{name} → Deep dive on specific cluster
|
|
15
|
-
```
|
|
6
|
+
# Exploring Codebases with GitNexus
|
|
16
7
|
|
|
17
8
|
## When to Use
|
|
18
9
|
- "How does authentication work?"
|
|
19
10
|
- "What's the project structure?"
|
|
20
11
|
- "Show me the main components"
|
|
21
12
|
- "Where is the database logic?"
|
|
13
|
+
- Understanding code you haven't seen before
|
|
14
|
+
|
|
15
|
+
## Workflow
|
|
22
16
|
|
|
23
|
-
## Workflow Checklist
|
|
24
17
|
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- [ ] READ gitnexus://repo/{name}/cluster/{name} for cluster details
|
|
31
|
-
- [ ] Use gitnexus_explore for specific symbols
|
|
18
|
+
1. READ gitnexus://repos → Discover indexed repos
|
|
19
|
+
2. READ gitnexus://repo/{name}/context → Codebase overview, check staleness
|
|
20
|
+
3. READ gitnexus://repo/{name}/clusters → See all functional areas
|
|
21
|
+
4. READ gitnexus://repo/{name}/cluster/{name} → Drill into relevant cluster
|
|
22
|
+
5. gitnexus_explore({name, type: "symbol"}) → Deep dive on specific symbol
|
|
32
23
|
```
|
|
33
24
|
|
|
34
|
-
|
|
25
|
+
> If step 2 says "Index is stale" → run `npx gitnexus analyze` in terminal.
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
Discover all indexed repositories. **Read first.**
|
|
38
|
-
```yaml
|
|
39
|
-
repos:
|
|
40
|
-
- name: "my-app"
|
|
41
|
-
path: "/home/user/my-app"
|
|
42
|
-
files: 42
|
|
43
|
-
symbols: 918
|
|
44
|
-
```
|
|
27
|
+
## Checklist
|
|
45
28
|
|
|
46
|
-
### gitnexus://repo/{name}/context
|
|
47
|
-
Codebase overview for a specific repo.
|
|
48
|
-
```yaml
|
|
49
|
-
project: my-app
|
|
50
|
-
stats:
|
|
51
|
-
files: 42
|
|
52
|
-
symbols: 918
|
|
53
|
-
clusters: 12
|
|
54
|
-
processes: 45
|
|
55
|
-
tools_available: [list_repos, search, explore, impact, overview, cypher]
|
|
56
29
|
```
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
cohesion: 92%
|
|
65
|
-
- name: "Database"
|
|
66
|
-
symbols: 32
|
|
67
|
-
cohesion: 88%
|
|
30
|
+
- [ ] READ gitnexus://repos
|
|
31
|
+
- [ ] READ gitnexus://repo/{name}/context
|
|
32
|
+
- [ ] READ gitnexus://repo/{name}/clusters
|
|
33
|
+
- [ ] Identify the relevant cluster
|
|
34
|
+
- [ ] READ gitnexus://repo/{name}/cluster/{name}
|
|
35
|
+
- [ ] gitnexus_explore for key symbols
|
|
36
|
+
- [ ] Read source files for implementation details
|
|
68
37
|
```
|
|
69
38
|
|
|
70
|
-
|
|
71
|
-
Members of a specific cluster.
|
|
72
|
-
```yaml
|
|
73
|
-
name: Auth
|
|
74
|
-
symbols: 47
|
|
75
|
-
cohesion: 92%
|
|
76
|
-
members:
|
|
77
|
-
- name: validateUser
|
|
78
|
-
type: Function
|
|
79
|
-
file: src/auth/validator.ts
|
|
80
|
-
```
|
|
39
|
+
## Resources
|
|
81
40
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
name
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
1: handleLogin (src/auth/handler.ts)
|
|
89
|
-
2: validateUser (src/auth/validator.ts)
|
|
90
|
-
3: createSession (src/auth/session.ts)
|
|
91
|
-
```
|
|
41
|
+
| Resource | What you get |
|
|
42
|
+
|----------|-------------|
|
|
43
|
+
| `gitnexus://repo/{name}/context` | Stats, staleness warning (~150 tokens) |
|
|
44
|
+
| `gitnexus://repo/{name}/clusters` | All clusters with cohesion scores (~300 tokens) |
|
|
45
|
+
| `gitnexus://repo/{name}/cluster/{name}` | Cluster members with file paths (~500 tokens) |
|
|
46
|
+
| `gitnexus://repo/{name}/process/{name}` | Step-by-step execution trace (~200 tokens) |
|
|
92
47
|
|
|
93
|
-
##
|
|
48
|
+
## Tools
|
|
94
49
|
|
|
95
|
-
|
|
96
|
-
For detailed symbol context with callers/callees:
|
|
50
|
+
**gitnexus_explore** — symbol context with callers/callees:
|
|
97
51
|
```
|
|
98
|
-
gitnexus_explore({name: "validateUser", type: "symbol"
|
|
52
|
+
gitnexus_explore({name: "validateUser", type: "symbol"})
|
|
99
53
|
→ Callers: loginHandler, apiMiddleware
|
|
100
54
|
→ Callees: checkToken, getUserById
|
|
55
|
+
→ Cluster: Auth (92% cohesion)
|
|
101
56
|
```
|
|
102
57
|
|
|
103
|
-
|
|
104
|
-
For finding code by query:
|
|
58
|
+
**gitnexus_search** — find code by query when you don't know the cluster:
|
|
105
59
|
```
|
|
106
|
-
gitnexus_search({query: "payment validation", depth: "full"
|
|
60
|
+
gitnexus_search({query: "payment validation", depth: "full"})
|
|
107
61
|
```
|
|
108
62
|
|
|
109
63
|
## Example: "How does payment processing work?"
|
|
110
64
|
|
|
111
65
|
```
|
|
112
|
-
1. READ gitnexus://
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
→
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
→ Clusters: Auth, Payment, Database, API...
|
|
120
|
-
|
|
121
|
-
4. READ gitnexus://repo/my-app/cluster/Payment
|
|
122
|
-
→ Members: processPayment, validateCard, PaymentService
|
|
123
|
-
|
|
124
|
-
5. READ gitnexus://repo/my-app/process/CheckoutFlow
|
|
125
|
-
→ handleCheckout → validateCart → processPayment → sendConfirmation
|
|
66
|
+
1. READ gitnexus://repo/my-app/context → 918 symbols, 12 clusters
|
|
67
|
+
2. READ gitnexus://repo/my-app/clusters → Auth, Payment, Database, API...
|
|
68
|
+
3. READ gitnexus://repo/my-app/cluster/Payment → processPayment, validateCard, PaymentService
|
|
69
|
+
4. gitnexus_explore({name: "processPayment", type: "symbol"})
|
|
70
|
+
→ Callers: checkoutHandler, webhookHandler
|
|
71
|
+
→ Callees: validateCard, chargeStripe, saveTransaction
|
|
72
|
+
5. Read src/payments/processor.ts for implementation details
|
|
126
73
|
```
|
|
@@ -3,74 +3,64 @@ name: gitnexus-impact-analysis
|
|
|
3
3
|
description: Analyze blast radius before making code changes
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Impact Analysis
|
|
7
|
-
|
|
8
|
-
## Quick Start
|
|
9
|
-
```
|
|
10
|
-
0. READ gitnexus://repos → Discover indexed repos
|
|
11
|
-
1. If "Index is stale" → gitnexus_analyze({repo: "my-app"})
|
|
12
|
-
2. gitnexus_impact({target, direction: "upstream", repo: "my-app"}) → What depends on this
|
|
13
|
-
3. READ gitnexus://repo/my-app/clusters → Check affected areas
|
|
14
|
-
4. READ gitnexus://repo/my-app/processes → Affected execution flows
|
|
15
|
-
```
|
|
6
|
+
# Impact Analysis with GitNexus
|
|
16
7
|
|
|
17
8
|
## When to Use
|
|
18
9
|
- "Is it safe to change this function?"
|
|
19
10
|
- "What will break if I modify X?"
|
|
20
11
|
- "Show me the blast radius"
|
|
21
12
|
- "Who uses this code?"
|
|
13
|
+
- Before making non-trivial code changes
|
|
22
14
|
|
|
23
|
-
##
|
|
15
|
+
## Workflow
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
```
|
|
18
|
+
1. gitnexus_impact({target: "X", direction: "upstream"}) → What depends on this
|
|
19
|
+
2. READ gitnexus://repo/{name}/clusters → Check which areas are affected
|
|
20
|
+
3. READ gitnexus://repo/{name}/processes → Check affected execution flows
|
|
21
|
+
4. Assess risk and report to user
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
> If "Index is stale" → run `npx gitnexus analyze` in terminal.
|
|
25
|
+
|
|
26
|
+
## Checklist
|
|
30
27
|
|
|
31
|
-
## Workflow Checklist
|
|
32
28
|
```
|
|
33
|
-
|
|
34
|
-
- [ ]
|
|
35
|
-
- [ ]
|
|
36
|
-
- [ ] READ
|
|
37
|
-
- [ ] Check high-confidence (>0.8) dependencies first
|
|
29
|
+
- [ ] gitnexus_impact({target, direction: "upstream"}) to find dependents
|
|
30
|
+
- [ ] Review d=1 items first (these WILL BREAK)
|
|
31
|
+
- [ ] Check high-confidence (>0.8) dependencies
|
|
32
|
+
- [ ] READ clusters to understand which areas are affected
|
|
38
33
|
- [ ] Count affected clusters (cross-cutting = higher risk)
|
|
39
|
-
- [ ]
|
|
34
|
+
- [ ] READ processes to check affected execution flows
|
|
35
|
+
- [ ] Assess risk level and report to user
|
|
40
36
|
```
|
|
41
37
|
|
|
42
|
-
##
|
|
38
|
+
## Understanding Output
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
symbols: 47
|
|
50
|
-
- name: API
|
|
51
|
-
symbols: 32
|
|
52
|
-
```
|
|
40
|
+
| Depth | Risk Level | Meaning |
|
|
41
|
+
|-------|-----------|---------|
|
|
42
|
+
| d=1 | **WILL BREAK** | Direct callers/importers |
|
|
43
|
+
| d=2 | LIKELY AFFECTED | Indirect dependencies |
|
|
44
|
+
| d=3 | MAY NEED TESTING | Transitive effects |
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
Find which processes touch the target:
|
|
56
|
-
```yaml
|
|
57
|
-
processes:
|
|
58
|
-
- name: LoginFlow
|
|
59
|
-
type: cross_community
|
|
60
|
-
steps: 5
|
|
61
|
-
```
|
|
46
|
+
## Risk Assessment
|
|
62
47
|
|
|
63
|
-
|
|
48
|
+
| Affected | Risk |
|
|
49
|
+
|----------|------|
|
|
50
|
+
| <5 symbols, 1 cluster | LOW |
|
|
51
|
+
| 5-15 symbols, 1-2 clusters | MEDIUM |
|
|
52
|
+
| >15 symbols or 3+ clusters | HIGH |
|
|
53
|
+
| Critical path (auth, payments) | CRITICAL |
|
|
54
|
+
|
|
55
|
+
## Tools
|
|
64
56
|
|
|
65
|
-
|
|
66
|
-
Analyze blast radius:
|
|
57
|
+
**gitnexus_impact** — the primary tool:
|
|
67
58
|
```
|
|
68
59
|
gitnexus_impact({
|
|
69
60
|
target: "validateUser",
|
|
70
61
|
direction: "upstream",
|
|
71
62
|
minConfidence: 0.8,
|
|
72
|
-
maxDepth: 3
|
|
73
|
-
repo: "my-app"
|
|
63
|
+
maxDepth: 3
|
|
74
64
|
})
|
|
75
65
|
|
|
76
66
|
→ d=1 (WILL BREAK):
|
|
@@ -84,34 +74,15 @@ gitnexus_impact({
|
|
|
84
74
|
→ Risk: MEDIUM (3 processes)
|
|
85
75
|
```
|
|
86
76
|
|
|
87
|
-
## Risk Assessment
|
|
88
|
-
|
|
89
|
-
| Affected | Risk |
|
|
90
|
-
|----------|------|
|
|
91
|
-
| <5 symbols, 1 cluster | LOW |
|
|
92
|
-
| 5-15 symbols, 1-2 clusters | MEDIUM |
|
|
93
|
-
| >15 symbols or 3+ clusters | HIGH |
|
|
94
|
-
| Critical path (auth, payments) | CRITICAL |
|
|
95
|
-
|
|
96
|
-
## Pre-Change Checklist
|
|
97
|
-
```
|
|
98
|
-
Before Committing:
|
|
99
|
-
- [ ] Run impact analysis
|
|
100
|
-
- [ ] Review all d=1 (WILL BREAK) items
|
|
101
|
-
- [ ] Verify test coverage for affected processes
|
|
102
|
-
- [ ] If risk > MEDIUM, get code review
|
|
103
|
-
- [ ] If cross-cluster, coordinate with other teams
|
|
104
|
-
```
|
|
105
|
-
|
|
106
77
|
## Example: "What breaks if I change validateUser?"
|
|
107
78
|
|
|
108
79
|
```
|
|
109
|
-
1. gitnexus_impact({target: "validateUser", direction: "upstream"
|
|
110
|
-
→ d=1: loginHandler, apiMiddleware
|
|
111
|
-
→ d=2: authRouter, sessionManager
|
|
80
|
+
1. gitnexus_impact({target: "validateUser", direction: "upstream"})
|
|
81
|
+
→ d=1: loginHandler, apiMiddleware (WILL BREAK)
|
|
82
|
+
→ d=2: authRouter, sessionManager (LIKELY AFFECTED)
|
|
112
83
|
|
|
113
84
|
2. READ gitnexus://repo/my-app/clusters
|
|
114
|
-
→ Auth and API clusters affected
|
|
85
|
+
→ Auth and API clusters affected (2 clusters)
|
|
115
86
|
|
|
116
|
-
3.
|
|
87
|
+
3. Risk: 2 direct callers, 2 clusters = MEDIUM
|
|
117
88
|
```
|
package/skills/refactoring.md
CHANGED
|
@@ -5,116 +5,98 @@ description: Plan safe refactors using blast radius and dependency mapping
|
|
|
5
5
|
|
|
6
6
|
# Refactoring with GitNexus
|
|
7
7
|
|
|
8
|
-
## Quick Start
|
|
9
|
-
```
|
|
10
|
-
0. READ gitnexus://repos → Discover indexed repos
|
|
11
|
-
1. If "Index is stale" → gitnexus_analyze({repo: "my-app"})
|
|
12
|
-
2. gitnexus_impact({target, direction: "upstream", repo: "my-app"}) → Map all dependents
|
|
13
|
-
3. READ gitnexus://repo/my-app/schema → Understand graph structure
|
|
14
|
-
4. gitnexus_cypher({query: "...", repo: "my-app"}) → Find all references
|
|
15
|
-
```
|
|
16
|
-
|
|
17
8
|
## When to Use
|
|
18
9
|
- "Rename this function safely"
|
|
19
10
|
- "Extract this into a module"
|
|
20
11
|
- "Split this service"
|
|
21
|
-
- "
|
|
12
|
+
- "Move this to a new file"
|
|
13
|
+
- Any task involving renaming, extracting, splitting, or restructuring code
|
|
14
|
+
|
|
15
|
+
## Workflow
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
1. gitnexus_impact({target: "X", direction: "upstream"}) → Map all dependents
|
|
19
|
+
2. gitnexus_search({query: "X"}) → Find string/dynamic references
|
|
20
|
+
3. READ gitnexus://repo/{name}/cluster/{name} → Check cohesion impact
|
|
21
|
+
4. Plan update order: interfaces → implementations → callers → tests
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
> If "Index is stale" → run `npx gitnexus analyze` in terminal.
|
|
22
25
|
|
|
23
26
|
## Checklists
|
|
24
27
|
|
|
25
28
|
### Rename Symbol
|
|
26
29
|
```
|
|
27
|
-
|
|
28
|
-
- [ ]
|
|
29
|
-
- [ ]
|
|
30
|
-
- [ ]
|
|
31
|
-
- [ ] Update
|
|
30
|
+
- [ ] gitnexus_impact({target: oldName, direction: "upstream"}) — find all callers
|
|
31
|
+
- [ ] gitnexus_search({query: oldName}) — find string literals and dynamic references
|
|
32
|
+
- [ ] Check for reflection/dynamic invocation patterns
|
|
33
|
+
- [ ] Plan update order: interface → implementation → callers → tests
|
|
34
|
+
- [ ] Update all d=1 (WILL BREAK) items
|
|
32
35
|
- [ ] Run tests for affected processes
|
|
33
36
|
```
|
|
34
37
|
|
|
35
38
|
### Extract Module
|
|
36
39
|
```
|
|
37
|
-
|
|
38
|
-
- [ ]
|
|
39
|
-
- [ ]
|
|
40
|
-
- [ ] READ gitnexus://repo/my-app/cluster/{name} — check cohesion
|
|
40
|
+
- [ ] gitnexus_explore({name: target, type: "symbol"}) — map internal dependencies
|
|
41
|
+
- [ ] gitnexus_impact({target, direction: "upstream"}) — find all external callers
|
|
42
|
+
- [ ] READ cluster resource — check if extraction preserves cohesion
|
|
41
43
|
- [ ] Define new module interface
|
|
42
|
-
- [ ]
|
|
44
|
+
- [ ] Extract code, update imports
|
|
45
|
+
- [ ] Run tests for affected processes
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
### Split Function
|
|
48
|
+
### Split Function/Service
|
|
46
49
|
```
|
|
47
|
-
|
|
48
|
-
- [ ]
|
|
49
|
-
- [ ]
|
|
50
|
-
- [ ]
|
|
51
|
-
- [ ] Create new functions
|
|
50
|
+
- [ ] gitnexus_explore({name: target, type: "symbol"}) — understand all callees
|
|
51
|
+
- [ ] Group callees by responsibility/domain
|
|
52
|
+
- [ ] gitnexus_impact({target, direction: "upstream"}) — map callers to update
|
|
53
|
+
- [ ] Create new functions/services
|
|
52
54
|
- [ ] Update callers
|
|
55
|
+
- [ ] Run tests for affected processes
|
|
53
56
|
```
|
|
54
57
|
|
|
55
|
-
##
|
|
58
|
+
## Tools
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
Graph structure for Cypher queries:
|
|
59
|
-
```yaml
|
|
60
|
-
nodes: [Function, Class, Method, Community, Process]
|
|
61
|
-
relationships: [CALLS, IMPORTS, EXTENDS, MEMBER_OF]
|
|
62
|
-
|
|
63
|
-
example_queries:
|
|
64
|
-
find_callers: |
|
|
65
|
-
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "X"})
|
|
66
|
-
RETURN caller.name
|
|
60
|
+
**gitnexus_impact** — map all dependents first:
|
|
67
61
|
```
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
```yaml
|
|
72
|
-
name: Payment
|
|
73
|
-
cohesion: 92%
|
|
74
|
-
members: [processPayment, validateCard, PaymentService]
|
|
62
|
+
gitnexus_impact({target: "validateUser", direction: "upstream"})
|
|
63
|
+
→ d=1: loginHandler, apiMiddleware, testUtils
|
|
64
|
+
→ Affected Processes: LoginFlow, TokenRefresh
|
|
75
65
|
```
|
|
76
66
|
|
|
77
|
-
|
|
67
|
+
**gitnexus_search** — find string/dynamic references impact() might miss:
|
|
68
|
+
```
|
|
69
|
+
gitnexus_search({query: "validateUser"})
|
|
70
|
+
→ Found in: config.json (dynamic reference!), test fixtures
|
|
71
|
+
```
|
|
78
72
|
|
|
79
|
-
|
|
73
|
+
**gitnexus_cypher** — custom reference queries:
|
|
80
74
|
```cypher
|
|
81
75
|
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "validateUser"})
|
|
82
|
-
RETURN caller.name, caller.filePath
|
|
83
|
-
ORDER BY caller.filePath
|
|
76
|
+
RETURN caller.name, caller.filePath ORDER BY caller.filePath
|
|
84
77
|
```
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
79
|
+
## Risk Rules
|
|
80
|
+
|
|
81
|
+
| Risk Factor | Mitigation |
|
|
82
|
+
|-------------|------------|
|
|
83
|
+
| Many callers (>5) | Update in small batches |
|
|
84
|
+
| Cross-cluster refs | Coordinate with affected areas |
|
|
85
|
+
| String/dynamic refs | `gitnexus_search` to find them |
|
|
86
|
+
| External/public API | Version and deprecate properly |
|
|
91
87
|
|
|
92
|
-
## Example:
|
|
88
|
+
## Example: Rename `validateUser` to `authenticateUser`
|
|
93
89
|
|
|
94
90
|
```
|
|
95
|
-
1. gitnexus_impact({target: "validateUser", direction: "upstream"
|
|
96
|
-
→ loginHandler, apiMiddleware, testUtils
|
|
91
|
+
1. gitnexus_impact({target: "validateUser", direction: "upstream"})
|
|
92
|
+
→ d=1: loginHandler, apiMiddleware, testUtils
|
|
97
93
|
|
|
98
|
-
2. gitnexus_search({query: "validateUser"
|
|
94
|
+
2. gitnexus_search({query: "validateUser"})
|
|
99
95
|
→ Found in: config.json (dynamic reference!)
|
|
100
96
|
|
|
101
|
-
3.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
4. Plan update order:
|
|
105
|
-
1. Update declaration in auth.ts
|
|
97
|
+
3. Plan update order:
|
|
98
|
+
1. Update declaration in src/auth/validator.ts
|
|
106
99
|
2. Update config.json string reference
|
|
107
|
-
3. Update loginHandler
|
|
108
|
-
4.
|
|
109
|
-
5. Run tests for LoginFlow, TokenRefresh
|
|
100
|
+
3. Update loginHandler, apiMiddleware, testUtils
|
|
101
|
+
4. Run tests for LoginFlow, TokenRefresh
|
|
110
102
|
```
|
|
111
|
-
|
|
112
|
-
## Refactoring Safety Rules
|
|
113
|
-
|
|
114
|
-
| Risk Factor | Mitigation |
|
|
115
|
-
|-------------|------------|
|
|
116
|
-
| Many callers (>5) | Update in small batches |
|
|
117
|
-
| Cross-cluster | Coordinate with other teams |
|
|
118
|
-
| String references | Search for dynamic usage |
|
|
119
|
-
| Reflection | Check for dynamic invocation |
|
|
120
|
-
| External exports | May break downstream repos |
|