@vdkit/cli 3.0.0 ā 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
|
@@ -329,7 +329,9 @@ export class BaseIntegration {
|
|
|
329
329
|
break;
|
|
330
330
|
case 'medium':
|
|
331
331
|
detection.recommendations.push(`${name} appears to be configured`);
|
|
332
|
-
detection.recommendations.push(
|
|
332
|
+
detection.recommendations.push(
|
|
333
|
+
'Consider optimizing .vdk/blueprints/rules for better AI assistance'
|
|
334
|
+
);
|
|
333
335
|
break;
|
|
334
336
|
case 'high':
|
|
335
337
|
detection.recommendations.push(`${name} is actively configured and being used`);
|
|
@@ -374,7 +374,7 @@ This project uses VDK CLI for AI assistant integration and follows specific patt
|
|
|
374
374
|
- **Framework**: ${options.framework || 'Not detected'}
|
|
375
375
|
|
|
376
376
|
### Important Conventions
|
|
377
|
-
- All AI
|
|
377
|
+
- All AI rule artifacts are stored in \`.vdk/blueprints/rules/\` directory
|
|
378
378
|
- Rules follow unified YAML frontmatter format
|
|
379
379
|
- Project follows VDK CLI naming conventions
|
|
380
380
|
- Memory persistence is enabled for context continuity
|
|
@@ -422,7 +422,7 @@ claudeCode:
|
|
|
422
422
|
supports: false
|
|
423
423
|
fileReferences:
|
|
424
424
|
supports: true
|
|
425
|
-
autoInclude: ["CLAUDE.md", ".vdk/rules/", "package.json"]
|
|
425
|
+
autoInclude: ["CLAUDE.md", ".vdk/blueprints/rules/", "package.json"]
|
|
426
426
|
|
|
427
427
|
permissions:
|
|
428
428
|
allowedTools: ["Read", "Glob", "Grep"]
|
|
@@ -456,7 +456,7 @@ Analyze the current project using VDK CLI capabilities and provide actionable re
|
|
|
456
456
|
### File References
|
|
457
457
|
Auto-included files:
|
|
458
458
|
- \`@CLAUDE.md\` - Project context and conventions
|
|
459
|
-
- \`@.vdk/rules/\` - Current VDK
|
|
459
|
+
- \`@.vdk/blueprints/rules/\` - Current VDK rule artifacts directory
|
|
460
460
|
- \`@package.json\` - Project dependencies
|
|
461
461
|
|
|
462
462
|
## Analysis Areas
|
|
@@ -467,7 +467,7 @@ Auto-included files:
|
|
|
467
467
|
- Analyze technology stack and dependencies
|
|
468
468
|
|
|
469
469
|
2. **Rule Status Review**
|
|
470
|
-
|
|
470
|
+
- Check existing VDK rules in \`.vdk/blueprints/rules/\`
|
|
471
471
|
- Validate rule format and content
|
|
472
472
|
- Identify missing or outdated rules
|
|
473
473
|
|
|
@@ -516,7 +516,7 @@ claudeCode:
|
|
|
516
516
|
supports: false
|
|
517
517
|
fileReferences:
|
|
518
518
|
supports: true
|
|
519
|
-
autoInclude: ["CLAUDE.md", ".vdk/rules/", "package.json"]
|
|
519
|
+
autoInclude: ["CLAUDE.md", ".vdk/blueprints/rules/", "package.json"]
|
|
520
520
|
|
|
521
521
|
permissions:
|
|
522
522
|
allowedTools: ["Read", "Write", "Edit", "Bash(git:*)"]
|
|
@@ -604,7 +604,7 @@ claudeCode:
|
|
|
604
604
|
supports: false
|
|
605
605
|
fileReferences:
|
|
606
606
|
supports: true
|
|
607
|
-
autoInclude: ["CLAUDE.md", ".vdk/rules/", "package.json"]
|
|
607
|
+
autoInclude: ["CLAUDE.md", ".vdk/blueprints/rules/", "package.json"]
|
|
608
608
|
bashCommands:
|
|
609
609
|
supports: true
|
|
610
610
|
commands: ["git status", "git log --oneline -10"]
|
|
@@ -256,7 +256,7 @@ temp/
|
|
|
256
256
|
*.temp
|
|
257
257
|
|
|
258
258
|
# VDK specific (comment out if you want AI to see these)
|
|
259
|
-
# .vdk/rules/
|
|
259
|
+
# .vdk/blueprints/rules/
|
|
260
260
|
# vdk.config.json
|
|
261
261
|
`;
|
|
262
262
|
|
|
@@ -424,7 +424,7 @@ Reference this rule with @vdk-integration when working with VDK CLI.
|
|
|
424
424
|
|
|
425
425
|
## Integration Features
|
|
426
426
|
- **Automatic Detection**: VDK CLI detects Cursor configuration
|
|
427
|
-
- **Rule Generation**: Creates Cursor-compatible .vdk/rules
|
|
427
|
+
- **Rule Generation**: Creates Cursor-compatible .vdk/blueprints/rules
|
|
428
428
|
- **MDC Format**: Proper metadata for rule activation
|
|
429
429
|
- **Cross-IDE Compatibility**: Works with multiple AI assistants
|
|
430
430
|
|
|
@@ -118,7 +118,7 @@ export class GenericAIIntegration extends BaseIntegration {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
} catch
|
|
121
|
+
} catch {
|
|
122
122
|
// Ignore file read errors
|
|
123
123
|
}
|
|
124
124
|
}
|
|
@@ -171,7 +171,7 @@ export class GenericAIIntegration extends BaseIntegration {
|
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
} catch
|
|
174
|
+
} catch {
|
|
175
175
|
// Ignore package.json read errors
|
|
176
176
|
}
|
|
177
177
|
}
|
|
@@ -235,7 +235,7 @@ export class GenericAIIntegration extends BaseIntegration {
|
|
|
235
235
|
detection.confidence = 'low';
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
|
-
} catch
|
|
238
|
+
} catch {
|
|
239
239
|
// Ignore directory read errors
|
|
240
240
|
}
|
|
241
241
|
}
|
|
@@ -265,7 +265,7 @@ export class GenericAIIntegration extends BaseIntegration {
|
|
|
265
265
|
'VDK can help standardize AI tool configurations across your project'
|
|
266
266
|
);
|
|
267
267
|
detection.recommendations.push(
|
|
268
|
-
'Review .vdk/rules/ for AI assistant optimization opportunities'
|
|
268
|
+
'Review .vdk/blueprints/rules/ for AI assistant optimization opportunities'
|
|
269
269
|
);
|
|
270
270
|
} else {
|
|
271
271
|
detection.recommendations.push('Well-configured AI setup detected');
|
|
@@ -283,10 +283,10 @@ export class GenericAIIntegration extends BaseIntegration {
|
|
|
283
283
|
getConfigPaths() {
|
|
284
284
|
return {
|
|
285
285
|
projectConfig: path.join(this.projectPath, '.ai'),
|
|
286
|
-
rulesPath: path.join(this.projectPath, '.vdk', 'rules'),
|
|
286
|
+
rulesPath: path.join(this.projectPath, '.vdk', 'blueprints', 'rules'),
|
|
287
287
|
configFile: path.join(this.projectPath, '.aiconfig.json'),
|
|
288
288
|
aiConfig: path.join(this.projectPath, '.ai'),
|
|
289
|
-
vdkRules: path.join(this.projectPath, '.vdk', 'rules'),
|
|
289
|
+
vdkRules: path.join(this.projectPath, '.vdk', 'blueprints', 'rules'),
|
|
290
290
|
aiConfigFiles: [
|
|
291
291
|
path.join(this.projectPath, '.aiconfig.json'),
|
|
292
292
|
path.join(this.projectPath, 'ai-config.json'),
|
|
@@ -319,8 +319,8 @@ export class GenericAIIntegration extends BaseIntegration {
|
|
|
319
319
|
console.log('Setting up generic AI platform integration...');
|
|
320
320
|
}
|
|
321
321
|
|
|
322
|
-
// Ensure .vdk/rules directory exists
|
|
323
|
-
const rulesPath = path.join(this.projectPath, '.vdk', 'rules');
|
|
322
|
+
// Ensure .vdk/blueprints/rules directory exists
|
|
323
|
+
const rulesPath = path.join(this.projectPath, '.vdk', 'blueprints', 'rules');
|
|
324
324
|
await this.ensureDirectory(rulesPath);
|
|
325
325
|
|
|
326
326
|
// Create basic AI configuration if none exists
|
|
@@ -364,7 +364,7 @@ This configuration was automatically generated by VDK to provide basic AI assist
|
|
|
364
364
|
|
|
365
365
|
- AI assistants can use this configuration to better understand your project structure
|
|
366
366
|
- Customize this file to include project-specific patterns and conventions
|
|
367
|
-
- Add more specific rules in the .vdk/rules/ directory as needed
|
|
367
|
+
- Add more specific rules in the .vdk/blueprints/rules/ directory as needed
|
|
368
368
|
|
|
369
369
|
## Generated
|
|
370
370
|
|
|
@@ -170,7 +170,7 @@ export class GenericIDEIntegration extends BaseIntegration {
|
|
|
170
170
|
break;
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
|
-
} catch
|
|
173
|
+
} catch {
|
|
174
174
|
// Ignore file read errors
|
|
175
175
|
}
|
|
176
176
|
}
|
|
@@ -295,7 +295,7 @@ export class GenericIDEIntegration extends BaseIntegration {
|
|
|
295
295
|
if (verbose) {
|
|
296
296
|
console.log('No IDEs detected - setting up generic configuration');
|
|
297
297
|
}
|
|
298
|
-
// Set up generic .vdk/rules configuration
|
|
298
|
+
// Set up generic .vdk/blueprints/rules configuration
|
|
299
299
|
await this.setupGenericConfiguration(options);
|
|
300
300
|
return true;
|
|
301
301
|
}
|
|
@@ -330,11 +330,11 @@ export class GenericIDEIntegration extends BaseIntegration {
|
|
|
330
330
|
}
|
|
331
331
|
|
|
332
332
|
/**
|
|
333
|
-
* Set up generic .vdk/rules configuration
|
|
333
|
+
* Set up generic .vdk/blueprints/rules configuration
|
|
334
334
|
* @param {Object} options - Configuration options
|
|
335
335
|
*/
|
|
336
336
|
async setupGenericConfiguration(options = {}) {
|
|
337
|
-
const genericRulesPath = path.join(this.projectPath, '.vdk', 'rules');
|
|
337
|
+
const genericRulesPath = path.join(this.projectPath, '.vdk', 'blueprints', 'rules');
|
|
338
338
|
await this.ensureDirectory(genericRulesPath);
|
|
339
339
|
await this.createInitialRules(genericRulesPath, 'generic', options);
|
|
340
340
|
}
|
|
@@ -391,7 +391,7 @@ export class GenericIDEIntegration extends BaseIntegration {
|
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
// Sort by confidence and return the highest
|
|
394
|
-
const sorted = [...detectedIDEs].
|
|
394
|
+
const sorted = [...detectedIDEs].toSorted((a, b) => {
|
|
395
395
|
const confidenceOrder = { high: 3, medium: 2, low: 1, none: 0 };
|
|
396
396
|
return confidenceOrder[b.confidence] - confidenceOrder[a.confidence];
|
|
397
397
|
});
|
|
@@ -493,7 +493,7 @@ export class IntegrationManager {
|
|
|
493
493
|
|
|
494
494
|
// Sort by project-specific config first, then confidence level
|
|
495
495
|
const confidenceOrder = { high: 3, medium: 2, low: 1, none: 0 };
|
|
496
|
-
const sorted = [...activeIntegrations].
|
|
496
|
+
const sorted = [...activeIntegrations].toSorted((a, b) => {
|
|
497
497
|
// First priority: Project-specific config beats global config, regardless of confidence
|
|
498
498
|
const aHasProjectConfig = a.detection?.hasProjectSpecificConfig;
|
|
499
499
|
const bHasProjectConfig = b.detection?.hasProjectSpecificConfig;
|
|
@@ -82,7 +82,7 @@ export class JetBrainsIntegration extends BaseIntegration {
|
|
|
82
82
|
detection.confidence = 'medium';
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
-
} catch
|
|
85
|
+
} catch {
|
|
86
86
|
// Process detection failed - not critical
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -165,7 +165,7 @@ export class JetBrainsIntegration extends BaseIntegration {
|
|
|
165
165
|
return path.join(cacheDir, jetbrainsVersions[0], 'mcp');
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
|
-
} catch
|
|
168
|
+
} catch {
|
|
169
169
|
// Ignore errors in path detection
|
|
170
170
|
}
|
|
171
171
|
|
|
@@ -193,7 +193,7 @@ export class JetBrainsIntegration extends BaseIntegration {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
return [...new Set(jetbrainsProcesses)]; // Remove duplicates
|
|
196
|
-
} catch
|
|
196
|
+
} catch {
|
|
197
197
|
return [];
|
|
198
198
|
}
|
|
199
199
|
}
|
|
@@ -147,7 +147,7 @@ class VSCodeVariantIntegration extends BaseIntegration {
|
|
|
147
147
|
detection.confidence = 'medium';
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
-
} catch
|
|
150
|
+
} catch {
|
|
151
151
|
// Process detection failed - not critical
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -189,7 +189,7 @@ class VSCodeVariantIntegration extends BaseIntegration {
|
|
|
189
189
|
|
|
190
190
|
const names = processNames[this.variant] || ['code'];
|
|
191
191
|
return names.some(name => processes.includes(name));
|
|
192
|
-
} catch
|
|
192
|
+
} catch {
|
|
193
193
|
return false;
|
|
194
194
|
}
|
|
195
195
|
}
|
|
@@ -289,7 +289,7 @@ export class WindsurfContextIntegration extends BaseIntegration {
|
|
|
289
289
|
},
|
|
290
290
|
projectAwareness: {
|
|
291
291
|
enabled: true,
|
|
292
|
-
includeFiles: ['README.md', 'package.json', '*.config.*', '.vdk/rules/**'],
|
|
292
|
+
includeFiles: ['README.md', 'package.json', '*.config.*', '.vdk/blueprints/rules/**'],
|
|
293
293
|
excludePatterns: ['node_modules/**', 'dist/**', '*.log', '.git/**'],
|
|
294
294
|
},
|
|
295
295
|
};
|
|
@@ -53,7 +53,7 @@ export class ZedIntegration extends BaseIntegration {
|
|
|
53
53
|
indicators.push('Zed process is currently running');
|
|
54
54
|
if (confidence === 'none') confidence = 'medium';
|
|
55
55
|
}
|
|
56
|
-
} catch
|
|
56
|
+
} catch {
|
|
57
57
|
// Process detection failed - not critical
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -118,7 +118,7 @@ export class ZedIntegration extends BaseIntegration {
|
|
|
118
118
|
return (
|
|
119
119
|
processes.toLowerCase().includes('zed') || processes.toLowerCase().includes('zed-editor')
|
|
120
120
|
);
|
|
121
|
-
} catch
|
|
121
|
+
} catch {
|
|
122
122
|
return false;
|
|
123
123
|
}
|
|
124
124
|
}
|
package/src/ir/README.md
CHANGED
|
@@ -26,7 +26,7 @@ VDK-CLI/src/ir/
|
|
|
26
26
|
### Base Platforms (index.js + generators.js)
|
|
27
27
|
|
|
28
28
|
- **Claude Code** - Full support (.claude/, CLAUDE.md, agents, rules, commands, skills)
|
|
29
|
-
- **Cursor** - MDC format
|
|
29
|
+
- **Cursor** - MDC format in `.cursor/rules/*.mdc`, glob patterns, activation modes
|
|
30
30
|
- **GitHub Copilot** - 3000 char limit with smart truncation
|
|
31
31
|
- **Windsurf** - Rules and workflows
|
|
32
32
|
|
|
@@ -273,7 +273,7 @@ const { lossInfo } = irToCopilot(ir);
|
|
|
273
273
|
- ā
MDC (Markdown Component) format
|
|
274
274
|
- ā
Glob patterns for auto-attachment
|
|
275
275
|
- ā
Activation modes: always, auto-attached, agent-requested, manual
|
|
276
|
-
- ā
|
|
276
|
+
- ā
`.cursor/rules/*.mdc`
|
|
277
277
|
- ā No agents
|
|
278
278
|
- ā No settings
|
|
279
279
|
|
package/src/ir/generators.js
CHANGED
|
@@ -104,11 +104,10 @@ export function irToClaude(ir, _options = {}) {
|
|
|
104
104
|
* @param {IntermediateRepresentation} ir - IR to convert
|
|
105
105
|
* @param {Object} [options] - Generation options
|
|
106
106
|
* @param {boolean} [options.useMDC=true] - Use MDC format for .cursor/rules/
|
|
107
|
-
* @param {boolean} [options.singleFile=false] - Generate single .cursorrules file
|
|
108
107
|
* @returns {{content: string, filePath: string, lossInfo: Array}}
|
|
109
108
|
*/
|
|
110
109
|
export function irToCursor(ir, options = {}) {
|
|
111
|
-
const { useMDC = true
|
|
110
|
+
const { useMDC = true } = options;
|
|
112
111
|
const lossInfo = trackConversionLoss(ir, ir, 'cursor');
|
|
113
112
|
|
|
114
113
|
// Track agent conversion (Cursor doesn't support agents)
|
|
@@ -122,9 +121,9 @@ export function irToCursor(ir, options = {}) {
|
|
|
122
121
|
}
|
|
123
122
|
|
|
124
123
|
let content = '';
|
|
125
|
-
const filePath =
|
|
124
|
+
const filePath = `.cursor/rules/${sanitizeFileName(ir.name)}.mdc`;
|
|
126
125
|
|
|
127
|
-
if (useMDC
|
|
126
|
+
if (useMDC) {
|
|
128
127
|
// Generate MDC format
|
|
129
128
|
const frontmatter = {};
|
|
130
129
|
if (ir.description) frontmatter.description = ir.description;
|
|
@@ -240,7 +239,7 @@ function priorityTruncate(content, sections, maxLength) {
|
|
|
240
239
|
}
|
|
241
240
|
|
|
242
241
|
// Sort sections by priority
|
|
243
|
-
const sortedSections = [...sections].
|
|
242
|
+
const sortedSections = [...sections].toSorted((a, b) => {
|
|
244
243
|
const aTitle = a.title?.toLowerCase() || '';
|
|
245
244
|
const bTitle = b.title?.toLowerCase() || '';
|
|
246
245
|
|
package/src/ir/index.js
CHANGED
|
@@ -416,12 +416,7 @@ export function detectPlatformFromPath(filePath) {
|
|
|
416
416
|
|
|
417
417
|
if (normalizedPath.includes('.claude') || normalizedPath.includes('claude.md'))
|
|
418
418
|
return 'claude-code';
|
|
419
|
-
if (
|
|
420
|
-
normalizedPath.includes('.cursor') ||
|
|
421
|
-
normalizedPath.includes('.cursorrules') ||
|
|
422
|
-
normalizedPath.endsWith('.mdc')
|
|
423
|
-
)
|
|
424
|
-
return 'cursor';
|
|
419
|
+
if (normalizedPath.includes('.cursor') || normalizedPath.endsWith('.mdc')) return 'cursor';
|
|
425
420
|
if (normalizedPath.includes('copilot') || normalizedPath.includes('.github/copilot'))
|
|
426
421
|
return 'github-copilot';
|
|
427
422
|
if (normalizedPath.includes('.windsurf')) return 'windsurf';
|
package/src/ir/performance.js
CHANGED
|
@@ -99,7 +99,7 @@ function getFileHash(filePath) {
|
|
|
99
99
|
try {
|
|
100
100
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
101
101
|
return crypto.createHash('sha256').update(content).digest('hex').substring(0, 16);
|
|
102
|
-
} catch
|
|
102
|
+
} catch {
|
|
103
103
|
return null;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
@@ -119,7 +119,7 @@ function getCachedFileStats(filePath) {
|
|
|
119
119
|
if (stats.mtimeMs === cached.mtime && stats.size === cached.size) {
|
|
120
120
|
return cached;
|
|
121
121
|
}
|
|
122
|
-
} catch
|
|
122
|
+
} catch {
|
|
123
123
|
// File no longer exists or error reading
|
|
124
124
|
fileStatsCache.delete(filePath);
|
|
125
125
|
return null;
|
|
@@ -141,7 +141,7 @@ function getCachedFileStats(filePath) {
|
|
|
141
141
|
|
|
142
142
|
fileStatsCache.set(filePath, fileStats);
|
|
143
143
|
return fileStats;
|
|
144
|
-
} catch
|
|
144
|
+
} catch {
|
|
145
145
|
return null;
|
|
146
146
|
}
|
|
147
147
|
}
|
package/src/mcp/McpManager.js
CHANGED
|
@@ -35,7 +35,7 @@ export class McpManager {
|
|
|
35
35
|
if (config.mcpServers) {
|
|
36
36
|
this.configs.set(loc, config.mcpServers);
|
|
37
37
|
}
|
|
38
|
-
} catch
|
|
38
|
+
} catch {
|
|
39
39
|
// Ignore missing files
|
|
40
40
|
}
|
|
41
41
|
}
|
|
@@ -82,7 +82,7 @@ export class McpManager {
|
|
|
82
82
|
// Check common paths if none found
|
|
83
83
|
if (ruleDirectories.length === 0) {
|
|
84
84
|
const commonPaths = [
|
|
85
|
-
'.vdk/rules',
|
|
85
|
+
'.vdk/blueprints/rules',
|
|
86
86
|
'.vscode/ai-rules',
|
|
87
87
|
'.cursor/rules',
|
|
88
88
|
'.claude/rules',
|
|
@@ -101,7 +101,7 @@ export class McpManager {
|
|
|
101
101
|
|
|
102
102
|
// Create default if forced
|
|
103
103
|
if (ruleDirectories.length === 0 && force) {
|
|
104
|
-
const defaultPath = path.join(projectPath, '.vdk/rules');
|
|
104
|
+
const defaultPath = path.join(projectPath, '.vdk/blueprints/rules');
|
|
105
105
|
if (!existsSync(defaultPath)) {
|
|
106
106
|
await fs.mkdir(defaultPath, { recursive: true });
|
|
107
107
|
}
|
|
@@ -22,7 +22,8 @@ import { MigrationBackup } from './core/MigrationBackup.js';
|
|
|
22
22
|
export class AutoMigrator {
|
|
23
23
|
constructor(projectPath) {
|
|
24
24
|
this.projectPath = projectPath;
|
|
25
|
-
this.importPath = path.join(projectPath, '.vdk', '
|
|
25
|
+
this.importPath = path.join(projectPath, '.vdk', 'migrate');
|
|
26
|
+
this.legacyImportPath = path.join(projectPath, '.vdk', 'import');
|
|
26
27
|
this.projectScanner = new ProjectScanner({ projectPath: projectPath });
|
|
27
28
|
this.technologyAnalyzer = new TechnologyAnalyzer({ verbose: false });
|
|
28
29
|
this.patternDetector = new PatternDetector({ verbose: false });
|
|
@@ -46,11 +47,11 @@ export class AutoMigrator {
|
|
|
46
47
|
|
|
47
48
|
try {
|
|
48
49
|
// 1. Scan import directory for old rules
|
|
49
|
-
spinner.text = 'Scanning .vdk/
|
|
50
|
+
spinner.text = 'Scanning .vdk/migrate/ for AI rules...';
|
|
50
51
|
const detectedRules = await this.detectImportedRules();
|
|
51
52
|
|
|
52
53
|
if (detectedRules.length === 0) {
|
|
53
|
-
spinner.info('No rules found in .vdk/import/');
|
|
54
|
+
spinner.info('No rules found in .vdk/migrate/ (legacy: .vdk/import/)');
|
|
54
55
|
this.showImportInstructions();
|
|
55
56
|
return { success: false, reason: 'no_rules_found' };
|
|
56
57
|
}
|
|
@@ -160,28 +161,34 @@ export class AutoMigrator {
|
|
|
160
161
|
*/
|
|
161
162
|
async detectImportedRules() {
|
|
162
163
|
const rules = [];
|
|
164
|
+
const seenFiles = new Set();
|
|
165
|
+
const candidatePaths = [this.importPath, this.legacyImportPath];
|
|
163
166
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
for (const candidatePath of candidatePaths) {
|
|
168
|
+
try {
|
|
169
|
+
await fs.access(candidatePath);
|
|
170
|
+
} catch {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
170
173
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
try {
|
|
175
|
+
const importFiles = await fs.readdir(candidatePath, { withFileTypes: true });
|
|
176
|
+
|
|
177
|
+
for (const entry of importFiles) {
|
|
178
|
+
if (entry.isFile()) {
|
|
179
|
+
const filePath = path.join(candidatePath, entry.name);
|
|
180
|
+
if (seenFiles.has(filePath)) continue;
|
|
181
|
+
|
|
182
|
+
const detectedRule = await this.detectRuleType(filePath);
|
|
183
|
+
if (detectedRule) {
|
|
184
|
+
rules.push(detectedRule);
|
|
185
|
+
seenFiles.add(filePath);
|
|
186
|
+
}
|
|
180
187
|
}
|
|
181
188
|
}
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.warn(chalk.yellow(`Warning: Could not read import directory: ${error.message}`));
|
|
182
191
|
}
|
|
183
|
-
} catch (error) {
|
|
184
|
-
console.warn(chalk.yellow(`Warning: Could not read import directory: ${error.message}`));
|
|
185
192
|
}
|
|
186
193
|
|
|
187
194
|
return rules;
|
|
@@ -597,14 +604,20 @@ export class AutoMigrator {
|
|
|
597
604
|
* Clean up the import directory after successful migration
|
|
598
605
|
*/
|
|
599
606
|
async cleanImportDirectory() {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
607
|
+
const candidatePaths = [this.importPath, this.legacyImportPath];
|
|
608
|
+
|
|
609
|
+
for (const candidatePath of candidatePaths) {
|
|
610
|
+
try {
|
|
611
|
+
const files = await fs.readdir(candidatePath);
|
|
612
|
+
for (const file of files) {
|
|
613
|
+
await fs.unlink(path.join(candidatePath, file));
|
|
614
|
+
}
|
|
615
|
+
await fs.rmdir(candidatePath);
|
|
616
|
+
} catch (error) {
|
|
617
|
+
if (error?.code !== 'ENOENT') {
|
|
618
|
+
console.warn(chalk.yellow(`Warning: Could not clean import directory: ${error.message}`));
|
|
619
|
+
}
|
|
604
620
|
}
|
|
605
|
-
await fs.rmdir(this.importPath);
|
|
606
|
-
} catch (error) {
|
|
607
|
-
console.warn(chalk.yellow(`Warning: Could not clean import directory: ${error.message}`));
|
|
608
621
|
}
|
|
609
622
|
}
|
|
610
623
|
|
|
@@ -702,12 +715,13 @@ export class AutoMigrator {
|
|
|
702
715
|
showImportInstructions() {
|
|
703
716
|
console.log(chalk.cyan('\nš To migrate existing AI rules:'));
|
|
704
717
|
console.log(chalk.gray('1. Create the import directory:'));
|
|
705
|
-
console.log(chalk.gray(' mkdir -p .vdk/
|
|
718
|
+
console.log(chalk.gray(' mkdir -p .vdk/migrate'));
|
|
706
719
|
console.log(chalk.gray('\n2. Copy your existing rule files:'));
|
|
707
|
-
console.log(chalk.gray(' cp .cursorrules .vdk/
|
|
708
|
-
console.log(chalk.gray(' cp .claude/memory.md .vdk/
|
|
709
|
-
console.log(chalk.gray(' cp .github/copilot-instructions.json .vdk/
|
|
710
|
-
console.log(chalk.gray(' cp .windsurf/rules.xml .vdk/
|
|
720
|
+
console.log(chalk.gray(' cp .cursorrules .vdk/migrate/'));
|
|
721
|
+
console.log(chalk.gray(' cp .claude/memory.md .vdk/migrate/'));
|
|
722
|
+
console.log(chalk.gray(' cp .github/copilot-instructions.json .vdk/migrate/'));
|
|
723
|
+
console.log(chalk.gray(' cp .windsurf/rules.xml .vdk/migrate/'));
|
|
724
|
+
console.log(chalk.gray('\n # Legacy path .vdk/import/ is still supported during transition'));
|
|
711
725
|
console.log(chalk.gray('\n3. Run migration:'));
|
|
712
726
|
console.log(chalk.gray(' vdk migrate'));
|
|
713
727
|
}
|
|
@@ -27,7 +27,7 @@ export class ContextConverter {
|
|
|
27
27
|
* @returns {Object} VDK blueprint or command
|
|
28
28
|
*/
|
|
29
29
|
async convertClaudeCode(context) {
|
|
30
|
-
const { fileName, bodyContent,
|
|
30
|
+
const { fileName, bodyContent, claudeSpecific } = context;
|
|
31
31
|
|
|
32
32
|
// Determine if it's a command or blueprint
|
|
33
33
|
const isCommand = claudeSpecific?.hasSlashCommands || fileName.includes('command');
|
|
@@ -105,7 +105,7 @@ export class ContextConverter {
|
|
|
105
105
|
* @returns {Object} VDK blueprint
|
|
106
106
|
*/
|
|
107
107
|
async convertGitHubCopilot(context) {
|
|
108
|
-
const {
|
|
108
|
+
const { copilotSpecific } = context;
|
|
109
109
|
|
|
110
110
|
const reviewType = copilotSpecific?.hasSecurityRules
|
|
111
111
|
? 'security'
|
|
@@ -290,7 +290,7 @@ export class ContextConverter {
|
|
|
290
290
|
* @returns {Object} Memory blueprint
|
|
291
291
|
*/
|
|
292
292
|
convertToMemoryBlueprint(context) {
|
|
293
|
-
const {
|
|
293
|
+
const {} = context;
|
|
294
294
|
|
|
295
295
|
return this.convertToBlueprint(context, {
|
|
296
296
|
category: 'core',
|
|
@@ -75,7 +75,7 @@ export class MigrationBackup {
|
|
|
75
75
|
|
|
76
76
|
return this.migrationId;
|
|
77
77
|
} catch (error) {
|
|
78
|
-
throw new Error(`Failed to create migration backup: ${error.message}
|
|
78
|
+
throw new Error(`Failed to create migration backup: ${error.message}`, { cause: error });
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -137,7 +137,7 @@ export class MigrationBackup {
|
|
|
137
137
|
|
|
138
138
|
return { success: true, restoredCount, backupId };
|
|
139
139
|
} catch (error) {
|
|
140
|
-
throw new Error(`Rollback failed: ${error.message}
|
|
140
|
+
throw new Error(`Rollback failed: ${error.message}`, { cause: error });
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -175,7 +175,7 @@ export class MigrationBackup {
|
|
|
175
175
|
path: path.join(this.backupDir, entry.name),
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
|
-
} catch
|
|
178
|
+
} catch {
|
|
179
179
|
// Skip invalid backup entries
|
|
180
180
|
console.warn(chalk.yellow(`Warning: Invalid backup metadata for ${entry.name}`));
|
|
181
181
|
}
|
|
@@ -183,7 +183,7 @@ export class MigrationBackup {
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
// Sort by timestamp (newest first)
|
|
186
|
-
return backups.
|
|
186
|
+
return backups.toSorted((a, b) => new Date(b.timestamp) - new Date(a.timestamp));
|
|
187
187
|
} catch (error) {
|
|
188
188
|
console.warn(chalk.yellow(`Warning: Failed to list backups: ${error.message}`));
|
|
189
189
|
return [];
|
|
@@ -263,7 +263,7 @@ export class MigrationBackup {
|
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
return true;
|
|
266
|
-
} catch
|
|
266
|
+
} catch {
|
|
267
267
|
return false;
|
|
268
268
|
}
|
|
269
269
|
}
|
|
@@ -286,24 +286,30 @@ export class MigrationBackup {
|
|
|
286
286
|
});
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
// VDK
|
|
290
|
-
const rulesDir = path.join(this.projectPath, '.vdk', 'rules');
|
|
289
|
+
// VDK rule artifacts directory
|
|
290
|
+
const rulesDir = path.join(this.projectPath, '.vdk', 'blueprints', 'rules');
|
|
291
291
|
if (await this.fileExists(rulesDir)) {
|
|
292
292
|
targets.push({
|
|
293
293
|
type: 'directory',
|
|
294
294
|
path: rulesDir,
|
|
295
|
-
relativePath: '.vdk/rules',
|
|
295
|
+
relativePath: '.vdk/blueprints/rules',
|
|
296
296
|
});
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
// VDK
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
299
|
+
// VDK migration staging directories (primary + legacy)
|
|
300
|
+
const migrationDirs = [
|
|
301
|
+
{ path: path.join(this.projectPath, '.vdk', 'migrate'), relativePath: '.vdk/migrate' },
|
|
302
|
+
{ path: path.join(this.projectPath, '.vdk', 'import'), relativePath: '.vdk/import' },
|
|
303
|
+
];
|
|
304
|
+
|
|
305
|
+
for (const migrationDir of migrationDirs) {
|
|
306
|
+
if (await this.fileExists(migrationDir.path)) {
|
|
307
|
+
targets.push({
|
|
308
|
+
type: 'directory',
|
|
309
|
+
path: migrationDir.path,
|
|
310
|
+
relativePath: migrationDir.relativePath,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
307
313
|
}
|
|
308
314
|
|
|
309
315
|
// IDE-specific configuration files that VDK might modify
|
|
@@ -498,7 +504,7 @@ export class MigrationBackup {
|
|
|
498
504
|
* @private
|
|
499
505
|
*/
|
|
500
506
|
async removeCurrentVDKFiles(options = {}) {
|
|
501
|
-
const filesToRemove = ['vdk.config.json', '.vdk/rules'];
|
|
507
|
+
const filesToRemove = ['vdk.config.json', '.vdk/blueprints/rules'];
|
|
502
508
|
|
|
503
509
|
for (const relativePath of filesToRemove) {
|
|
504
510
|
const fullPath = path.join(this.projectPath, relativePath);
|