@veewo/gitnexus 1.3.4
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 +234 -0
- package/dist/benchmark/agent-context/evaluators.d.ts +9 -0
- package/dist/benchmark/agent-context/evaluators.js +196 -0
- package/dist/benchmark/agent-context/evaluators.test.d.ts +1 -0
- package/dist/benchmark/agent-context/evaluators.test.js +39 -0
- package/dist/benchmark/agent-context/io.d.ts +2 -0
- package/dist/benchmark/agent-context/io.js +23 -0
- package/dist/benchmark/agent-context/io.test.d.ts +1 -0
- package/dist/benchmark/agent-context/io.test.js +19 -0
- package/dist/benchmark/agent-context/report.d.ts +2 -0
- package/dist/benchmark/agent-context/report.js +59 -0
- package/dist/benchmark/agent-context/report.test.d.ts +1 -0
- package/dist/benchmark/agent-context/report.test.js +85 -0
- package/dist/benchmark/agent-context/runner.d.ts +46 -0
- package/dist/benchmark/agent-context/runner.js +111 -0
- package/dist/benchmark/agent-context/runner.test.d.ts +1 -0
- package/dist/benchmark/agent-context/runner.test.js +79 -0
- package/dist/benchmark/agent-context/tool-runner.d.ts +7 -0
- package/dist/benchmark/agent-context/tool-runner.js +18 -0
- package/dist/benchmark/agent-context/tool-runner.test.d.ts +1 -0
- package/dist/benchmark/agent-context/tool-runner.test.js +11 -0
- package/dist/benchmark/agent-context/types.d.ts +40 -0
- package/dist/benchmark/agent-context/types.js +1 -0
- package/dist/benchmark/analyze-runner.d.ts +16 -0
- package/dist/benchmark/analyze-runner.js +51 -0
- package/dist/benchmark/analyze-runner.test.d.ts +1 -0
- package/dist/benchmark/analyze-runner.test.js +37 -0
- package/dist/benchmark/evaluators.d.ts +6 -0
- package/dist/benchmark/evaluators.js +10 -0
- package/dist/benchmark/evaluators.test.d.ts +1 -0
- package/dist/benchmark/evaluators.test.js +12 -0
- package/dist/benchmark/io.d.ts +7 -0
- package/dist/benchmark/io.js +25 -0
- package/dist/benchmark/io.test.d.ts +1 -0
- package/dist/benchmark/io.test.js +35 -0
- package/dist/benchmark/neonspark-candidates.d.ts +19 -0
- package/dist/benchmark/neonspark-candidates.js +94 -0
- package/dist/benchmark/neonspark-candidates.test.d.ts +1 -0
- package/dist/benchmark/neonspark-candidates.test.js +43 -0
- package/dist/benchmark/neonspark-materialize.d.ts +19 -0
- package/dist/benchmark/neonspark-materialize.js +111 -0
- package/dist/benchmark/neonspark-materialize.test.d.ts +1 -0
- package/dist/benchmark/neonspark-materialize.test.js +124 -0
- package/dist/benchmark/neonspark-sync.d.ts +3 -0
- package/dist/benchmark/neonspark-sync.js +53 -0
- package/dist/benchmark/neonspark-sync.test.d.ts +1 -0
- package/dist/benchmark/neonspark-sync.test.js +20 -0
- package/dist/benchmark/report.d.ts +1 -0
- package/dist/benchmark/report.js +7 -0
- package/dist/benchmark/runner.d.ts +48 -0
- package/dist/benchmark/runner.js +302 -0
- package/dist/benchmark/runner.test.d.ts +1 -0
- package/dist/benchmark/runner.test.js +50 -0
- package/dist/benchmark/scoring.d.ts +16 -0
- package/dist/benchmark/scoring.js +27 -0
- package/dist/benchmark/scoring.test.d.ts +1 -0
- package/dist/benchmark/scoring.test.js +24 -0
- package/dist/benchmark/tool-runner.d.ts +6 -0
- package/dist/benchmark/tool-runner.js +17 -0
- package/dist/benchmark/types.d.ts +36 -0
- package/dist/benchmark/types.js +1 -0
- package/dist/cli/ai-context.d.ts +22 -0
- package/dist/cli/ai-context.js +184 -0
- package/dist/cli/ai-context.test.d.ts +1 -0
- package/dist/cli/ai-context.test.js +30 -0
- package/dist/cli/analyze-multi-scope-regression.test.d.ts +1 -0
- package/dist/cli/analyze-multi-scope-regression.test.js +22 -0
- package/dist/cli/analyze-options.d.ts +7 -0
- package/dist/cli/analyze-options.js +56 -0
- package/dist/cli/analyze-options.test.d.ts +1 -0
- package/dist/cli/analyze-options.test.js +36 -0
- package/dist/cli/analyze.d.ts +14 -0
- package/dist/cli/analyze.js +384 -0
- package/dist/cli/augment.d.ts +13 -0
- package/dist/cli/augment.js +33 -0
- package/dist/cli/benchmark-agent-context.d.ts +29 -0
- package/dist/cli/benchmark-agent-context.js +61 -0
- package/dist/cli/benchmark-agent-context.test.d.ts +1 -0
- package/dist/cli/benchmark-agent-context.test.js +80 -0
- package/dist/cli/benchmark-unity.d.ts +15 -0
- package/dist/cli/benchmark-unity.js +31 -0
- package/dist/cli/benchmark-unity.test.d.ts +1 -0
- package/dist/cli/benchmark-unity.test.js +18 -0
- package/dist/cli/claude-hooks.d.ts +22 -0
- package/dist/cli/claude-hooks.js +97 -0
- package/dist/cli/clean.d.ts +10 -0
- package/dist/cli/clean.js +60 -0
- package/dist/cli/eval-server.d.ts +30 -0
- package/dist/cli/eval-server.js +372 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +182 -0
- package/dist/cli/list.d.ts +6 -0
- package/dist/cli/list.js +33 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +34 -0
- package/dist/cli/repo-manager-alias.test.d.ts +1 -0
- package/dist/cli/repo-manager-alias.test.js +40 -0
- package/dist/cli/scope-filter.test.d.ts +1 -0
- package/dist/cli/scope-filter.test.js +49 -0
- package/dist/cli/serve.d.ts +4 -0
- package/dist/cli/serve.js +6 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +311 -0
- package/dist/cli/setup.test.d.ts +1 -0
- package/dist/cli/setup.test.js +31 -0
- package/dist/cli/status.d.ts +6 -0
- package/dist/cli/status.js +27 -0
- package/dist/cli/tool.d.ts +40 -0
- package/dist/cli/tool.js +94 -0
- package/dist/cli/version.test.d.ts +1 -0
- package/dist/cli/version.test.js +19 -0
- package/dist/cli/wiki.d.ts +15 -0
- package/dist/cli/wiki.js +361 -0
- package/dist/config/ignore-service.d.ts +1 -0
- package/dist/config/ignore-service.js +210 -0
- package/dist/config/supported-languages.d.ts +12 -0
- package/dist/config/supported-languages.js +15 -0
- package/dist/core/augmentation/engine.d.ts +26 -0
- package/dist/core/augmentation/engine.js +213 -0
- package/dist/core/embeddings/embedder.d.ts +60 -0
- package/dist/core/embeddings/embedder.js +251 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
- package/dist/core/embeddings/embedding-pipeline.js +329 -0
- package/dist/core/embeddings/index.d.ts +9 -0
- package/dist/core/embeddings/index.js +9 -0
- package/dist/core/embeddings/text-generator.d.ts +24 -0
- package/dist/core/embeddings/text-generator.js +182 -0
- package/dist/core/embeddings/types.d.ts +87 -0
- package/dist/core/embeddings/types.js +32 -0
- package/dist/core/graph/graph.d.ts +2 -0
- package/dist/core/graph/graph.js +66 -0
- package/dist/core/graph/types.d.ts +61 -0
- package/dist/core/graph/types.js +1 -0
- package/dist/core/ingestion/ast-cache.d.ts +11 -0
- package/dist/core/ingestion/ast-cache.js +34 -0
- package/dist/core/ingestion/call-processor.d.ts +15 -0
- package/dist/core/ingestion/call-processor.js +327 -0
- package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
- package/dist/core/ingestion/cluster-enricher.js +170 -0
- package/dist/core/ingestion/community-processor.d.ts +39 -0
- package/dist/core/ingestion/community-processor.js +312 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +39 -0
- package/dist/core/ingestion/entry-point-scoring.js +260 -0
- package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
- package/dist/core/ingestion/filesystem-walker.js +80 -0
- package/dist/core/ingestion/framework-detection.d.ts +39 -0
- package/dist/core/ingestion/framework-detection.js +235 -0
- package/dist/core/ingestion/heritage-processor.d.ts +20 -0
- package/dist/core/ingestion/heritage-processor.js +197 -0
- package/dist/core/ingestion/import-processor.d.ts +38 -0
- package/dist/core/ingestion/import-processor.js +778 -0
- package/dist/core/ingestion/parsing-processor.d.ts +15 -0
- package/dist/core/ingestion/parsing-processor.js +291 -0
- package/dist/core/ingestion/pipeline.d.ts +5 -0
- package/dist/core/ingestion/pipeline.js +323 -0
- package/dist/core/ingestion/process-processor.d.ts +51 -0
- package/dist/core/ingestion/process-processor.js +309 -0
- package/dist/core/ingestion/scope-filter.d.ts +25 -0
- package/dist/core/ingestion/scope-filter.js +100 -0
- package/dist/core/ingestion/structure-processor.d.ts +2 -0
- package/dist/core/ingestion/structure-processor.js +36 -0
- package/dist/core/ingestion/symbol-table.d.ts +33 -0
- package/dist/core/ingestion/symbol-table.js +38 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +12 -0
- package/dist/core/ingestion/tree-sitter-queries.js +398 -0
- package/dist/core/ingestion/utils.d.ts +10 -0
- package/dist/core/ingestion/utils.js +50 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +59 -0
- package/dist/core/ingestion/workers/parse-worker.js +672 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
- package/dist/core/ingestion/workers/worker-pool.js +120 -0
- package/dist/core/kuzu/csv-generator.d.ts +29 -0
- package/dist/core/kuzu/csv-generator.js +336 -0
- package/dist/core/kuzu/kuzu-adapter.d.ts +101 -0
- package/dist/core/kuzu/kuzu-adapter.js +753 -0
- package/dist/core/kuzu/schema.d.ts +53 -0
- package/dist/core/kuzu/schema.js +407 -0
- package/dist/core/search/bm25-index.d.ts +23 -0
- package/dist/core/search/bm25-index.js +95 -0
- package/dist/core/search/hybrid-search.d.ts +49 -0
- package/dist/core/search/hybrid-search.js +118 -0
- package/dist/core/tree-sitter/parser-loader.d.ts +4 -0
- package/dist/core/tree-sitter/parser-loader.js +44 -0
- package/dist/core/wiki/generator.d.ts +110 -0
- package/dist/core/wiki/generator.js +786 -0
- package/dist/core/wiki/graph-queries.d.ts +80 -0
- package/dist/core/wiki/graph-queries.js +238 -0
- package/dist/core/wiki/html-viewer.d.ts +10 -0
- package/dist/core/wiki/html-viewer.js +297 -0
- package/dist/core/wiki/llm-client.d.ts +40 -0
- package/dist/core/wiki/llm-client.js +162 -0
- package/dist/core/wiki/prompts.d.ts +53 -0
- package/dist/core/wiki/prompts.js +174 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +3 -0
- package/dist/mcp/core/embedder.d.ts +27 -0
- package/dist/mcp/core/embedder.js +108 -0
- package/dist/mcp/core/kuzu-adapter.d.ts +34 -0
- package/dist/mcp/core/kuzu-adapter.js +231 -0
- package/dist/mcp/local/local-backend.d.ts +160 -0
- package/dist/mcp/local/local-backend.js +1646 -0
- package/dist/mcp/resources.d.ts +31 -0
- package/dist/mcp/resources.js +407 -0
- package/dist/mcp/server.d.ts +23 -0
- package/dist/mcp/server.js +251 -0
- package/dist/mcp/staleness.d.ts +15 -0
- package/dist/mcp/staleness.js +29 -0
- package/dist/mcp/tools.d.ts +24 -0
- package/dist/mcp/tools.js +195 -0
- package/dist/server/api.d.ts +10 -0
- package/dist/server/api.js +344 -0
- package/dist/server/mcp-http.d.ts +13 -0
- package/dist/server/mcp-http.js +100 -0
- package/dist/storage/git.d.ts +6 -0
- package/dist/storage/git.js +32 -0
- package/dist/storage/repo-manager.d.ts +125 -0
- package/dist/storage/repo-manager.js +257 -0
- package/dist/types/pipeline.d.ts +34 -0
- package/dist/types/pipeline.js +18 -0
- package/hooks/claude/gitnexus-hook.cjs +135 -0
- package/hooks/claude/pre-tool-use.sh +78 -0
- package/hooks/claude/session-start.sh +42 -0
- package/package.json +92 -0
- package/skills/gitnexus-cli.md +82 -0
- package/skills/gitnexus-debugging.md +89 -0
- package/skills/gitnexus-exploring.md +78 -0
- package/skills/gitnexus-guide.md +64 -0
- package/skills/gitnexus-impact-analysis.md +97 -0
- package/skills/gitnexus-refactoring.md +121 -0
- package/vendor/leiden/index.cjs +355 -0
- package/vendor/leiden/utils.cjs +392 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Context Generator
|
|
3
|
+
*
|
|
4
|
+
* Creates AGENTS.md and CLAUDE.md with full inline GitNexus context.
|
|
5
|
+
* AGENTS.md is the standard read by Cursor, Windsurf, OpenCode, Cline, etc.
|
|
6
|
+
* CLAUDE.md is for Claude Code which only reads that file.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs/promises';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
// ESM equivalent of __dirname
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
const GITNEXUS_START_MARKER = '<!-- gitnexus:start -->';
|
|
15
|
+
const GITNEXUS_END_MARKER = '<!-- gitnexus:end -->';
|
|
16
|
+
/**
|
|
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 read
|
|
21
|
+
* - Skills contain the actual workflows — AGENTS.md does NOT duplicate them
|
|
22
|
+
* - Bold **IMPORTANT** block + "Skills — Read First" heading — agents skip soft suggestions
|
|
23
|
+
* - One-line quick start (read context resource) gives agents an entry point
|
|
24
|
+
* - Tools/Resources sections are labeled "Reference" — agents treat them as lookup, not workflow
|
|
25
|
+
*/
|
|
26
|
+
function generateGitNexusContent(projectName, stats) {
|
|
27
|
+
return `${GITNEXUS_START_MARKER}
|
|
28
|
+
# GitNexus MCP
|
|
29
|
+
|
|
30
|
+
This project is indexed by GitNexus as **${projectName}** (${stats.nodes || 0} symbols, ${stats.edges || 0} relationships, ${stats.processes || 0} execution flows).
|
|
31
|
+
|
|
32
|
+
## Always Start Here
|
|
33
|
+
|
|
34
|
+
1. **Read \`gitnexus://repo/{name}/context\`** — codebase overview + check index freshness
|
|
35
|
+
2. **Match your task to a skill below** and **read that skill file**
|
|
36
|
+
3. **Follow the skill's workflow and checklist**
|
|
37
|
+
|
|
38
|
+
> If step 1 warns the index is stale, run \`npx gitnexus analyze\` in the terminal first.
|
|
39
|
+
|
|
40
|
+
## Skills
|
|
41
|
+
|
|
42
|
+
| Task | Read this skill file |
|
|
43
|
+
|------|---------------------|
|
|
44
|
+
| Understand architecture / "How does X work?" | \`.agents/skills/gitnexus/gitnexus-exploring/SKILL.md\` |
|
|
45
|
+
| Blast radius / "What breaks if I change X?" | \`.agents/skills/gitnexus/gitnexus-impact-analysis/SKILL.md\` |
|
|
46
|
+
| Trace bugs / "Why is X failing?" | \`.agents/skills/gitnexus/gitnexus-debugging/SKILL.md\` |
|
|
47
|
+
| Rename / extract / split / refactor | \`.agents/skills/gitnexus/gitnexus-refactoring/SKILL.md\` |
|
|
48
|
+
| Tools, resources, schema reference | \`.agents/skills/gitnexus/gitnexus-guide/SKILL.md\` |
|
|
49
|
+
| Index, status, clean, wiki CLI commands | \`.agents/skills/gitnexus/gitnexus-cli/SKILL.md\` |
|
|
50
|
+
|
|
51
|
+
${GITNEXUS_END_MARKER}`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if a file exists
|
|
55
|
+
*/
|
|
56
|
+
async function fileExists(filePath) {
|
|
57
|
+
try {
|
|
58
|
+
await fs.access(filePath);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create or update GitNexus section in a file
|
|
67
|
+
* - If file doesn't exist: create with GitNexus content
|
|
68
|
+
* - If file exists without GitNexus section: append
|
|
69
|
+
* - If file exists with GitNexus section: replace that section
|
|
70
|
+
*/
|
|
71
|
+
async function upsertGitNexusSection(filePath, content) {
|
|
72
|
+
const exists = await fileExists(filePath);
|
|
73
|
+
if (!exists) {
|
|
74
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
75
|
+
return 'created';
|
|
76
|
+
}
|
|
77
|
+
const existingContent = await fs.readFile(filePath, 'utf-8');
|
|
78
|
+
// Check if GitNexus section already exists
|
|
79
|
+
const startIdx = existingContent.indexOf(GITNEXUS_START_MARKER);
|
|
80
|
+
const endIdx = existingContent.indexOf(GITNEXUS_END_MARKER);
|
|
81
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
82
|
+
// Replace existing section
|
|
83
|
+
const before = existingContent.substring(0, startIdx);
|
|
84
|
+
const after = existingContent.substring(endIdx + GITNEXUS_END_MARKER.length);
|
|
85
|
+
const newContent = before + content + after;
|
|
86
|
+
await fs.writeFile(filePath, newContent.trim() + '\n', 'utf-8');
|
|
87
|
+
return 'updated';
|
|
88
|
+
}
|
|
89
|
+
// Append new section
|
|
90
|
+
const newContent = existingContent.trim() + '\n\n' + content + '\n';
|
|
91
|
+
await fs.writeFile(filePath, newContent, 'utf-8');
|
|
92
|
+
return 'appended';
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Install repo-local GitNexus skills to .agents/skills/gitnexus/
|
|
96
|
+
* AGENTS.md should reference this path consistently.
|
|
97
|
+
*/
|
|
98
|
+
async function installSkills(repoPath) {
|
|
99
|
+
const skillsDir = path.join(repoPath, '.agents', 'skills', 'gitnexus');
|
|
100
|
+
const installedSkills = [];
|
|
101
|
+
// Skill definitions bundled with the package
|
|
102
|
+
const skills = [
|
|
103
|
+
{
|
|
104
|
+
name: 'gitnexus-exploring',
|
|
105
|
+
description: 'Use when the user asks how code works, wants to understand architecture, trace execution flows, or explore unfamiliar parts of the codebase. Examples: "How does X work?", "What calls this function?", "Show me the auth flow"',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'gitnexus-debugging',
|
|
109
|
+
description: 'Use when the user is debugging a bug, tracing an error, or asking why something fails. Examples: "Why is X failing?", "Where does this error come from?", "Trace this bug"',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: 'gitnexus-impact-analysis',
|
|
113
|
+
description: 'Use when the user wants to know what will break if they change something, or needs safety analysis before editing code. Examples: "Is it safe to change X?", "What depends on this?", "What will break?"',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'gitnexus-refactoring',
|
|
117
|
+
description: 'Use when the user wants to rename, extract, split, move, or restructure code safely. Examples: "Rename this function", "Extract this into a module", "Refactor this class", "Move this to a separate file"',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: 'gitnexus-guide',
|
|
121
|
+
description: 'Use when the user asks about GitNexus itself — available tools, how to query the knowledge graph, MCP resources, graph schema, or workflow reference. Examples: "What GitNexus tools are available?", "How do I use GitNexus?"',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'gitnexus-cli',
|
|
125
|
+
description: 'Use when the user needs to run GitNexus CLI commands like analyze/index a repo, check status, clean the index, generate a wiki, or list indexed repos. Examples: "Index this repo", "Reanalyze the codebase", "Generate a wiki"',
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
for (const skill of skills) {
|
|
129
|
+
const skillDir = path.join(skillsDir, skill.name);
|
|
130
|
+
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
131
|
+
try {
|
|
132
|
+
// Create skill directory
|
|
133
|
+
await fs.mkdir(skillDir, { recursive: true });
|
|
134
|
+
// Try to read from package skills directory
|
|
135
|
+
const packageSkillPath = path.join(__dirname, '..', '..', 'skills', `${skill.name}.md`);
|
|
136
|
+
let skillContent;
|
|
137
|
+
try {
|
|
138
|
+
skillContent = await fs.readFile(packageSkillPath, 'utf-8');
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Fallback: generate minimal skill content
|
|
142
|
+
skillContent = `---
|
|
143
|
+
name: ${skill.name}
|
|
144
|
+
description: ${skill.description}
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
# ${skill.name.charAt(0).toUpperCase() + skill.name.slice(1)}
|
|
148
|
+
|
|
149
|
+
${skill.description}
|
|
150
|
+
|
|
151
|
+
Use GitNexus tools to accomplish this task.
|
|
152
|
+
`;
|
|
153
|
+
}
|
|
154
|
+
await fs.writeFile(skillPath, skillContent, 'utf-8');
|
|
155
|
+
installedSkills.push(skill.name);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
// Skip on error, don't fail the whole process
|
|
159
|
+
console.warn(`Warning: Could not install skill ${skill.name}:`, err);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return installedSkills;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Generate AI context files after indexing
|
|
166
|
+
*/
|
|
167
|
+
export async function generateAIContextFiles(repoPath, _storagePath, projectName, stats) {
|
|
168
|
+
const content = generateGitNexusContent(projectName, stats);
|
|
169
|
+
const createdFiles = [];
|
|
170
|
+
// Create AGENTS.md (standard for Cursor, Windsurf, OpenCode, Cline, etc.)
|
|
171
|
+
const agentsPath = path.join(repoPath, 'AGENTS.md');
|
|
172
|
+
const agentsResult = await upsertGitNexusSection(agentsPath, content);
|
|
173
|
+
createdFiles.push(`AGENTS.md (${agentsResult})`);
|
|
174
|
+
// Create CLAUDE.md (for Claude Code)
|
|
175
|
+
const claudePath = path.join(repoPath, 'CLAUDE.md');
|
|
176
|
+
const claudeResult = await upsertGitNexusSection(claudePath, content);
|
|
177
|
+
createdFiles.push(`CLAUDE.md (${claudeResult})`);
|
|
178
|
+
// Install skills to .agents/skills/gitnexus/
|
|
179
|
+
const installedSkills = await installSkills(repoPath);
|
|
180
|
+
if (installedSkills.length > 0) {
|
|
181
|
+
createdFiles.push(`.agents/skills/gitnexus/ (${installedSkills.length} skills)`);
|
|
182
|
+
}
|
|
183
|
+
return { files: createdFiles };
|
|
184
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import { generateAIContextFiles } from './ai-context.js';
|
|
7
|
+
test('generateAIContextFiles installs repo skills under .agents/skills/gitnexus', async () => {
|
|
8
|
+
const repoPath = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-ai-context-'));
|
|
9
|
+
try {
|
|
10
|
+
const result = await generateAIContextFiles(repoPath, '', 'demo-repo', {
|
|
11
|
+
nodes: 1,
|
|
12
|
+
edges: 2,
|
|
13
|
+
processes: 3,
|
|
14
|
+
});
|
|
15
|
+
const agentsPath = path.join(repoPath, 'AGENTS.md');
|
|
16
|
+
const claudePath = path.join(repoPath, 'CLAUDE.md');
|
|
17
|
+
const skillPath = path.join(repoPath, '.agents', 'skills', 'gitnexus', 'gitnexus-exploring', 'SKILL.md');
|
|
18
|
+
const legacyClaudeSkillsDir = path.join(repoPath, '.claude', 'skills');
|
|
19
|
+
const agentsContent = await fs.readFile(agentsPath, 'utf-8');
|
|
20
|
+
const claudeContent = await fs.readFile(claudePath, 'utf-8');
|
|
21
|
+
await fs.access(skillPath);
|
|
22
|
+
assert.match(agentsContent, /\.agents\/skills\/gitnexus\/gitnexus-exploring\/SKILL\.md/);
|
|
23
|
+
assert.match(claudeContent, /\.agents\/skills\/gitnexus\/gitnexus-exploring\/SKILL\.md/);
|
|
24
|
+
assert.ok(result.files.some((entry) => entry.includes('.agents/skills/gitnexus/')), 'expected generated file summary to include .agents/skills/gitnexus/');
|
|
25
|
+
await assert.rejects(fs.access(legacyClaudeSkillsDir));
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
await fs.rm(repoPath, { recursive: true, force: true });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { runPipelineFromRepo } from '../core/ingestion/pipeline.js';
|
|
6
|
+
test('runPipelineFromRepo deduplicates overlapping scope matches and reports diagnostics', { timeout: 60_000 }, async () => {
|
|
7
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const fixtureRepo = path.resolve(here, '../../../benchmarks/fixtures/unity-mini');
|
|
9
|
+
const result = await runPipelineFromRepo(fixtureRepo, () => { }, {
|
|
10
|
+
includeExtensions: ['.cs'],
|
|
11
|
+
scopeRules: ['Assets', 'Assets/Scripts'],
|
|
12
|
+
});
|
|
13
|
+
const fileNodes = [...result.graph.iterNodes()].filter((node) => node.label === 'File');
|
|
14
|
+
const uniqueFilePaths = new Set(fileNodes.map((node) => String(node.properties.filePath)));
|
|
15
|
+
assert.equal(uniqueFilePaths.size, 3);
|
|
16
|
+
assert.equal(fileNodes.length, 3);
|
|
17
|
+
assert.equal(result.scopeDiagnostics?.appliedRuleCount, 2);
|
|
18
|
+
assert.equal(result.scopeDiagnostics?.matchedFiles, 3);
|
|
19
|
+
assert.equal(result.scopeDiagnostics?.overlapFiles, 3);
|
|
20
|
+
assert.equal(result.scopeDiagnostics?.dedupedMatchCount, 3);
|
|
21
|
+
assert.equal(result.scopeDiagnostics?.normalizedCollisions.length, 0);
|
|
22
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface AnalyzeScopeOptions {
|
|
2
|
+
scopeManifest?: string;
|
|
3
|
+
scopePrefix?: string[] | string;
|
|
4
|
+
}
|
|
5
|
+
export declare function parseExtensionList(rawExtensions?: string): string[];
|
|
6
|
+
export declare function normalizeRepoAlias(repoAlias?: string): string | undefined;
|
|
7
|
+
export declare function resolveAnalyzeScopeRules(options?: AnalyzeScopeOptions): Promise<string[]>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { normalizeScopeRules, parseScopeRules } from '../core/ingestion/scope-filter.js';
|
|
4
|
+
const REPO_ALIAS_REGEX = /^[a-zA-Z0-9._-]{3,64}$/;
|
|
5
|
+
export function parseExtensionList(rawExtensions) {
|
|
6
|
+
return (rawExtensions || '')
|
|
7
|
+
.split(',')
|
|
8
|
+
.map((ext) => ext.trim().toLowerCase())
|
|
9
|
+
.filter(Boolean)
|
|
10
|
+
.map((ext) => (ext.startsWith('.') ? ext : `.${ext}`));
|
|
11
|
+
}
|
|
12
|
+
export function normalizeRepoAlias(repoAlias) {
|
|
13
|
+
if (!repoAlias)
|
|
14
|
+
return undefined;
|
|
15
|
+
const normalized = repoAlias.trim();
|
|
16
|
+
if (!normalized)
|
|
17
|
+
return undefined;
|
|
18
|
+
if (!REPO_ALIAS_REGEX.test(normalized)) {
|
|
19
|
+
throw new Error('Invalid repo alias. Use ^[a-zA-Z0-9._-]{3,64}$');
|
|
20
|
+
}
|
|
21
|
+
return normalized;
|
|
22
|
+
}
|
|
23
|
+
export async function resolveAnalyzeScopeRules(options) {
|
|
24
|
+
const rules = [];
|
|
25
|
+
if (options?.scopeManifest) {
|
|
26
|
+
const manifestPath = path.resolve(options.scopeManifest);
|
|
27
|
+
let content;
|
|
28
|
+
try {
|
|
29
|
+
content = await fs.readFile(manifestPath, 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
throw new Error(`Scope manifest not found: ${manifestPath}`);
|
|
33
|
+
}
|
|
34
|
+
const manifestRules = parseScopeRules(content);
|
|
35
|
+
if (manifestRules.length === 0) {
|
|
36
|
+
throw new Error(`Scope manifest has no valid scope rules: ${manifestPath}`);
|
|
37
|
+
}
|
|
38
|
+
rules.push(...manifestRules);
|
|
39
|
+
}
|
|
40
|
+
const prefixesRaw = Array.isArray(options?.scopePrefix)
|
|
41
|
+
? options?.scopePrefix || []
|
|
42
|
+
: options?.scopePrefix
|
|
43
|
+
? [options.scopePrefix]
|
|
44
|
+
: [];
|
|
45
|
+
for (const prefix of prefixesRaw) {
|
|
46
|
+
const trimmed = prefix.trim();
|
|
47
|
+
if (trimmed) {
|
|
48
|
+
rules.push(trimmed);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const normalizedRules = normalizeScopeRules(rules);
|
|
52
|
+
if ((options?.scopeManifest || prefixesRaw.length > 0) && normalizedRules.length === 0) {
|
|
53
|
+
throw new Error('No valid scope rules provided.');
|
|
54
|
+
}
|
|
55
|
+
return normalizedRules;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { normalizeRepoAlias, parseExtensionList, resolveAnalyzeScopeRules } from './analyze-options.js';
|
|
7
|
+
test('parseExtensionList normalizes dot prefixes', () => {
|
|
8
|
+
const exts = parseExtensionList('cs,.ts, go ');
|
|
9
|
+
assert.deepEqual(exts, ['.cs', '.ts', '.go']);
|
|
10
|
+
});
|
|
11
|
+
test('normalizeRepoAlias validates format', () => {
|
|
12
|
+
assert.equal(normalizeRepoAlias(undefined), undefined);
|
|
13
|
+
assert.equal(normalizeRepoAlias('neonspark-v1-subset'), 'neonspark-v1-subset');
|
|
14
|
+
assert.throws(() => normalizeRepoAlias('ab'), /repo alias/i);
|
|
15
|
+
assert.throws(() => normalizeRepoAlias('bad alias'), /repo alias/i);
|
|
16
|
+
});
|
|
17
|
+
test('resolveAnalyzeScopeRules combines manifest and repeated prefixes', async () => {
|
|
18
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-scope-test-'));
|
|
19
|
+
const manifestPath = path.join(tmpDir, 'scope.txt');
|
|
20
|
+
await fs.writeFile(manifestPath, '# comment\nAssets/NEON/Code\n\nPackages/com.veewo.*\n', 'utf-8');
|
|
21
|
+
const rules = await resolveAnalyzeScopeRules({
|
|
22
|
+
scopeManifest: manifestPath,
|
|
23
|
+
scopePrefix: ['Packages/com.neonspark.*'],
|
|
24
|
+
});
|
|
25
|
+
assert.deepEqual(rules, [
|
|
26
|
+
'Assets/NEON/Code',
|
|
27
|
+
'Packages/com.veewo.*',
|
|
28
|
+
'Packages/com.neonspark.*',
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
test('resolveAnalyzeScopeRules fails when manifest has no usable rule', async () => {
|
|
32
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-scope-test-'));
|
|
33
|
+
const manifestPath = path.join(tmpDir, 'empty-scope.txt');
|
|
34
|
+
await fs.writeFile(manifestPath, '# only comments\n\n', 'utf-8');
|
|
35
|
+
await assert.rejects(resolveAnalyzeScopeRules({ scopeManifest: manifestPath }), /no valid scope rules/i);
|
|
36
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze Command
|
|
3
|
+
*
|
|
4
|
+
* Indexes a repository and stores the knowledge graph in .gitnexus/
|
|
5
|
+
*/
|
|
6
|
+
export interface AnalyzeOptions {
|
|
7
|
+
force?: boolean;
|
|
8
|
+
embeddings?: boolean;
|
|
9
|
+
extensions?: string;
|
|
10
|
+
repoAlias?: string;
|
|
11
|
+
scopeManifest?: string;
|
|
12
|
+
scopePrefix?: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare const analyzeCommand: (inputPath?: string, options?: AnalyzeOptions) => Promise<void>;
|