@veewo/gitnexus 1.5.0-rc.4 → 1.5.1
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/benchmark/agent-context/runner.js +3 -0
- package/dist/benchmark/agent-context/runner.test.js +22 -0
- package/dist/benchmark/agent-context/tool-runner.d.ts +7 -6
- package/dist/benchmark/agent-safe-query-context/io.d.ts +2 -0
- package/dist/benchmark/agent-safe-query-context/io.js +86 -0
- package/dist/benchmark/agent-safe-query-context/io.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/io.test.js +13 -0
- package/dist/benchmark/agent-safe-query-context/report.d.ts +57 -0
- package/dist/benchmark/agent-safe-query-context/report.js +159 -0
- package/dist/benchmark/agent-safe-query-context/report.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/report.test.js +362 -0
- package/dist/benchmark/agent-safe-query-context/runner.d.ts +44 -0
- package/dist/benchmark/agent-safe-query-context/runner.js +406 -0
- package/dist/benchmark/agent-safe-query-context/runner.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/runner.test.js +290 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.d.ts +20 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.js +225 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/semantic-tuple.test.js +122 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.d.ts +47 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.js +128 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.test.d.ts +1 -0
- package/dist/benchmark/agent-safe-query-context/subagent-live.test.js +155 -0
- package/dist/benchmark/agent-safe-query-context/telemetry-tool.d.ts +9 -0
- package/dist/benchmark/agent-safe-query-context/telemetry-tool.js +77 -0
- package/dist/benchmark/agent-safe-query-context/types.d.ts +61 -0
- package/dist/benchmark/agent-safe-query-context/types.js +8 -0
- package/dist/benchmark/analyze-runner.d.ts +1 -1
- package/dist/benchmark/analyze-runner.js +4 -3
- package/dist/benchmark/analyze-runner.test.js +7 -0
- package/dist/benchmark/runtime-poc/provenance-artifact.d.ts +47 -0
- package/dist/benchmark/runtime-poc/provenance-artifact.js +89 -0
- package/dist/benchmark/runtime-poc/runner.d.ts +31 -0
- package/dist/benchmark/runtime-poc/runner.js +163 -0
- package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.d.ts +8 -0
- package/dist/benchmark/u2-e2e/hydration-policy-repeatability-runner.js +21 -0
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.d.ts +0 -1
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.js +53 -51
- package/dist/benchmark/u2-e2e/phase2-runtime-claim-acceptance-runner.test.js +0 -1
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.d.ts +1 -1
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.js +82 -18
- package/dist/benchmark/u2-e2e/phase5-rule-lab-acceptance-runner.test.js +1 -2
- package/dist/benchmark/u2-e2e/retrieval-runner.js +15 -7
- package/dist/benchmark/u2-e2e/retrieval-runner.test.js +46 -0
- package/dist/cli/ai-context.d.ts +0 -1
- package/dist/cli/ai-context.js +5 -6
- package/dist/cli/ai-context.test.js +8 -0
- package/dist/cli/analyze-options.js +58 -34
- package/dist/cli/analyze-options.test.js +57 -0
- package/dist/cli/analyze-runtime-summary.js +2 -0
- package/dist/cli/analyze-runtime-summary.test.js +12 -0
- package/dist/cli/analyze-summary.d.ts +4 -0
- package/dist/cli/analyze-summary.js +43 -0
- package/dist/cli/analyze-summary.test.js +65 -1
- package/dist/cli/analyze.d.ts +11 -0
- package/dist/cli/analyze.js +34 -5
- package/dist/cli/analyze.test.d.ts +1 -0
- package/dist/cli/analyze.test.js +25 -0
- package/dist/cli/benchmark-agent-context.js +1 -1
- package/dist/cli/benchmark-agent-safe-query-context.d.ts +20 -0
- package/dist/cli/benchmark-agent-safe-query-context.js +39 -0
- package/dist/cli/benchmark-agent-safe-query-context.test.d.ts +1 -0
- package/dist/cli/benchmark-agent-safe-query-context.test.js +271 -0
- package/dist/cli/benchmark-unity.js +1 -1
- package/dist/cli/benchmark-unity.test.js +5 -1
- package/dist/cli/benchmark.d.ts +29 -0
- package/dist/cli/benchmark.js +55 -0
- package/dist/cli/index.js +27 -2
- package/dist/cli/rule-lab.d.ts +3 -7
- package/dist/cli/rule-lab.js +13 -22
- package/dist/cli/rule-lab.test.js +23 -3
- package/dist/cli/scope-manifest-config.d.ts +9 -0
- package/dist/cli/scope-manifest-config.js +37 -0
- package/dist/cli/setup.js +40 -41
- package/dist/cli/setup.test.js +14 -14
- package/dist/cli/sync-manifest.d.ts +27 -0
- package/dist/cli/sync-manifest.js +200 -0
- package/dist/cli/sync-manifest.test.d.ts +1 -0
- package/dist/cli/sync-manifest.test.js +88 -0
- package/dist/cli/tool.d.ts +2 -0
- package/dist/cli/tool.js +2 -0
- package/dist/core/config/unity-config.d.ts +1 -1
- package/dist/core/config/unity-config.js +1 -1
- package/dist/core/ingestion/call-processor.d.ts +2 -1
- package/dist/core/ingestion/call-processor.js +28 -6
- package/dist/core/ingestion/heritage-processor.d.ts +2 -1
- package/dist/core/ingestion/heritage-processor.js +30 -7
- package/dist/core/ingestion/import-processor.d.ts +2 -1
- package/dist/core/ingestion/import-processor.js +28 -6
- package/dist/core/ingestion/parsing-processor.d.ts +5 -3
- package/dist/core/ingestion/parsing-processor.js +46 -13
- package/dist/core/ingestion/pipeline.js +100 -19
- package/dist/core/ingestion/unity-lifecycle-synthetic-calls.test.js +18 -20
- package/dist/core/ingestion/unity-parity-seed.d.ts +2 -1
- package/dist/core/ingestion/unity-parity-seed.js +8 -0
- package/dist/core/ingestion/unity-resource-processor.d.ts +11 -0
- package/dist/core/ingestion/unity-resource-processor.js +102 -0
- package/dist/core/ingestion/unity-resource-processor.test.js +449 -0
- package/dist/core/ingestion/unity-runtime-binding-rules.d.ts +16 -1
- package/dist/core/ingestion/unity-runtime-binding-rules.js +193 -42
- package/dist/core/ingestion/workers/parse-worker.d.ts +2 -0
- package/dist/core/ingestion/workers/parse-worker.js +50 -6
- package/dist/core/lbug/csv-generator.test.js +2 -2
- package/dist/core/tree-sitter/csharp-define-profile.d.ts +6 -0
- package/dist/core/tree-sitter/csharp-define-profile.js +43 -0
- package/dist/core/tree-sitter/csharp-preproc-normalizer.d.ts +14 -0
- package/dist/core/tree-sitter/csharp-preproc-normalizer.js +261 -0
- package/dist/core/tree-sitter/parser-loader.d.ts +10 -0
- package/dist/core/tree-sitter/parser-loader.js +19 -0
- package/dist/core/unity/doc-contract.test.d.ts +1 -0
- package/dist/core/unity/doc-contract.test.js +30 -0
- package/dist/core/unity/prefab-source-scan.d.ts +25 -0
- package/dist/core/unity/prefab-source-scan.js +152 -0
- package/dist/core/unity/prefab-source-scan.test.d.ts +1 -0
- package/dist/core/unity/prefab-source-scan.test.js +70 -0
- package/dist/core/unity/scan-context.d.ts +12 -0
- package/dist/core/unity/scan-context.js +50 -2
- package/dist/core/unity/scan-context.test.js +74 -0
- package/dist/mcp/local/agent-safe-response.d.ts +10 -0
- package/dist/mcp/local/agent-safe-response.js +639 -0
- package/dist/mcp/local/derived-process-reader.js +1 -1
- package/dist/mcp/local/local-backend.d.ts +18 -1
- package/dist/mcp/local/local-backend.js +319 -125
- package/dist/mcp/local/process-confidence.d.ts +1 -2
- package/dist/mcp/local/process-confidence.js +0 -3
- package/dist/mcp/local/process-confidence.test.js +4 -2
- package/dist/mcp/local/process-evidence.d.ts +1 -8
- package/dist/mcp/local/process-evidence.js +1 -23
- package/dist/mcp/local/process-evidence.test.js +2 -16
- package/dist/mcp/local/process-ref.d.ts +1 -1
- package/dist/mcp/local/runtime-chain-closure-evaluator.d.ts +33 -0
- package/dist/mcp/local/runtime-chain-closure-evaluator.js +273 -0
- package/dist/mcp/local/runtime-chain-graph-candidates.d.ts +23 -0
- package/dist/mcp/local/runtime-chain-graph-candidates.js +131 -0
- package/dist/mcp/local/runtime-chain-verify.d.ts +1 -1
- package/dist/mcp/local/runtime-chain-verify.js +149 -138
- package/dist/mcp/local/runtime-chain-verify.test.js +126 -68
- package/dist/mcp/local/runtime-claim-rule-registry.d.ts +4 -0
- package/dist/mcp/local/runtime-claim-rule-registry.js +4 -0
- package/dist/mcp/local/runtime-claim-rule-registry.test.js +37 -4
- package/dist/mcp/local/runtime-claim.d.ts +11 -0
- package/dist/mcp/local/runtime-claim.js +28 -0
- package/dist/mcp/local/unity-evidence-view.d.ts +1 -1
- package/dist/mcp/local/unity-evidence-view.js +1 -1
- package/dist/mcp/local/unity-evidence-view.test.js +22 -0
- package/dist/mcp/tools.js +51 -21
- package/dist/rule-lab/analyze.d.ts +2 -1
- package/dist/rule-lab/analyze.js +94 -59
- package/dist/rule-lab/analyze.test.js +238 -20
- package/dist/rule-lab/curate.d.ts +2 -1
- package/dist/rule-lab/curate.js +24 -3
- package/dist/rule-lab/curate.test.js +65 -0
- package/dist/rule-lab/curation-input-builder.d.ts +45 -0
- package/dist/rule-lab/curation-input-builder.js +133 -0
- package/dist/rule-lab/promote.js +80 -7
- package/dist/rule-lab/promote.test.js +150 -0
- package/dist/rule-lab/review-pack.d.ts +3 -0
- package/dist/rule-lab/review-pack.js +41 -1
- package/dist/rule-lab/review-pack.test.js +67 -0
- package/dist/rule-lab/types.d.ts +29 -0
- package/dist/types/pipeline.d.ts +16 -0
- package/package.json +14 -13
- package/scripts/check-sync-manifest-traceability.mjs +203 -0
- package/scripts/run-node-tests.mjs +61 -0
- package/scripts/tree-sitter-audit-classify.mjs +172 -0
- package/skills/_shared/unity-rule-authoring-contract.md +64 -0
- package/skills/_shared/unity-runtime-process-contract.md +16 -0
- package/skills/gitnexus-cli.md +44 -4
- package/skills/gitnexus-debugging.md +9 -0
- package/skills/gitnexus-exploring.md +66 -18
- package/skills/gitnexus-guide.md +42 -3
- package/skills/gitnexus-impact-analysis.md +8 -0
- package/skills/gitnexus-pr-review.md +8 -0
- package/skills/gitnexus-refactoring.md +8 -0
- package/skills/gitnexus-unity-rule-gen.md +66 -312
package/dist/cli/rule-lab.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { writeSync } from 'node:fs';
|
|
2
2
|
import fs from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { discoverRuleLabRun } from '../rule-lab/discover.js';
|
|
5
4
|
import { analyzeRuleLabSlice } from '../rule-lab/analyze.js';
|
|
6
5
|
import { buildReviewPack } from '../rule-lab/review-pack.js';
|
|
7
6
|
import { curateRuleLabSlice } from '../rule-lab/curate.js';
|
|
8
7
|
import { promoteCuratedRules } from '../rule-lab/promote.js';
|
|
9
8
|
import { runRuleLabRegress } from '../rule-lab/regress.js';
|
|
10
9
|
import { compileRules } from '../rule-lab/compile.js';
|
|
11
|
-
const RULE_LAB_COMMANDS = ['
|
|
10
|
+
const RULE_LAB_COMMANDS = ['analyze', 'review-pack', 'curate', 'promote', 'regress'];
|
|
12
11
|
function output(data) {
|
|
13
12
|
const text = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
14
13
|
writeSync(1, `${text}\n`);
|
|
@@ -16,6 +15,11 @@ function output(data) {
|
|
|
16
15
|
function resolveRepoPath(repoPath) {
|
|
17
16
|
return path.resolve(repoPath || process.cwd());
|
|
18
17
|
}
|
|
18
|
+
function assertConcreteRunSliceIds(runId, sliceId) {
|
|
19
|
+
if (/[<>]/.test(runId) || /[<>]/.test(sliceId)) {
|
|
20
|
+
throw new Error('Invalid run/slice id: placeholder values are not allowed');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
19
23
|
export function getRuleLabCommandNames(program) {
|
|
20
24
|
const root = program.commands.find((command) => command.name() === 'rule-lab');
|
|
21
25
|
if (!root)
|
|
@@ -27,8 +31,6 @@ export function attachRuleLabCommands(program, lazyFactory) {
|
|
|
27
31
|
if (lazyFactory)
|
|
28
32
|
return lazyFactory(handlerName);
|
|
29
33
|
switch (handlerName) {
|
|
30
|
-
case 'ruleLabDiscoverCommand':
|
|
31
|
-
return (options) => ruleLabDiscoverCommand(options);
|
|
32
34
|
case 'ruleLabAnalyzeCommand':
|
|
33
35
|
return (options) => ruleLabAnalyzeCommand(options);
|
|
34
36
|
case 'ruleLabReviewPackCommand':
|
|
@@ -47,13 +49,7 @@ export function attachRuleLabCommands(program, lazyFactory) {
|
|
|
47
49
|
};
|
|
48
50
|
const root = program
|
|
49
51
|
.command('rule-lab')
|
|
50
|
-
.description('Offline rule-lab workflow for
|
|
51
|
-
root
|
|
52
|
-
.command('discover')
|
|
53
|
-
.option('--repo-path <path>', 'Repository path (default: cwd)')
|
|
54
|
-
.option('--scope <scope>', 'Discovery scope: full|diff', 'full')
|
|
55
|
-
.option('--seed <seed>', 'Optional deterministic seed')
|
|
56
|
-
.action(action('ruleLabDiscoverCommand'));
|
|
52
|
+
.description('Offline rule-lab workflow for analyze/review-pack/curate/promote/regress');
|
|
57
53
|
root
|
|
58
54
|
.command('analyze')
|
|
59
55
|
.requiredOption('--run-id <id>', 'Rule-lab run id')
|
|
@@ -79,7 +75,7 @@ export function attachRuleLabCommands(program, lazyFactory) {
|
|
|
79
75
|
.requiredOption('--run-id <id>', 'Rule-lab run id')
|
|
80
76
|
.requiredOption('--slice-id <id>', 'Slice id')
|
|
81
77
|
.option('--repo-path <path>', 'Repository path (default: cwd)')
|
|
82
|
-
.option('--version <version>', 'Promoted rule version', '1.0.0')
|
|
78
|
+
.option('--rule-version <version>', 'Promoted rule version', '1.0.0')
|
|
83
79
|
.action(action('ruleLabPromoteCommand'));
|
|
84
80
|
root
|
|
85
81
|
.command('regress')
|
|
@@ -96,17 +92,11 @@ export function attachRuleLabCommands(program, lazyFactory) {
|
|
|
96
92
|
.option('--family <family>', 'Rule family to compile', 'analyze_rules')
|
|
97
93
|
.action((options) => compileRules({ repoPath: options.repoPath, family: options.family }));
|
|
98
94
|
}
|
|
99
|
-
export async function ruleLabDiscoverCommand(options) {
|
|
100
|
-
const result = await discoverRuleLabRun({
|
|
101
|
-
repoPath: resolveRepoPath(options?.repoPath),
|
|
102
|
-
scope: options?.scope || 'full',
|
|
103
|
-
seed: options?.seed,
|
|
104
|
-
});
|
|
105
|
-
output(result);
|
|
106
|
-
}
|
|
107
95
|
export async function ruleLabAnalyzeCommand(options) {
|
|
96
|
+
assertConcreteRunSliceIds(options.runId, options.sliceId);
|
|
97
|
+
const repoPath = resolveRepoPath(options?.repoPath);
|
|
108
98
|
const result = await analyzeRuleLabSlice({
|
|
109
|
-
repoPath
|
|
99
|
+
repoPath,
|
|
110
100
|
runId: options.runId,
|
|
111
101
|
sliceId: options.sliceId,
|
|
112
102
|
});
|
|
@@ -131,11 +121,12 @@ export async function ruleLabCurateCommand(options) {
|
|
|
131
121
|
output(result);
|
|
132
122
|
}
|
|
133
123
|
export async function ruleLabPromoteCommand(options) {
|
|
124
|
+
const version = options.ruleVersion ?? options.version;
|
|
134
125
|
const result = await promoteCuratedRules({
|
|
135
126
|
repoPath: resolveRepoPath(options?.repoPath),
|
|
136
127
|
runId: options.runId,
|
|
137
128
|
sliceId: options.sliceId,
|
|
138
|
-
version
|
|
129
|
+
version,
|
|
139
130
|
});
|
|
140
131
|
output(result);
|
|
141
132
|
}
|
|
@@ -1,11 +1,31 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
-
import { attachRuleLabCommands, getRuleLabCommandNames } from './rule-lab.js';
|
|
3
|
+
import { attachRuleLabCommands, getRuleLabCommandNames, ruleLabAnalyzeCommand } from './rule-lab.js';
|
|
4
4
|
describe('rule-lab cli', () => {
|
|
5
|
-
it('registers all
|
|
5
|
+
it('registers all rule-lab subcommands', async () => {
|
|
6
6
|
const program = new Command();
|
|
7
|
+
program.version('test-version');
|
|
7
8
|
attachRuleLabCommands(program);
|
|
8
9
|
const cmds = getRuleLabCommandNames(program);
|
|
9
|
-
expect(cmds).toEqual(['
|
|
10
|
+
expect(cmds).toEqual(['analyze', 'review-pack', 'curate', 'promote', 'regress', 'compile']);
|
|
11
|
+
});
|
|
12
|
+
it('uses --rule-version for promote to avoid root --version collision', () => {
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program.version('test-version');
|
|
15
|
+
attachRuleLabCommands(program);
|
|
16
|
+
const ruleLab = program.commands.find((command) => command.name() === 'rule-lab');
|
|
17
|
+
expect(ruleLab).toBeTruthy();
|
|
18
|
+
const promote = ruleLab?.commands.find((command) => command.name() === 'promote');
|
|
19
|
+
expect(promote).toBeTruthy();
|
|
20
|
+
const optionNames = (promote?.options || []).map((option) => option.long);
|
|
21
|
+
expect(optionNames).toContain('--rule-version');
|
|
22
|
+
expect(optionNames).not.toContain('--version');
|
|
23
|
+
});
|
|
24
|
+
it('rejects placeholder run/slice ids at analyze command boundary', async () => {
|
|
25
|
+
await expect(ruleLabAnalyzeCommand({
|
|
26
|
+
repoPath: process.cwd(),
|
|
27
|
+
runId: '<run_id>',
|
|
28
|
+
sliceId: '<slice_id>',
|
|
29
|
+
})).rejects.toThrow(/placeholder/i);
|
|
10
30
|
});
|
|
11
31
|
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { normalizeScopeRules, normalizeScopedPath } from '../core/ingestion/scope-filter.js';
|
|
2
|
+
const SUPPORTED_DIRECTIVES = new Set(['extensions', 'repoalias', 'embeddings']);
|
|
3
|
+
export function parseScopeManifestConfig(raw) {
|
|
4
|
+
const scopeRules = [];
|
|
5
|
+
const directives = {};
|
|
6
|
+
const lines = raw.split(/\r?\n/);
|
|
7
|
+
for (const [index, line] of lines.entries()) {
|
|
8
|
+
const trimmed = line.trim();
|
|
9
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
10
|
+
continue;
|
|
11
|
+
if (trimmed.startsWith('@')) {
|
|
12
|
+
const separatorIndex = trimmed.indexOf('=');
|
|
13
|
+
if (separatorIndex <= 1) {
|
|
14
|
+
throw new Error(`Invalid manifest directive at line ${index + 1}: ${trimmed}`);
|
|
15
|
+
}
|
|
16
|
+
const key = trimmed.slice(1, separatorIndex).trim().toLowerCase();
|
|
17
|
+
const value = trimmed.slice(separatorIndex + 1).trim();
|
|
18
|
+
if (!SUPPORTED_DIRECTIVES.has(key)) {
|
|
19
|
+
throw new Error(`Unknown manifest directive: @${key}`);
|
|
20
|
+
}
|
|
21
|
+
if (key === 'extensions')
|
|
22
|
+
directives.extensions = value;
|
|
23
|
+
else if (key === 'repoalias')
|
|
24
|
+
directives.repoAlias = value;
|
|
25
|
+
else if (key === 'embeddings')
|
|
26
|
+
directives.embeddings = value;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const normalized = normalizeScopedPath(trimmed);
|
|
30
|
+
if (normalized)
|
|
31
|
+
scopeRules.push(normalized);
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
scopeRules: normalizeScopeRules(scopeRules),
|
|
35
|
+
directives,
|
|
36
|
+
};
|
|
37
|
+
}
|
package/dist/cli/setup.js
CHANGED
|
@@ -14,7 +14,7 @@ import { fileURLToPath } from 'url';
|
|
|
14
14
|
import { getGlobalDir, loadCLIConfig, saveCLIConfig } from '../storage/repo-manager.js';
|
|
15
15
|
import { getGitRoot } from '../storage/git.js';
|
|
16
16
|
import { glob } from 'glob';
|
|
17
|
-
import {
|
|
17
|
+
import { resolveCliSpec } from '../config/cli-spec.js';
|
|
18
18
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
19
|
const __dirname = path.dirname(__filename);
|
|
20
20
|
const execFileAsync = promisify(execFile);
|
|
@@ -47,25 +47,24 @@ async function installLegacyCursorSkills(result) {
|
|
|
47
47
|
result.errors.push(`Cursor skills: ${err.message}`);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
const DEFAULT_MCP_PACKAGE_SPEC = resolveCliSpec().packageSpec;
|
|
51
50
|
/**
|
|
52
51
|
* The MCP server entry for all editors.
|
|
53
|
-
*
|
|
52
|
+
* Uses the locally installed gitnexus binary.
|
|
54
53
|
*/
|
|
55
|
-
function getMcpEntry(
|
|
54
|
+
function getMcpEntry() {
|
|
56
55
|
if (process.platform === 'win32') {
|
|
57
56
|
return {
|
|
58
57
|
command: 'cmd',
|
|
59
|
-
args: ['/c', '
|
|
58
|
+
args: ['/c', 'gitnexus', 'mcp'],
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
return {
|
|
63
|
-
command: '
|
|
64
|
-
args: ['
|
|
62
|
+
command: 'gitnexus',
|
|
63
|
+
args: ['mcp'],
|
|
65
64
|
};
|
|
66
65
|
}
|
|
67
|
-
function getOpenCodeMcpEntry(
|
|
68
|
-
const entry = getMcpEntry(
|
|
66
|
+
function getOpenCodeMcpEntry() {
|
|
67
|
+
const entry = getMcpEntry();
|
|
69
68
|
return {
|
|
70
69
|
type: 'local',
|
|
71
70
|
command: [entry.command, ...entry.args],
|
|
@@ -75,28 +74,28 @@ function getOpenCodeMcpEntry(mcpPackageSpec) {
|
|
|
75
74
|
* Merge gitnexus entry into an existing MCP config JSON object.
|
|
76
75
|
* Returns the updated config.
|
|
77
76
|
*/
|
|
78
|
-
function mergeMcpConfig(existing
|
|
77
|
+
function mergeMcpConfig(existing) {
|
|
79
78
|
if (!existing || typeof existing !== 'object') {
|
|
80
79
|
existing = {};
|
|
81
80
|
}
|
|
82
81
|
if (!existing.mcpServers || typeof existing.mcpServers !== 'object') {
|
|
83
82
|
existing.mcpServers = {};
|
|
84
83
|
}
|
|
85
|
-
existing.mcpServers.gitnexus = getMcpEntry(
|
|
84
|
+
existing.mcpServers.gitnexus = getMcpEntry();
|
|
86
85
|
return existing;
|
|
87
86
|
}
|
|
88
87
|
/**
|
|
89
88
|
* Merge gitnexus entry into an OpenCode config JSON object.
|
|
90
89
|
* Returns the updated config.
|
|
91
90
|
*/
|
|
92
|
-
function mergeOpenCodeConfig(existing
|
|
91
|
+
function mergeOpenCodeConfig(existing) {
|
|
93
92
|
if (!existing || typeof existing !== 'object') {
|
|
94
93
|
existing = {};
|
|
95
94
|
}
|
|
96
95
|
if (!existing.mcp || typeof existing.mcp !== 'object') {
|
|
97
96
|
existing.mcp = {};
|
|
98
97
|
}
|
|
99
|
-
existing.mcp.gitnexus = getOpenCodeMcpEntry(
|
|
98
|
+
existing.mcp.gitnexus = getOpenCodeMcpEntry();
|
|
100
99
|
return existing;
|
|
101
100
|
}
|
|
102
101
|
/**
|
|
@@ -148,16 +147,16 @@ async function fileExists(filePath) {
|
|
|
148
147
|
function toTomlString(value) {
|
|
149
148
|
return `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
|
|
150
149
|
}
|
|
151
|
-
function buildCodexMcpTable(
|
|
152
|
-
const entry = getMcpEntry(
|
|
150
|
+
function buildCodexMcpTable() {
|
|
151
|
+
const entry = getMcpEntry();
|
|
153
152
|
return [
|
|
154
153
|
'[mcp_servers.gitnexus]',
|
|
155
154
|
`command = ${toTomlString(entry.command)}`,
|
|
156
155
|
`args = [${entry.args.map(toTomlString).join(', ')}]`,
|
|
157
156
|
].join('\n');
|
|
158
157
|
}
|
|
159
|
-
function mergeCodexConfig(existingRaw
|
|
160
|
-
const table = buildCodexMcpTable(
|
|
158
|
+
function mergeCodexConfig(existingRaw) {
|
|
159
|
+
const table = buildCodexMcpTable();
|
|
161
160
|
const normalized = existingRaw.replace(/\r\n/g, '\n');
|
|
162
161
|
const tablePattern = /^\[mcp_servers\.gitnexus\][\s\S]*?(?=^\[[^\]]+\]|(?![\s\S]))/m;
|
|
163
162
|
if (tablePattern.test(normalized)) {
|
|
@@ -179,7 +178,7 @@ async function resolveOpenCodeConfigPath(opencodeDir) {
|
|
|
179
178
|
return preferredPath;
|
|
180
179
|
}
|
|
181
180
|
// ─── Editor-specific setup ─────────────────────────────────────────
|
|
182
|
-
async function setupCursor(result
|
|
181
|
+
async function setupCursor(result) {
|
|
183
182
|
const cursorDir = path.join(os.homedir(), '.cursor');
|
|
184
183
|
if (!(await dirExists(cursorDir))) {
|
|
185
184
|
result.skipped.push('Cursor (not installed)');
|
|
@@ -188,7 +187,7 @@ async function setupCursor(result, mcpPackageSpec) {
|
|
|
188
187
|
const mcpPath = path.join(cursorDir, 'mcp.json');
|
|
189
188
|
try {
|
|
190
189
|
const existing = await readJsonFile(mcpPath);
|
|
191
|
-
const updated = mergeMcpConfig(existing
|
|
190
|
+
const updated = mergeMcpConfig(existing);
|
|
192
191
|
await writeJsonFile(mcpPath, updated);
|
|
193
192
|
result.configured.push('Cursor');
|
|
194
193
|
}
|
|
@@ -196,7 +195,7 @@ async function setupCursor(result, mcpPackageSpec) {
|
|
|
196
195
|
result.errors.push(`Cursor: ${err.message}`);
|
|
197
196
|
}
|
|
198
197
|
}
|
|
199
|
-
async function setupClaudeCode(result
|
|
198
|
+
async function setupClaudeCode(result) {
|
|
200
199
|
const claudeDir = path.join(os.homedir(), '.claude');
|
|
201
200
|
const hasClaude = await dirExists(claudeDir);
|
|
202
201
|
if (!hasClaude) {
|
|
@@ -207,7 +206,7 @@ async function setupClaudeCode(result, mcpPackageSpec) {
|
|
|
207
206
|
console.log('');
|
|
208
207
|
console.log(' Claude Code detected. Run this command to add GitNexus MCP:');
|
|
209
208
|
console.log('');
|
|
210
|
-
console.log(` claude mcp add gitnexus --
|
|
209
|
+
console.log(` claude mcp add gitnexus -- gitnexus mcp`);
|
|
211
210
|
console.log('');
|
|
212
211
|
result.configured.push('Claude Code (MCP manual step printed)');
|
|
213
212
|
}
|
|
@@ -243,7 +242,7 @@ async function installProjectAgentSkills(repoRoot, result) {
|
|
|
243
242
|
* Install GitNexus hooks to ~/.claude/settings.json for Claude Code.
|
|
244
243
|
* Merges hook config without overwriting existing hooks.
|
|
245
244
|
*/
|
|
246
|
-
async function installClaudeCodeHooks(result
|
|
245
|
+
async function installClaudeCodeHooks(result) {
|
|
247
246
|
const claudeDir = path.join(os.homedir(), '.claude');
|
|
248
247
|
if (!(await dirExists(claudeDir)))
|
|
249
248
|
return;
|
|
@@ -295,7 +294,7 @@ async function installClaudeCodeHooks(result, mcpPackageSpec) {
|
|
|
295
294
|
result.errors.push(`Claude Code hooks: ${err.message}`);
|
|
296
295
|
}
|
|
297
296
|
}
|
|
298
|
-
async function setupOpenCode(result
|
|
297
|
+
async function setupOpenCode(result) {
|
|
299
298
|
const opencodeDir = path.join(os.homedir(), '.config', 'opencode');
|
|
300
299
|
if (!(await dirExists(opencodeDir))) {
|
|
301
300
|
result.skipped.push('OpenCode (not installed)');
|
|
@@ -304,7 +303,7 @@ async function setupOpenCode(result, mcpPackageSpec) {
|
|
|
304
303
|
const configPath = await resolveOpenCodeConfigPath(opencodeDir);
|
|
305
304
|
try {
|
|
306
305
|
const existing = await readJsonFile(configPath);
|
|
307
|
-
const config = mergeOpenCodeConfig(existing
|
|
306
|
+
const config = mergeOpenCodeConfig(existing);
|
|
308
307
|
await writeJsonFile(configPath, config);
|
|
309
308
|
result.configured.push(`OpenCode (${path.basename(configPath)})`);
|
|
310
309
|
}
|
|
@@ -312,8 +311,8 @@ async function setupOpenCode(result, mcpPackageSpec) {
|
|
|
312
311
|
result.errors.push(`OpenCode: ${err.message}`);
|
|
313
312
|
}
|
|
314
313
|
}
|
|
315
|
-
async function setupCodex(result
|
|
316
|
-
const entry = getMcpEntry(
|
|
314
|
+
async function setupCodex(result) {
|
|
315
|
+
const entry = getMcpEntry();
|
|
317
316
|
try {
|
|
318
317
|
await execFileAsync('codex', ['mcp', 'add', 'gitnexus', '--', entry.command, ...entry.args], { timeout: 15000 });
|
|
319
318
|
result.configured.push('Codex');
|
|
@@ -326,11 +325,11 @@ async function setupCodex(result, mcpPackageSpec) {
|
|
|
326
325
|
result.errors.push(`Codex: ${err.message}`);
|
|
327
326
|
}
|
|
328
327
|
}
|
|
329
|
-
async function setupProjectMcp(repoRoot, result
|
|
328
|
+
async function setupProjectMcp(repoRoot, result) {
|
|
330
329
|
const mcpPath = path.join(repoRoot, '.mcp.json');
|
|
331
330
|
try {
|
|
332
331
|
const existing = await readJsonFile(mcpPath);
|
|
333
|
-
const updated = mergeMcpConfig(existing
|
|
332
|
+
const updated = mergeMcpConfig(existing);
|
|
334
333
|
await writeJsonFile(mcpPath, updated);
|
|
335
334
|
result.configured.push(`Project MCP (${path.relative(repoRoot, mcpPath)})`);
|
|
336
335
|
}
|
|
@@ -338,7 +337,7 @@ async function setupProjectMcp(repoRoot, result, mcpPackageSpec) {
|
|
|
338
337
|
result.errors.push(`Project MCP: ${err.message}`);
|
|
339
338
|
}
|
|
340
339
|
}
|
|
341
|
-
async function setupProjectCodex(repoRoot, result
|
|
340
|
+
async function setupProjectCodex(repoRoot, result) {
|
|
342
341
|
const codexConfigPath = path.join(repoRoot, '.codex', 'config.toml');
|
|
343
342
|
try {
|
|
344
343
|
let existingRaw = '';
|
|
@@ -349,7 +348,7 @@ async function setupProjectCodex(repoRoot, result, mcpPackageSpec) {
|
|
|
349
348
|
if (err?.code !== 'ENOENT')
|
|
350
349
|
throw err;
|
|
351
350
|
}
|
|
352
|
-
const merged = mergeCodexConfig(existingRaw
|
|
351
|
+
const merged = mergeCodexConfig(existingRaw);
|
|
353
352
|
await fs.mkdir(path.dirname(codexConfigPath), { recursive: true });
|
|
354
353
|
await fs.writeFile(codexConfigPath, merged, 'utf-8');
|
|
355
354
|
result.configured.push(`Project Codex MCP (${path.relative(repoRoot, codexConfigPath)})`);
|
|
@@ -358,11 +357,11 @@ async function setupProjectCodex(repoRoot, result, mcpPackageSpec) {
|
|
|
358
357
|
result.errors.push(`Project Codex MCP: ${err.message}`);
|
|
359
358
|
}
|
|
360
359
|
}
|
|
361
|
-
async function setupProjectOpenCode(repoRoot, result
|
|
360
|
+
async function setupProjectOpenCode(repoRoot, result) {
|
|
362
361
|
const opencodePath = path.join(repoRoot, 'opencode.json');
|
|
363
362
|
try {
|
|
364
363
|
const existing = await readJsonFile(opencodePath);
|
|
365
|
-
const merged = mergeOpenCodeConfig(existing
|
|
364
|
+
const merged = mergeOpenCodeConfig(existing);
|
|
366
365
|
await writeJsonFile(opencodePath, merged);
|
|
367
366
|
result.configured.push(`Project OpenCode MCP (${path.relative(repoRoot, opencodePath)})`);
|
|
368
367
|
}
|
|
@@ -510,7 +509,7 @@ export const setupCommand = async (options = {}) => {
|
|
|
510
509
|
explicitVersion: options.cliVersion,
|
|
511
510
|
config: existingConfig,
|
|
512
511
|
});
|
|
513
|
-
const mcpPackageSpec = resolvedCliSpec.packageSpec
|
|
512
|
+
const mcpPackageSpec = resolvedCliSpec.packageSpec;
|
|
514
513
|
const result = {
|
|
515
514
|
configured: [],
|
|
516
515
|
skipped: [],
|
|
@@ -518,7 +517,7 @@ export const setupCommand = async (options = {}) => {
|
|
|
518
517
|
};
|
|
519
518
|
if (scope === 'global') {
|
|
520
519
|
if (legacyCursorMode) {
|
|
521
|
-
await setupCursor(result
|
|
520
|
+
await setupCursor(result);
|
|
522
521
|
await installLegacyCursorSkills(result);
|
|
523
522
|
await saveSetupConfig(scope, mcpPackageSpec, result);
|
|
524
523
|
agent = LEGACY_CURSOR_AGENT;
|
|
@@ -526,15 +525,15 @@ export const setupCommand = async (options = {}) => {
|
|
|
526
525
|
else {
|
|
527
526
|
// Configure only the selected agent MCP
|
|
528
527
|
if (agent === 'claude') {
|
|
529
|
-
await setupClaudeCode(result
|
|
528
|
+
await setupClaudeCode(result);
|
|
530
529
|
// Claude-only hooks should only be installed when Claude is selected.
|
|
531
|
-
await installClaudeCodeHooks(result
|
|
530
|
+
await installClaudeCodeHooks(result);
|
|
532
531
|
}
|
|
533
532
|
else if (agent === 'opencode') {
|
|
534
|
-
await setupOpenCode(result
|
|
533
|
+
await setupOpenCode(result);
|
|
535
534
|
}
|
|
536
535
|
else if (agent === 'codex') {
|
|
537
|
-
await setupCodex(result
|
|
536
|
+
await setupCodex(result);
|
|
538
537
|
}
|
|
539
538
|
// Install shared global skills once
|
|
540
539
|
await installGlobalAgentSkills(result);
|
|
@@ -549,13 +548,13 @@ export const setupCommand = async (options = {}) => {
|
|
|
549
548
|
return;
|
|
550
549
|
}
|
|
551
550
|
if (agent === 'claude') {
|
|
552
|
-
await setupProjectMcp(repoRoot, result
|
|
551
|
+
await setupProjectMcp(repoRoot, result);
|
|
553
552
|
}
|
|
554
553
|
else if (agent === 'codex') {
|
|
555
|
-
await setupProjectCodex(repoRoot, result
|
|
554
|
+
await setupProjectCodex(repoRoot, result);
|
|
556
555
|
}
|
|
557
556
|
else if (agent === 'opencode') {
|
|
558
|
-
await setupProjectOpenCode(repoRoot, result
|
|
557
|
+
await setupProjectOpenCode(repoRoot, result);
|
|
559
558
|
}
|
|
560
559
|
await installProjectAgentSkills(repoRoot, result);
|
|
561
560
|
await saveSetupConfig(scope, mcpPackageSpec, result);
|
package/dist/cli/setup.test.js
CHANGED
|
@@ -10,9 +10,6 @@ const execFileAsync = promisify(execFile);
|
|
|
10
10
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const packageRoot = path.resolve(here, '..', '..');
|
|
12
12
|
const cliPath = path.join(packageRoot, 'dist', 'cli', 'index.js');
|
|
13
|
-
const packageName = JSON.parse(await fs.readFile(path.join(packageRoot, 'package.json'), 'utf-8'));
|
|
14
|
-
const expectedMcpPackage = `${packageName.name || 'gitnexus'}@latest`;
|
|
15
|
-
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
16
13
|
async function runSetup(args, env, cwd = packageRoot) {
|
|
17
14
|
return execFileAsync(process.execPath, [cliPath, 'setup', ...args], { cwd, env });
|
|
18
15
|
}
|
|
@@ -30,8 +27,8 @@ test('setup without --agent uses legacy Cursor install path', async () => {
|
|
|
30
27
|
const configPath = path.join(fakeHome, '.gitnexus', 'config.json');
|
|
31
28
|
const cursorMcpRaw = await fs.readFile(cursorMcpPath, 'utf-8');
|
|
32
29
|
const cursorMcp = JSON.parse(cursorMcpRaw);
|
|
33
|
-
assert.equal(cursorMcp.mcpServers?.gitnexus?.command, '
|
|
34
|
-
assert.deepEqual(cursorMcp.mcpServers?.gitnexus?.args, ['
|
|
30
|
+
assert.equal(cursorMcp.mcpServers?.gitnexus?.command, 'gitnexus');
|
|
31
|
+
assert.deepEqual(cursorMcp.mcpServers?.gitnexus?.args, ['mcp']);
|
|
35
32
|
await fs.access(cursorSkillPath);
|
|
36
33
|
const configRaw = await fs.readFile(configPath, 'utf-8');
|
|
37
34
|
const config = JSON.parse(configRaw);
|
|
@@ -142,7 +139,7 @@ process.exit(0);
|
|
|
142
139
|
const raw = await fs.readFile(outputPath, 'utf-8');
|
|
143
140
|
const parsed = JSON.parse(raw);
|
|
144
141
|
assert.deepEqual(parsed.args.slice(0, 4), ['mcp', 'add', 'gitnexus', '--']);
|
|
145
|
-
assert.ok(parsed.args.includes(
|
|
142
|
+
assert.ok(parsed.args.includes('gitnexus'));
|
|
146
143
|
assert.ok(parsed.args.includes('mcp'));
|
|
147
144
|
}
|
|
148
145
|
finally {
|
|
@@ -164,7 +161,7 @@ test('setup configures OpenCode MCP in ~/.config/opencode/opencode.json', async
|
|
|
164
161
|
const opencodeRaw = await fs.readFile(opencodeConfigPath, 'utf-8');
|
|
165
162
|
const opencodeConfig = JSON.parse(opencodeRaw);
|
|
166
163
|
assert.equal(opencodeConfig.mcp?.gitnexus?.type, 'local');
|
|
167
|
-
assert.deepEqual(opencodeConfig.mcp?.gitnexus?.command, ['
|
|
164
|
+
assert.deepEqual(opencodeConfig.mcp?.gitnexus?.command, ['gitnexus', 'mcp']);
|
|
168
165
|
}
|
|
169
166
|
finally {
|
|
170
167
|
await fs.rm(fakeHome, { recursive: true, force: true });
|
|
@@ -186,7 +183,8 @@ test('setup --cli-version pins MCP package spec and persists it in config', asyn
|
|
|
186
183
|
const configPath = path.join(fakeHome, '.gitnexus', 'config.json');
|
|
187
184
|
const savedConfigRaw = await fs.readFile(configPath, 'utf-8');
|
|
188
185
|
const savedConfig = JSON.parse(savedConfigRaw);
|
|
189
|
-
assert.deepEqual(opencodeConfig.mcp?.gitnexus?.command, ['
|
|
186
|
+
assert.deepEqual(opencodeConfig.mcp?.gitnexus?.command, ['gitnexus', 'mcp']);
|
|
187
|
+
// Version is persisted to config, not MCP entry:
|
|
190
188
|
assert.equal(savedConfig.cliPackageSpec, '@veewo/gitnexus@1.4.7-rc');
|
|
191
189
|
assert.equal(savedConfig.cliVersion, '1.4.7-rc');
|
|
192
190
|
}
|
|
@@ -211,7 +209,7 @@ test('setup keeps using legacy ~/.config/opencode/config.json when it already ex
|
|
|
211
209
|
const legacyConfig = JSON.parse(legacyRaw);
|
|
212
210
|
assert.equal(legacyConfig.existing, true);
|
|
213
211
|
assert.equal(legacyConfig.mcp?.gitnexus?.type, 'local');
|
|
214
|
-
assert.deepEqual(legacyConfig.mcp?.gitnexus?.command, ['
|
|
212
|
+
assert.deepEqual(legacyConfig.mcp?.gitnexus?.command, ['gitnexus', 'mcp']);
|
|
215
213
|
await assert.rejects(fs.access(preferredConfigPath));
|
|
216
214
|
}
|
|
217
215
|
finally {
|
|
@@ -254,7 +252,8 @@ test('setup --scope project --agent claude writes only .mcp.json', async () => {
|
|
|
254
252
|
const opencodeConfigPath = path.join(fakeRepo, 'opencode.json');
|
|
255
253
|
const projectMcpRaw = await fs.readFile(projectMcpPath, 'utf-8');
|
|
256
254
|
const projectMcp = JSON.parse(projectMcpRaw);
|
|
257
|
-
assert.equal(projectMcp.mcpServers?.gitnexus?.command, '
|
|
255
|
+
assert.equal(projectMcp.mcpServers?.gitnexus?.command, 'gitnexus');
|
|
256
|
+
assert.deepEqual(projectMcp.mcpServers?.gitnexus?.args, ['mcp']);
|
|
258
257
|
await assert.rejects(fs.access(codexConfigPath));
|
|
259
258
|
await assert.rejects(fs.access(opencodeConfigPath));
|
|
260
259
|
}
|
|
@@ -278,7 +277,8 @@ test('setup --scope project --agent codex writes only .codex/config.toml', async
|
|
|
278
277
|
const opencodeConfigPath = path.join(fakeRepo, 'opencode.json');
|
|
279
278
|
const codexConfigRaw = await fs.readFile(codexConfigPath, 'utf-8');
|
|
280
279
|
assert.match(codexConfigRaw, /\[mcp_servers\.gitnexus\]/);
|
|
281
|
-
assert.match(codexConfigRaw, /command = "
|
|
280
|
+
assert.match(codexConfigRaw, /command = "gitnexus"/);
|
|
281
|
+
assert.match(codexConfigRaw, /args = \["mcp"\]/);
|
|
282
282
|
await assert.rejects(fs.access(projectMcpPath));
|
|
283
283
|
await assert.rejects(fs.access(opencodeConfigPath));
|
|
284
284
|
}
|
|
@@ -316,7 +316,7 @@ test('setup --scope project --agent codex replaces existing gitnexus table witho
|
|
|
316
316
|
const gitnexusTable = gitnexusTableMatch[0];
|
|
317
317
|
assert.equal((gitnexusTable.match(/^command\s*=/gm) || []).length, 1);
|
|
318
318
|
assert.equal((gitnexusTable.match(/^args\s*=/gm) || []).length, 1);
|
|
319
|
-
assert.match(gitnexusTable,
|
|
319
|
+
assert.match(gitnexusTable, /command = "gitnexus"/);
|
|
320
320
|
assert.doesNotMatch(gitnexusTable, /oldpkg@latest/);
|
|
321
321
|
assert.match(codexConfigRaw, /^\[profiles\.default\]$/m);
|
|
322
322
|
}
|
|
@@ -346,7 +346,7 @@ test('setup --scope project --agent codex is idempotent across repeated runs', a
|
|
|
346
346
|
const gitnexusTable = gitnexusTableMatch[0];
|
|
347
347
|
assert.equal((gitnexusTable.match(/^command\s*=/gm) || []).length, 1);
|
|
348
348
|
assert.equal((gitnexusTable.match(/^args\s*=/gm) || []).length, 1);
|
|
349
|
-
assert.match(gitnexusTable,
|
|
349
|
+
assert.match(gitnexusTable, /command = "gitnexus"/);
|
|
350
350
|
}
|
|
351
351
|
finally {
|
|
352
352
|
await fs.rm(fakeHome, { recursive: true, force: true });
|
|
@@ -374,7 +374,7 @@ test('setup --scope project --agent opencode writes only opencode.json', async (
|
|
|
374
374
|
const configRaw = await fs.readFile(configPath, 'utf-8');
|
|
375
375
|
const config = JSON.parse(configRaw);
|
|
376
376
|
assert.equal(opencodeConfig.mcp?.gitnexus?.type, 'local');
|
|
377
|
-
assert.deepEqual(opencodeConfig.mcp?.gitnexus?.command, ['
|
|
377
|
+
assert.deepEqual(opencodeConfig.mcp?.gitnexus?.command, ['gitnexus', 'mcp']);
|
|
378
378
|
await assert.rejects(fs.access(projectMcpPath));
|
|
379
379
|
await assert.rejects(fs.access(codexConfigPath));
|
|
380
380
|
await fs.access(localSkillPath);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface SyncManifestScopeOptions {
|
|
2
|
+
scopeManifest?: string;
|
|
3
|
+
scopePrefix?: string[] | string;
|
|
4
|
+
}
|
|
5
|
+
export type SyncManifestPolicy = 'ask' | 'update' | 'keep' | 'error';
|
|
6
|
+
export interface SyncManifestDiffEntry {
|
|
7
|
+
directive: 'extensions' | 'repoAlias' | 'embeddings';
|
|
8
|
+
manifestValue?: string;
|
|
9
|
+
cliValue: string;
|
|
10
|
+
}
|
|
11
|
+
export interface EnforceSyncManifestConsistencyInput {
|
|
12
|
+
manifestPath?: string;
|
|
13
|
+
extensions?: string;
|
|
14
|
+
repoAlias?: string;
|
|
15
|
+
embeddings?: boolean;
|
|
16
|
+
policy?: SyncManifestPolicy;
|
|
17
|
+
stdinIsTTY?: boolean;
|
|
18
|
+
prompt?: (message: string) => Promise<'update' | 'keep'>;
|
|
19
|
+
}
|
|
20
|
+
export interface EnforceSyncManifestConsistencyResult {
|
|
21
|
+
decision: 'none' | 'update' | 'keep';
|
|
22
|
+
diff: SyncManifestDiffEntry[];
|
|
23
|
+
}
|
|
24
|
+
export declare function resolveDefaultSyncManifestPath(repoPath: string): string;
|
|
25
|
+
export declare function shouldAutoUseSyncManifest(options?: SyncManifestScopeOptions): boolean;
|
|
26
|
+
export declare function resolveScopeManifestForAnalyze(repoPath: string, options?: SyncManifestScopeOptions, pathExists?: (candidatePath: string) => Promise<boolean>): Promise<string | undefined>;
|
|
27
|
+
export declare function enforceSyncManifestConsistency(input: EnforceSyncManifestConsistencyInput): Promise<EnforceSyncManifestConsistencyResult>;
|