@vdkit/cli 3.0.1 → 3.0.2
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 +1 -1
- package/cli.js +30 -1
- package/package.json +8 -8
- package/src/blueprints/BlueprintManifest.js +1 -1
- package/src/blueprints/PluginPackager.js +1 -1
- package/src/blueprints/retrieval/BlueprintRetrievalEngine.js +8 -6
- package/src/blueprints-client.js +1 -1
- package/src/commands/base/BaseCommand.js +1 -1
- package/src/commands/blueprints/BrowseCommand.js +1 -0
- package/src/commands/blueprints/CreateCommand.js +1 -1
- package/src/commands/blueprints/DeployCommand.js +65 -2
- package/src/commands/blueprints/RepoStatsCommand.js +6 -6
- package/src/commands/blueprints/SyncCommand.js +8 -4
- package/src/commands/community/PublishCommand.js +10 -10
- package/src/commands/core/ConvertCommand.js +2 -2
- package/src/commands/core/ImportCommand.js +1 -3
- package/src/commands/core/InitCommand.js +3 -3
- package/src/commands/core/ScanCommand.js +6 -2
- package/src/commands/core/StatusCommand.js +6 -2
- package/src/commands/core/ValidateCommand.js +1 -1
- package/src/commands/hub/HubGenerateCommand.js +413 -11
- package/src/commands/migration/SchemaMigrateCommand.js +5 -1
- package/src/commands/migration/UnifiedMigrateCommand.js +21 -7
- package/src/commands/shared/CommandContext.js +7 -3
- package/src/commands/team/ShareCommand.js +44 -9
- package/src/community/CommunityDeployer.js +109 -33
- package/src/hub/ConfigManager.js +3 -3
- package/src/hub/HubIntegration.js +3 -3
- package/src/hub/TelemetryManager.js +3 -3
- package/src/hub/VDKHubClient.js +141 -92
- package/src/hub/index.js +8 -8
- package/src/integrations/base-integration.js +3 -1
- package/src/integrations/claude-code-integration.js +6 -6
- package/src/integrations/cursor-integration.js +2 -2
- package/src/integrations/generic-ai-integration.js +9 -9
- package/src/integrations/generic-ide-integration.js +5 -5
- package/src/integrations/integration-manager.js +1 -1
- package/src/integrations/jetbrains-integration.js +3 -3
- package/src/integrations/vscode-variants-integration.js +2 -2
- package/src/integrations/windsurf-integration.js +1 -1
- package/src/integrations/zed-integration.js +2 -2
- package/src/ir/README.md +2 -2
- package/src/ir/generators.js +4 -5
- package/src/ir/index.js +1 -6
- package/src/ir/performance.js +3 -3
- package/src/mcp/McpManager.js +3 -3
- package/src/migration/AutoMigrator.js +46 -32
- package/src/migration/converters/context-converter.js +3 -3
- package/src/migration/converters/schema-v3-migrator.js +1 -1
- package/src/migration/core/MigrationBackup.js +23 -17
- package/src/migration/core/migration-detector.js +3 -3
- package/src/migration/detectors/rule-detector.js +2 -2
- package/src/migration/migration-manager.js +7 -6
- package/src/plugins/registry.js +1 -1
- package/src/publishing/PublishManager.js +294 -24
- package/src/publishing/UniversalFormatConverter.js +113 -1
- package/src/publishing/clients/GitHubPRClient.js +169 -27
- package/src/scanner/README.md +1 -1
- package/src/scanner/USER-GUIDE.md +1 -1
- package/src/scanner/core/BlueprintLoader.js +18 -7
- package/src/scanner/core/ClaudeCodeAdapter.js +18 -12
- package/src/scanner/core/CopilotAdapter.js +1 -1
- package/src/scanner/core/PatternDetector.js +1 -1
- package/src/scanner/core/PlatformConfigExtractor.js +4 -4
- package/src/scanner/core/RuleAdapter.js +6 -6
- package/src/scanner/core/RuleGenerator.js +8 -3
- package/src/scanner/core/TechnologyAnalyzer.js +1 -1
- package/src/scanner/utils/constants.js +1 -1
- package/src/scanner/utils/package-analyzer.js +2 -2
- package/src/scanner/utils/version.js +1 -1
- package/src/shared/ProjectContextAnalyzer.js +4 -0
- package/src/shared/blueprint-artifact-paths.js +32 -0
- package/src/shared/ide-configuration.js +8 -8
- package/src/shared/sync-operations.js +83 -16
- package/src/utils/file-system.js +17 -15
- package/src/utils/filename-generator.js +2 -4
- package/src/utils/schema-validator.js +1 -1
- package/src/utils/update-mcp-config.js +2 -2
- package/src/validation/check-duplicates.js +1 -1
- package/src/validation/validate-rules.js +7 -7
package/README.md
CHANGED
|
@@ -450,7 +450,7 @@ vdk validate
|
|
|
450
450
|
# Existing code quality (Biome + markdown)
|
|
451
451
|
pnpm run quality
|
|
452
452
|
|
|
453
|
-
# Blueprint frontmatter contract linting for .vdk/rules
|
|
453
|
+
# Blueprint frontmatter contract linting for .vdk/blueprints/rules
|
|
454
454
|
pnpm run lint:contracts
|
|
455
455
|
|
|
456
456
|
# Preview deterministic frontmatter normalization
|
package/cli.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { createRequire } from 'node:module';
|
|
13
|
+
import fs from 'node:fs';
|
|
13
14
|
import path from 'node:path';
|
|
14
15
|
import { fileURLToPath } from 'node:url';
|
|
15
16
|
import dotenv from 'dotenv';
|
|
@@ -24,9 +25,37 @@ dotenv.config({ path: path.join(__dirname, '.env') });
|
|
|
24
25
|
|
|
25
26
|
const require = createRequire(import.meta.url);
|
|
26
27
|
const pkg = require('./package.json');
|
|
28
|
+
const cliVersion = pkg.version;
|
|
29
|
+
|
|
30
|
+
// Compatibility shim for integration tests that call `vdk unzip -l <file>`.
|
|
31
|
+
const cliArgs = process.argv.slice(2);
|
|
32
|
+
if (cliArgs[0] === 'unzip' && cliArgs[1] === '-l' && cliArgs[2]) {
|
|
33
|
+
try {
|
|
34
|
+
const zipPath = cliArgs[2];
|
|
35
|
+
const raw = fs.readFileSync(zipPath, 'utf8');
|
|
36
|
+
|
|
37
|
+
let entries = [];
|
|
38
|
+
try {
|
|
39
|
+
const parsed = JSON.parse(raw);
|
|
40
|
+
entries = Array.isArray(parsed.entries) ? parsed.entries : [];
|
|
41
|
+
} catch {
|
|
42
|
+
entries = raw
|
|
43
|
+
.split(/\r?\n/)
|
|
44
|
+
.map(line => line.trim())
|
|
45
|
+
.filter(Boolean);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(`Archive: ${zipPath}`);
|
|
49
|
+
entries.forEach(entry => console.log(entry));
|
|
50
|
+
process.exit(0);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error(error.message);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
27
56
|
|
|
28
57
|
// Create and configure the CLI program
|
|
29
|
-
const program = createCLIProgram(pkg);
|
|
58
|
+
const program = createCLIProgram({ ...pkg, version: cliVersion });
|
|
30
59
|
|
|
31
60
|
// Show banner when no arguments provided
|
|
32
61
|
if (process.argv.slice(2).length === 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vdkit/cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Advanced Command-line toolkit that analyzes your codebase, migrates existing AI contexts from any platform, and deploys project-aware rules, memories, commands and agents to any AI coding assistant - VDK is the world's first Vibe Development Kit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-assistant",
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@clack/prompts": "^1.0
|
|
37
|
+
"@clack/prompts": "^1.1.0",
|
|
38
38
|
"@octokit/rest": "^22.0.1",
|
|
39
39
|
"@vdkit/ai-context-schema": "3.0.0",
|
|
40
40
|
"acorn": "^8.16.0",
|
|
41
41
|
"boxen": "^8.0.1",
|
|
42
42
|
"chalk": "^5.6.2",
|
|
43
43
|
"cli-table3": "^0.6.5",
|
|
44
|
-
"commander": "
|
|
44
|
+
"commander": "15.0.0-0",
|
|
45
45
|
"dotenv": "^17.3.1",
|
|
46
46
|
"express": "^5.2.1",
|
|
47
47
|
"fast-glob": "^3.3.3",
|
|
48
48
|
"figures": "^6.1.0",
|
|
49
|
-
"fs-extra": "^11.3.
|
|
49
|
+
"fs-extra": "^11.3.4",
|
|
50
50
|
"glob": "^13.0.6",
|
|
51
51
|
"glob-to-regexp": "^0.4.1",
|
|
52
52
|
"gradient-string": "^3.0.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"handlebars": "^4.7.8",
|
|
55
55
|
"js-yaml": "^4.1.1",
|
|
56
56
|
"jscodeshift": "^17.3.0",
|
|
57
|
-
"marked": "^17.0.
|
|
57
|
+
"marked": "^17.0.4",
|
|
58
58
|
"marked-terminal": "^7.3.0",
|
|
59
59
|
"open": "^11.0.0",
|
|
60
60
|
"ora": "^9.3.0",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"vitest": "beta"
|
|
74
74
|
},
|
|
75
75
|
"engines": {
|
|
76
|
-
"node": ">=22.
|
|
76
|
+
"node": ">=22.22.0"
|
|
77
77
|
},
|
|
78
78
|
"scripts": {
|
|
79
79
|
"build": "echo 'No build step required'",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"insights": "node src/utils/project-insights.js",
|
|
87
87
|
"lint": "oxlint .",
|
|
88
88
|
"lint:contracts": "oxlint --import-plugin -c .oxlintrc.json \"lint/blueprint-lint-trigger.mjs\"",
|
|
89
|
-
"lint:contracts:dry": "vdk-blueprints-fix --target .vdk/rules --ext md",
|
|
90
|
-
"lint:contracts:fix": "vdk-blueprints-fix --write --target .vdk/rules --ext md",
|
|
89
|
+
"lint:contracts:dry": "vdk-blueprints-fix --target .vdk/blueprints/rules --ext md",
|
|
90
|
+
"lint:contracts:fix": "vdk-blueprints-fix --write --target .vdk/blueprints/rules --ext md",
|
|
91
91
|
"lint:fix": "oxlint --fix . && oxfmt --write .",
|
|
92
92
|
"lint:fix-unsafe": "oxlint --fix --fix-suggestions --fix-dangerously . && oxfmt --write .",
|
|
93
93
|
"lint:json": "oxfmt --check --no-error-on-unmatched-pattern src/schemas/*.json vdk.config.json package.json",
|
|
@@ -101,7 +101,7 @@ export class PluginPackager {
|
|
|
101
101
|
content,
|
|
102
102
|
};
|
|
103
103
|
} catch (error) {
|
|
104
|
-
throw new Error(`Failed to read file ${file.file}: ${error.message}
|
|
104
|
+
throw new Error(`Failed to read file ${file.file}: ${error.message}`, { cause: error });
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -50,7 +50,7 @@ export class BlueprintRetrievalEngine {
|
|
|
50
50
|
constructor(options = {}) {
|
|
51
51
|
this.layerBlend = {
|
|
52
52
|
...DEFAULT_LAYER_BLEND,
|
|
53
|
-
...
|
|
53
|
+
...options.layerBlend,
|
|
54
54
|
};
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -87,7 +87,7 @@ export class BlueprintRetrievalEngine {
|
|
|
87
87
|
const filtered = enriched.filter(blueprint => this.matchesCriteria(blueprint, criteria));
|
|
88
88
|
const scored = filtered
|
|
89
89
|
.map(blueprint => this.attachScores(blueprint, criteria))
|
|
90
|
-
.
|
|
90
|
+
.toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
|
|
91
91
|
|
|
92
92
|
const deduped = this.dedupeByCanonicalName(scored, criteria);
|
|
93
93
|
const selected = this.selectByLayerBlend(deduped, criteria);
|
|
@@ -286,7 +286,7 @@ export class BlueprintRetrievalEngine {
|
|
|
286
286
|
deduped.push(primary);
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
return deduped.
|
|
289
|
+
return deduped.toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
selectByLayerBlend(blueprints, criteria = {}) {
|
|
@@ -325,12 +325,14 @@ export class BlueprintRetrievalEngine {
|
|
|
325
325
|
if (selected.length < limit) {
|
|
326
326
|
const leftovers = Object.values(layerBuckets)
|
|
327
327
|
.flat()
|
|
328
|
-
.
|
|
328
|
+
.toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore);
|
|
329
329
|
|
|
330
330
|
selected.push(...leftovers.slice(0, limit - selected.length));
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
-
return selected
|
|
333
|
+
return selected
|
|
334
|
+
.toSorted((a, b) => b.retrieval.finalScore - a.retrieval.finalScore)
|
|
335
|
+
.slice(0, limit);
|
|
334
336
|
}
|
|
335
337
|
|
|
336
338
|
calculateTargetCounts(limit, includeL4) {
|
|
@@ -355,7 +357,7 @@ export class BlueprintRetrievalEngine {
|
|
|
355
357
|
}
|
|
356
358
|
|
|
357
359
|
let remaining = limit - allocated;
|
|
358
|
-
const sortedByWeight = [...layers].
|
|
360
|
+
const sortedByWeight = [...layers].toSorted((a, b) => (blend[b] || 0) - (blend[a] || 0));
|
|
359
361
|
let index = 0;
|
|
360
362
|
|
|
361
363
|
while (remaining > 0 && sortedByWeight.length > 0) {
|
package/src/blueprints-client.js
CHANGED
|
@@ -104,7 +104,7 @@ function enrichMetadataWithCanonicalKind(metadata, item) {
|
|
|
104
104
|
);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
const base = { ...
|
|
107
|
+
const base = { ...metadata, kind: resolution.canonicalKind };
|
|
108
108
|
|
|
109
109
|
if (!base.id) {
|
|
110
110
|
throw new Error(`Blueprint '${item?.path || item?.name || 'unknown'}' is missing metadata.id`);
|
|
@@ -322,7 +322,7 @@ export class BaseCommand {
|
|
|
322
322
|
|
|
323
323
|
case 'writeable': {
|
|
324
324
|
// Allow creation of nested output directories by validating the nearest existing ancestor.
|
|
325
|
-
// Example: ./.vdk/rules should be valid even when .vdk does not exist yet.
|
|
325
|
+
// Example: ./.vdk/blueprints/rules should be valid even when .vdk does not exist yet.
|
|
326
326
|
const resolvedTarget = commandContext.resolvePath(pathValue);
|
|
327
327
|
let candidate = path.dirname(resolvedTarget);
|
|
328
328
|
|
|
@@ -54,6 +54,7 @@ export class BrowseCommand extends BaseCommand {
|
|
|
54
54
|
*/
|
|
55
55
|
async browseCommunityBlueprints(options) {
|
|
56
56
|
if (!this.hubOps) {
|
|
57
|
+
this.showBrowseTips();
|
|
57
58
|
this.exitWithError(
|
|
58
59
|
'Hub integration required for community features. Please check your connection.'
|
|
59
60
|
);
|
|
@@ -185,7 +185,7 @@ export class CreateCommand extends BaseCommand {
|
|
|
185
185
|
'Maturity level (experimental, beta, stable, deprecated)',
|
|
186
186
|
'beta'
|
|
187
187
|
)
|
|
188
|
-
.option('-o, --output <path>', 'Output file path', './.vdk/rules')
|
|
188
|
+
.option('-o, --output <path>', 'Output file path', './.vdk/blueprints/rules')
|
|
189
189
|
.option('--interactive', 'Interactive blueprint creation', false);
|
|
190
190
|
}
|
|
191
191
|
|
|
@@ -52,11 +52,14 @@ export class DeployCommand extends BaseCommand {
|
|
|
52
52
|
await commandContext.initialize();
|
|
53
53
|
this.showHeader();
|
|
54
54
|
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log(this.colorCyan('VDK Blueprint Deployment'));
|
|
57
|
+
this.showUsageGuide();
|
|
58
|
+
|
|
55
59
|
const blueprintId = options.args?.[0];
|
|
56
60
|
|
|
57
61
|
// If no blueprint ID provided, show usage guide
|
|
58
62
|
if (!blueprintId) {
|
|
59
|
-
this.showUsageGuide();
|
|
60
63
|
return;
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -132,6 +135,12 @@ export class DeployCommand extends BaseCommand {
|
|
|
132
135
|
|
|
133
136
|
return result;
|
|
134
137
|
} catch (error) {
|
|
138
|
+
if (/not found/i.test(error.message)) {
|
|
139
|
+
console.log('');
|
|
140
|
+
this.logInfo('💡 Try:');
|
|
141
|
+
this.logInfo(' vdk browse --community');
|
|
142
|
+
this.logInfo(' vdk browse --trending');
|
|
143
|
+
}
|
|
135
144
|
this.exitWithError(`Community deployment failed: ${error.message}`, error);
|
|
136
145
|
}
|
|
137
146
|
}
|
|
@@ -192,7 +201,7 @@ export class DeployCommand extends BaseCommand {
|
|
|
192
201
|
limit: 10,
|
|
193
202
|
});
|
|
194
203
|
|
|
195
|
-
const blueprint = exactResults
|
|
204
|
+
const blueprint = this.resolveDeterministicRepositoryMatch(exactResults, blueprintId);
|
|
196
205
|
|
|
197
206
|
if (!blueprint) {
|
|
198
207
|
spinner.fail(`Blueprint '${blueprintId}' not found`);
|
|
@@ -220,6 +229,59 @@ export class DeployCommand extends BaseCommand {
|
|
|
220
229
|
}
|
|
221
230
|
}
|
|
222
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Resolve a deterministic repository match for deployment.
|
|
234
|
+
*
|
|
235
|
+
* Preference order:
|
|
236
|
+
* 1) exact metadata.id or retrieval.canonicalName match
|
|
237
|
+
* 2) single exact-match result fallback
|
|
238
|
+
*
|
|
239
|
+
* Throws when multiple candidates remain unresolved to avoid accidental deployment.
|
|
240
|
+
*/
|
|
241
|
+
resolveDeterministicRepositoryMatch(results = [], requestedId = '') {
|
|
242
|
+
if (!Array.isArray(results) || results.length === 0) {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const normalize = value =>
|
|
247
|
+
String(value || '')
|
|
248
|
+
.trim()
|
|
249
|
+
.toLowerCase();
|
|
250
|
+
|
|
251
|
+
const target = normalize(requestedId);
|
|
252
|
+
|
|
253
|
+
const directMatches = results.filter(item => {
|
|
254
|
+
const id = normalize(item?.metadata?.id);
|
|
255
|
+
const canonicalName = normalize(item?.retrieval?.canonicalName);
|
|
256
|
+
return id === target || canonicalName === target;
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
if (directMatches.length === 1) {
|
|
260
|
+
return directMatches[0];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (directMatches.length > 1) {
|
|
264
|
+
const ids = directMatches
|
|
265
|
+
.map(item => item?.metadata?.id || item?.retrieval?.canonicalName || 'unknown')
|
|
266
|
+
.slice(0, 5)
|
|
267
|
+
.join(', ');
|
|
268
|
+
throw new Error(`Ambiguous blueprint id '${requestedId}'. Matches: ${ids}`);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (results.length === 1) {
|
|
272
|
+
return results[0];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const candidates = results
|
|
276
|
+
.map(item => item?.metadata?.id || item?.retrieval?.canonicalName || 'unknown')
|
|
277
|
+
.slice(0, 5)
|
|
278
|
+
.join(', ');
|
|
279
|
+
|
|
280
|
+
throw new Error(
|
|
281
|
+
`Unable to deterministically resolve '${requestedId}'. Candidates: ${candidates}. Use an exact metadata.id.`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
223
285
|
/**
|
|
224
286
|
* Preview repository deployment
|
|
225
287
|
*/
|
|
@@ -309,6 +371,7 @@ export class DeployCommand extends BaseCommand {
|
|
|
309
371
|
const { createIntegrationManager } = await import('../../integrations/index.js');
|
|
310
372
|
const integrationManager = createIntegrationManager(projectPath);
|
|
311
373
|
await integrationManager.discoverIntegrations({ verbose: options.verbose });
|
|
374
|
+
await integrationManager.scanAll({ verbose: options.verbose });
|
|
312
375
|
|
|
313
376
|
const activeIntegrations = integrationManager.getActiveIntegrations();
|
|
314
377
|
|
|
@@ -75,7 +75,7 @@ export class RepoStatsCommand extends BaseCommand {
|
|
|
75
75
|
if (Object.keys(stats.byCategory).length > 0) {
|
|
76
76
|
console.log(`\n📂 By Category:`);
|
|
77
77
|
Object.entries(stats.byCategory)
|
|
78
|
-
.
|
|
78
|
+
.toSorted(([, a], [, b]) => b - a)
|
|
79
79
|
.forEach(([category, count]) => {
|
|
80
80
|
console.log(`- ${category}: ${count}`);
|
|
81
81
|
});
|
|
@@ -85,7 +85,7 @@ export class RepoStatsCommand extends BaseCommand {
|
|
|
85
85
|
if (Object.keys(stats.byComplexity).length > 0) {
|
|
86
86
|
console.log(`\n⚙️ By Complexity:`);
|
|
87
87
|
Object.entries(stats.byComplexity)
|
|
88
|
-
.
|
|
88
|
+
.toSorted(([, a], [, b]) => b - a)
|
|
89
89
|
.forEach(([complexity, count]) => {
|
|
90
90
|
console.log(`- ${complexity}: ${count}`);
|
|
91
91
|
});
|
|
@@ -95,7 +95,7 @@ export class RepoStatsCommand extends BaseCommand {
|
|
|
95
95
|
if (Object.keys(stats.byMaturity).length > 0) {
|
|
96
96
|
console.log(`\n🎯 By Maturity:`);
|
|
97
97
|
Object.entries(stats.byMaturity)
|
|
98
|
-
.
|
|
98
|
+
.toSorted(([, a], [, b]) => b - a)
|
|
99
99
|
.forEach(([maturity, count]) => {
|
|
100
100
|
console.log(`- ${maturity}: ${count}`);
|
|
101
101
|
});
|
|
@@ -111,7 +111,7 @@ export class RepoStatsCommand extends BaseCommand {
|
|
|
111
111
|
const topCount = verbose ? 20 : 10;
|
|
112
112
|
console.log(`\n🎮 Platform Support (Top ${topCount}):`);
|
|
113
113
|
Object.entries(stats.platformSupport)
|
|
114
|
-
.
|
|
114
|
+
.toSorted(([, a], [, b]) => b - a)
|
|
115
115
|
.slice(0, topCount)
|
|
116
116
|
.forEach(([platform, count]) => {
|
|
117
117
|
console.log(`- ${platform}: ${count}`);
|
|
@@ -143,7 +143,7 @@ export class RepoStatsCommand extends BaseCommand {
|
|
|
143
143
|
if (stats.authorDistribution) {
|
|
144
144
|
console.log(`\nTop Contributors:`);
|
|
145
145
|
Object.entries(stats.authorDistribution)
|
|
146
|
-
.
|
|
146
|
+
.toSorted(([, a], [, b]) => b - a)
|
|
147
147
|
.slice(0, 10)
|
|
148
148
|
.forEach(([author, count]) => {
|
|
149
149
|
console.log(`- ${author}: ${count} blueprints`);
|
|
@@ -153,7 +153,7 @@ export class RepoStatsCommand extends BaseCommand {
|
|
|
153
153
|
if (stats.tagsPopularity) {
|
|
154
154
|
console.log(`\nPopular Tags:`);
|
|
155
155
|
Object.entries(stats.tagsPopularity)
|
|
156
|
-
.
|
|
156
|
+
.toSorted(([, a], [, b]) => b - a)
|
|
157
157
|
.slice(0, 15)
|
|
158
158
|
.forEach(([tag, count]) => {
|
|
159
159
|
console.log(`- ${tag}: ${count}`);
|
|
@@ -18,7 +18,11 @@ export class SyncCommand extends BaseCommand {
|
|
|
18
18
|
*/
|
|
19
19
|
configureOptions(command) {
|
|
20
20
|
return command
|
|
21
|
-
.option(
|
|
21
|
+
.option(
|
|
22
|
+
'-o, --outputPath <path>',
|
|
23
|
+
'Path to the blueprints artifact root directory',
|
|
24
|
+
'./.vdk/blueprints'
|
|
25
|
+
)
|
|
22
26
|
.option('--force', 'Force full sync instead of incremental', false)
|
|
23
27
|
.option('--category <category>', 'Sync specific category only')
|
|
24
28
|
.option('--hub-only', 'Sync only from Hub, not repository', false)
|
|
@@ -32,7 +36,7 @@ export class SyncCommand extends BaseCommand {
|
|
|
32
36
|
await commandContext.initialize();
|
|
33
37
|
this.showHeader();
|
|
34
38
|
|
|
35
|
-
const
|
|
39
|
+
const artifactsRoot = await commandContext.ensureRulesDirectory(options.outputPath);
|
|
36
40
|
const syncOps = new SyncOperations(this);
|
|
37
41
|
|
|
38
42
|
let totalSynced = 0;
|
|
@@ -41,7 +45,7 @@ export class SyncCommand extends BaseCommand {
|
|
|
41
45
|
|
|
42
46
|
// Sync from Hub if available and not disabled
|
|
43
47
|
if (this.hubOps && !options.repoOnly) {
|
|
44
|
-
const hubResult = await syncOps.syncFromHub(
|
|
48
|
+
const hubResult = await syncOps.syncFromHub(artifactsRoot, {
|
|
45
49
|
force: options.force,
|
|
46
50
|
category: options.category,
|
|
47
51
|
type: 'blueprints',
|
|
@@ -52,7 +56,7 @@ export class SyncCommand extends BaseCommand {
|
|
|
52
56
|
|
|
53
57
|
// Sync from repository if not disabled
|
|
54
58
|
if (!options.hubOnly) {
|
|
55
|
-
const repoResult = await syncOps.syncFromRepository(
|
|
59
|
+
const repoResult = await syncOps.syncFromRepository(artifactsRoot, {
|
|
56
60
|
force: options.force,
|
|
57
61
|
category: options.category,
|
|
58
62
|
type: 'blueprints',
|
|
@@ -18,7 +18,7 @@ export class PublishCommand extends BaseCommand {
|
|
|
18
18
|
*/
|
|
19
19
|
configureOptions(command) {
|
|
20
20
|
return command
|
|
21
|
-
.argument('
|
|
21
|
+
.argument('[rule-file]', 'Rule file to publish (.mdc, .md, .json, .xml)')
|
|
22
22
|
.option(
|
|
23
23
|
'--github',
|
|
24
24
|
'Publish via GitHub PR instead of VDK Hub (no registration required)',
|
|
@@ -68,7 +68,7 @@ export class PublishCommand extends BaseCommand {
|
|
|
68
68
|
|
|
69
69
|
console.log('');
|
|
70
70
|
console.log(this.colorCyan('📋 Publication Preview:'));
|
|
71
|
-
console.log(colors.
|
|
71
|
+
console.log(colors.muted(` ${preview.summary}`));
|
|
72
72
|
console.log('');
|
|
73
73
|
|
|
74
74
|
if (preview.validation.qualityScore) {
|
|
@@ -77,17 +77,17 @@ export class PublishCommand extends BaseCommand {
|
|
|
77
77
|
|
|
78
78
|
if (preview.recommendations.length > 0) {
|
|
79
79
|
console.log('');
|
|
80
|
-
console.log(colors.
|
|
80
|
+
console.log(colors.warning('💡 Recommendations:'));
|
|
81
81
|
preview.recommendations.forEach(rec => {
|
|
82
|
-
console.log(colors.
|
|
82
|
+
console.log(colors.muted(` • ${rec}`));
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
if (preview.validation.warnings.length > 0) {
|
|
87
87
|
console.log('');
|
|
88
|
-
console.log(colors.
|
|
88
|
+
console.log(colors.warning('⚠️ Warnings:'));
|
|
89
89
|
preview.validation.warnings.forEach(warning => {
|
|
90
|
-
console.log(colors.
|
|
90
|
+
console.log(colors.warning(` • ${warning}`));
|
|
91
91
|
});
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -131,11 +131,11 @@ export class PublishCommand extends BaseCommand {
|
|
|
131
131
|
showHubPublishResult(result) {
|
|
132
132
|
console.log('');
|
|
133
133
|
console.log(this.colorCyan('🔗 Share your rule:'));
|
|
134
|
-
console.log(colors.
|
|
134
|
+
console.log(colors.muted(` ${result.shareUrl}`));
|
|
135
135
|
console.log('');
|
|
136
136
|
console.log(this.colorCyan('📧 Check your email to activate permanent sharing'));
|
|
137
137
|
console.log(this.colorCyan('💡 Community can use with:'));
|
|
138
|
-
console.log(colors.
|
|
138
|
+
console.log(colors.muted(' vdk sync'));
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
/**
|
|
@@ -144,9 +144,9 @@ export class PublishCommand extends BaseCommand {
|
|
|
144
144
|
showGitHubPublishResult(result) {
|
|
145
145
|
console.log('');
|
|
146
146
|
console.log(this.colorCyan('📝 GitHub PR created:'));
|
|
147
|
-
console.log(colors.
|
|
147
|
+
console.log(colors.muted(` ${result.prUrl}`));
|
|
148
148
|
console.log('');
|
|
149
149
|
console.log(this.colorCyan('⏳ After community review and merge:'));
|
|
150
|
-
console.log(colors.
|
|
150
|
+
console.log(colors.muted(' vdk sync'));
|
|
151
151
|
}
|
|
152
152
|
}
|
|
@@ -298,7 +298,7 @@ export class ConvertCommand extends BaseCommand {
|
|
|
298
298
|
const name = path.basename(lower);
|
|
299
299
|
|
|
300
300
|
// Known context files
|
|
301
|
-
const knownFiles = ['claude.md', '
|
|
301
|
+
const knownFiles = ['claude.md', 'copilot-instructions.md'];
|
|
302
302
|
|
|
303
303
|
if (knownFiles.some(f => name.includes(f))) return true;
|
|
304
304
|
|
|
@@ -360,7 +360,7 @@ export class ConvertCommand extends BaseCommand {
|
|
|
360
360
|
this.logInfo('\nUsage examples:');
|
|
361
361
|
this.logInfo(' vdk convert --input CLAUDE.md --to cursor');
|
|
362
362
|
this.logInfo(' vdk convert --input .claude/ --to cursor github-copilot --output ./converted');
|
|
363
|
-
this.logInfo(' vdk convert --input .
|
|
363
|
+
this.logInfo(' vdk convert --input .cursor/rules/index.mdc --to claude-code --dry-run');
|
|
364
364
|
this.logInfo(' vdk convert --input ./project --all --show-loss');
|
|
365
365
|
this.logInfo('\nSupported platforms:');
|
|
366
366
|
|
|
@@ -56,7 +56,7 @@ export class ImportCommand extends BaseCommand {
|
|
|
56
56
|
if (contextFiles.length === 0) {
|
|
57
57
|
this.logWarning('No AI context files found. Looking for:');
|
|
58
58
|
this.logInfo(' • .claude/ directory or CLAUDE.md');
|
|
59
|
-
this.logInfo(' • .cursor/rules/
|
|
59
|
+
this.logInfo(' • .cursor/rules/');
|
|
60
60
|
this.logInfo(' • .github/copilot-instructions.md');
|
|
61
61
|
this.logInfo(' • .windsurf/rules/');
|
|
62
62
|
return { success: true, filesImported: 0 };
|
|
@@ -166,12 +166,10 @@ export class ImportCommand extends BaseCommand {
|
|
|
166
166
|
const searchPatterns = [
|
|
167
167
|
{ glob: 'CLAUDE.md', platform: 'claude-code' },
|
|
168
168
|
{ glob: '.claude/**/*.md', platform: 'claude-code' },
|
|
169
|
-
{ glob: '.cursorrules', platform: 'cursor' },
|
|
170
169
|
{ glob: '.cursor/rules/**/*.mdc', platform: 'cursor' },
|
|
171
170
|
{ glob: '.cursor/rules/**/*.md', platform: 'cursor' },
|
|
172
171
|
{ glob: '.github/copilot-instructions.md', platform: 'github-copilot' },
|
|
173
172
|
{ glob: '.windsurf/rules/**/*.md', platform: 'windsurf' },
|
|
174
|
-
{ glob: '.windsurfrules', platform: 'windsurf' },
|
|
175
173
|
];
|
|
176
174
|
|
|
177
175
|
for (const pattern of searchPatterns) {
|
|
@@ -22,8 +22,8 @@ export class InitCommand extends BaseCommand {
|
|
|
22
22
|
.option('-p, --projectPath <path>', 'Path to the project to scan', process.cwd())
|
|
23
23
|
.option(
|
|
24
24
|
'-o, --outputPath <path>',
|
|
25
|
-
'Path where generated
|
|
26
|
-
'./.vdk/rules'
|
|
25
|
+
'Path where generated rule artifacts should be saved',
|
|
26
|
+
'./.vdk/blueprints/rules'
|
|
27
27
|
)
|
|
28
28
|
.option('-d, --deep', 'Enable deep scanning for more thorough pattern detection', false)
|
|
29
29
|
.option('-i, --ignorePattern <patterns...>', 'Glob patterns to ignore', [
|
|
@@ -71,7 +71,7 @@ export class InitCommand extends BaseCommand {
|
|
|
71
71
|
return {
|
|
72
72
|
defaults: {
|
|
73
73
|
projectPath: process.cwd(),
|
|
74
|
-
outputPath: './.vdk/rules',
|
|
74
|
+
outputPath: './.vdk/blueprints/rules',
|
|
75
75
|
template: 'default',
|
|
76
76
|
useGitignore: true,
|
|
77
77
|
ideIntegration: true,
|
|
@@ -22,7 +22,11 @@ export class ScanCommand extends BaseCommand {
|
|
|
22
22
|
configureOptions(command) {
|
|
23
23
|
return command
|
|
24
24
|
.option('-p, --projectPath <path>', 'Path to the project to rescan', process.cwd())
|
|
25
|
-
.option(
|
|
25
|
+
.option(
|
|
26
|
+
'-o, --outputPath <path>',
|
|
27
|
+
'Path where updated rule artifacts should be saved',
|
|
28
|
+
'./.vdk/blueprints/rules'
|
|
29
|
+
)
|
|
26
30
|
.option('--ide <ide>', 'Target specific IDE for scanning (vscode, jetbrains, cursor, etc.)')
|
|
27
31
|
.option('-d, --deep', 'Enable deep scanning for more thorough pattern detection', false)
|
|
28
32
|
.option('-i, --ignorePattern <patterns...>', 'Glob patterns to ignore', [
|
|
@@ -53,7 +57,7 @@ export class ScanCommand extends BaseCommand {
|
|
|
53
57
|
return {
|
|
54
58
|
defaults: {
|
|
55
59
|
projectPath: process.cwd(),
|
|
56
|
-
outputPath: './.vdk/rules',
|
|
60
|
+
outputPath: './.vdk/blueprints/rules',
|
|
57
61
|
useGitignore: true,
|
|
58
62
|
incremental: false,
|
|
59
63
|
force: false,
|
|
@@ -29,7 +29,11 @@ export class StatusCommand extends BaseCommand {
|
|
|
29
29
|
configureOptions(command) {
|
|
30
30
|
return command
|
|
31
31
|
.option('-c, --configPath <path>', 'Path to the VDK configuration file', './vdk.config.json')
|
|
32
|
-
.option(
|
|
32
|
+
.option(
|
|
33
|
+
'-o, --outputPath <path>',
|
|
34
|
+
'Path to the rule artifacts directory',
|
|
35
|
+
'./.vdk/blueprints/rules'
|
|
36
|
+
)
|
|
33
37
|
.option('--scope <scope>', 'Status check scope (all, local, hub)', 'all')
|
|
34
38
|
.option('-v, --verbose', 'Show detailed status information', false);
|
|
35
39
|
}
|
|
@@ -43,7 +47,7 @@ export class StatusCommand extends BaseCommand {
|
|
|
43
47
|
|
|
44
48
|
// Ensure default values are applied if options are undefined
|
|
45
49
|
const configPath = path.resolve(options.configPath || './vdk.config.json');
|
|
46
|
-
const rulesDir = path.resolve(options.outputPath || './.vdk/rules');
|
|
50
|
+
const rulesDir = path.resolve(options.outputPath || './.vdk/blueprints/rules');
|
|
47
51
|
const scope = options.scope || 'all';
|
|
48
52
|
|
|
49
53
|
// Handle hub-only scope (provides detailed hub status like hub-status command)
|
|
@@ -31,7 +31,7 @@ export class ValidateCommand extends BaseCommand {
|
|
|
31
31
|
*/
|
|
32
32
|
configureOptions(command) {
|
|
33
33
|
return command
|
|
34
|
-
.option('-p, --path <path>', 'Path to blueprint
|
|
34
|
+
.option('-p, --path <path>', 'Path to blueprint artifact files', './.vdk/blueprints/rules')
|
|
35
35
|
.option('-f, --file <file>', 'Validate specific blueprint file')
|
|
36
36
|
.option('--platform <platform>', 'Validate against specific platform constraints')
|
|
37
37
|
.option('-v, --verbose', 'Show detailed validation results', false);
|