mcp-adr-analysis-server 2.0.13 → 2.0.14
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 +87 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/src/index.d.ts +17 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +332 -23
- package/dist/src/index.js.map +1 -1
- package/dist/src/utils/directory-compat.d.ts +8 -0
- package/dist/src/utils/directory-compat.d.ts.map +1 -0
- package/dist/src/utils/directory-compat.js +27 -0
- package/dist/src/utils/directory-compat.js.map +1 -0
- package/package.json +13 -12
package/dist/src/index.js
CHANGED
|
@@ -10,8 +10,8 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
|
10
10
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
11
11
|
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
12
12
|
import { readFileSync } from 'fs';
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
import { getCurrentDirCompat } from './utils/directory-compat.js';
|
|
15
15
|
import { McpAdrError } from './types/index.js';
|
|
16
16
|
import { CONVERSATION_CONTEXT_SCHEMA } from './types/conversation-context.js';
|
|
17
17
|
import { maskMcpResponse, createMaskingConfig } from './utils/output-masking.js';
|
|
@@ -23,17 +23,7 @@ import { KnowledgeGraphManager } from './utils/knowledge-graph-manager.js';
|
|
|
23
23
|
function getPackageVersion() {
|
|
24
24
|
try {
|
|
25
25
|
// Handle both Jest environment and normal execution
|
|
26
|
-
|
|
27
|
-
if (typeof import.meta !== 'undefined' && import.meta.url) {
|
|
28
|
-
// Normal ESM execution
|
|
29
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
30
|
-
currentDir = dirname(__filename);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
// Jest or other environments without import.meta support
|
|
34
|
-
// Use process.cwd() as fallback
|
|
35
|
-
currentDir = process.cwd();
|
|
36
|
-
}
|
|
26
|
+
const currentDir = getCurrentDirCompat();
|
|
37
27
|
// Try multiple possible locations for package.json
|
|
38
28
|
const possiblePaths = [
|
|
39
29
|
join(currentDir, 'package.json'),
|
|
@@ -330,6 +320,37 @@ export class McpAdrAnalysisServer {
|
|
|
330
320
|
description: 'Path to project root for environment analysis',
|
|
331
321
|
default: '.'
|
|
332
322
|
},
|
|
323
|
+
environment: {
|
|
324
|
+
type: 'string',
|
|
325
|
+
enum: ['development', 'staging', 'production', 'testing', 'auto-detect'],
|
|
326
|
+
description: 'Target environment context for validation (auto-detect will infer from project structure)',
|
|
327
|
+
default: 'auto-detect'
|
|
328
|
+
},
|
|
329
|
+
environmentConfig: {
|
|
330
|
+
type: 'object',
|
|
331
|
+
description: 'Environment-specific configuration and requirements',
|
|
332
|
+
properties: {
|
|
333
|
+
requiredFiles: {
|
|
334
|
+
type: 'array',
|
|
335
|
+
items: { type: 'string' },
|
|
336
|
+
description: 'Files required for this environment'
|
|
337
|
+
},
|
|
338
|
+
requiredServices: {
|
|
339
|
+
type: 'array',
|
|
340
|
+
items: { type: 'string' },
|
|
341
|
+
description: 'Services that must be implemented for this environment'
|
|
342
|
+
},
|
|
343
|
+
securityLevel: {
|
|
344
|
+
type: 'string',
|
|
345
|
+
enum: ['low', 'medium', 'high', 'critical'],
|
|
346
|
+
description: 'Required security level for this environment'
|
|
347
|
+
},
|
|
348
|
+
performanceRequirements: {
|
|
349
|
+
type: 'object',
|
|
350
|
+
description: 'Performance requirements for this environment'
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
},
|
|
333
354
|
validationType: {
|
|
334
355
|
type: 'string',
|
|
335
356
|
enum: ['full', 'todo-only', 'adr-only', 'environment-only'],
|
|
@@ -360,6 +381,11 @@ export class McpAdrAnalysisServer {
|
|
|
360
381
|
type: 'boolean',
|
|
361
382
|
description: 'Enable strict validation mode with reality-check mechanisms against overconfident assessments',
|
|
362
383
|
default: true
|
|
384
|
+
},
|
|
385
|
+
environmentValidation: {
|
|
386
|
+
type: 'boolean',
|
|
387
|
+
description: 'Enable environment-specific validation rules and checks',
|
|
388
|
+
default: true
|
|
363
389
|
}
|
|
364
390
|
}
|
|
365
391
|
}
|
|
@@ -3588,7 +3614,7 @@ ${importResult.content[0].text}
|
|
|
3588
3614
|
}
|
|
3589
3615
|
}
|
|
3590
3616
|
async compareAdrProgress(args) {
|
|
3591
|
-
const { todoPath = 'TODO.md', adrDirectory = this.config.adrDirectory, projectPath = this.config.projectPath, validationType = 'full', includeFileChecks = true, includeRuleValidation = true, deepCodeAnalysis = true, functionalValidation = true, strictMode = true } = args;
|
|
3617
|
+
const { todoPath = 'TODO.md', adrDirectory = this.config.adrDirectory, projectPath = this.config.projectPath, environment = 'auto-detect', environmentConfig = {}, validationType = 'full', includeFileChecks = true, includeRuleValidation = true, deepCodeAnalysis = true, functionalValidation = true, strictMode = true, environmentValidation = true } = args;
|
|
3592
3618
|
const { getAdrDirectoryPath } = await import('./utils/config.js');
|
|
3593
3619
|
const path = await import('path');
|
|
3594
3620
|
// Resolve paths
|
|
@@ -3596,7 +3622,21 @@ ${importResult.content[0].text}
|
|
|
3596
3622
|
const absoluteAdrPath = adrDirectory ?
|
|
3597
3623
|
path.resolve(projectPath, adrDirectory) :
|
|
3598
3624
|
getAdrDirectoryPath(this.config);
|
|
3599
|
-
this.logger.info(`Comparing ADR progress: TODO(${absoluteTodoPath}) vs ADRs(${absoluteAdrPath}) vs Environment(${projectPath})`);
|
|
3625
|
+
this.logger.info(`Comparing ADR progress: TODO(${absoluteTodoPath}) vs ADRs(${absoluteAdrPath}) vs Environment(${projectPath}) [env: ${environment}]`);
|
|
3626
|
+
// Environment validation and auto-detection
|
|
3627
|
+
let detectedEnvironment = environment;
|
|
3628
|
+
let finalEnvironmentConfig = { ...environmentConfig };
|
|
3629
|
+
if (environmentValidation && (validationType === 'full' || validationType === 'environment-only')) {
|
|
3630
|
+
try {
|
|
3631
|
+
const envResult = await this.detectAndValidateEnvironment(projectPath, environment, environmentConfig);
|
|
3632
|
+
detectedEnvironment = envResult.detectedEnvironment;
|
|
3633
|
+
finalEnvironmentConfig = { ...finalEnvironmentConfig, ...envResult.environmentConfig };
|
|
3634
|
+
this.logger.info(`Environment detection result: ${detectedEnvironment}`);
|
|
3635
|
+
}
|
|
3636
|
+
catch (error) {
|
|
3637
|
+
this.logger.warn(`Environment detection failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3600
3640
|
try {
|
|
3601
3641
|
// Step 1: Read TODO.md file directly
|
|
3602
3642
|
let todoContent = '';
|
|
@@ -3642,7 +3682,10 @@ ${importResult.content[0].text}
|
|
|
3642
3682
|
includeRuleValidation,
|
|
3643
3683
|
deepCodeAnalysis,
|
|
3644
3684
|
functionalValidation,
|
|
3645
|
-
strictMode
|
|
3685
|
+
strictMode,
|
|
3686
|
+
environment: detectedEnvironment,
|
|
3687
|
+
environmentConfig: finalEnvironmentConfig,
|
|
3688
|
+
environmentValidation
|
|
3646
3689
|
});
|
|
3647
3690
|
return {
|
|
3648
3691
|
content: [
|
|
@@ -3657,11 +3700,101 @@ ${importResult.content[0].text}
|
|
|
3657
3700
|
throw new McpAdrError(`Failed to compare ADR progress: ${error instanceof Error ? error.message : String(error)}`, 'VALIDATION_ERROR');
|
|
3658
3701
|
}
|
|
3659
3702
|
}
|
|
3703
|
+
/**
|
|
3704
|
+
* Detect and validate environment context
|
|
3705
|
+
*/
|
|
3706
|
+
async detectAndValidateEnvironment(projectPath, environment, environmentConfig) {
|
|
3707
|
+
const path = await import('path');
|
|
3708
|
+
const fs = await import('fs/promises');
|
|
3709
|
+
let detectedEnvironment = environment;
|
|
3710
|
+
let finalConfig = { ...environmentConfig };
|
|
3711
|
+
if (environment === 'auto-detect') {
|
|
3712
|
+
// Auto-detect environment based on project structure
|
|
3713
|
+
try {
|
|
3714
|
+
// Check for environment indicator files
|
|
3715
|
+
const envFiles = [
|
|
3716
|
+
'.env.development',
|
|
3717
|
+
'.env.staging',
|
|
3718
|
+
'.env.production',
|
|
3719
|
+
'.env.test',
|
|
3720
|
+
'package.json',
|
|
3721
|
+
'docker-compose.yml',
|
|
3722
|
+
'Dockerfile'
|
|
3723
|
+
];
|
|
3724
|
+
const existingFiles = [];
|
|
3725
|
+
for (const file of envFiles) {
|
|
3726
|
+
try {
|
|
3727
|
+
await fs.access(path.join(projectPath, file));
|
|
3728
|
+
existingFiles.push(file);
|
|
3729
|
+
}
|
|
3730
|
+
catch {
|
|
3731
|
+
// File doesn't exist, continue
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
// Environment detection logic
|
|
3735
|
+
if (existingFiles.includes('.env.production') || existingFiles.includes('Dockerfile')) {
|
|
3736
|
+
detectedEnvironment = 'production';
|
|
3737
|
+
}
|
|
3738
|
+
else if (existingFiles.includes('.env.staging')) {
|
|
3739
|
+
detectedEnvironment = 'staging';
|
|
3740
|
+
}
|
|
3741
|
+
else if (existingFiles.includes('.env.test')) {
|
|
3742
|
+
detectedEnvironment = 'testing';
|
|
3743
|
+
}
|
|
3744
|
+
else {
|
|
3745
|
+
detectedEnvironment = 'development';
|
|
3746
|
+
}
|
|
3747
|
+
// Set environment-specific default configurations
|
|
3748
|
+
switch (detectedEnvironment) {
|
|
3749
|
+
case 'production':
|
|
3750
|
+
finalConfig = {
|
|
3751
|
+
securityLevel: 'critical',
|
|
3752
|
+
requiredFiles: ['package.json', 'README.md'],
|
|
3753
|
+
requiredServices: ['monitoring', 'logging'],
|
|
3754
|
+
performanceRequirements: { minUptime: 99.9 },
|
|
3755
|
+
...finalConfig
|
|
3756
|
+
};
|
|
3757
|
+
break;
|
|
3758
|
+
case 'staging':
|
|
3759
|
+
finalConfig = {
|
|
3760
|
+
securityLevel: 'high',
|
|
3761
|
+
requiredFiles: ['package.json'],
|
|
3762
|
+
requiredServices: ['testing', 'monitoring'],
|
|
3763
|
+
performanceRequirements: { minUptime: 95 },
|
|
3764
|
+
...finalConfig
|
|
3765
|
+
};
|
|
3766
|
+
break;
|
|
3767
|
+
case 'testing':
|
|
3768
|
+
finalConfig = {
|
|
3769
|
+
securityLevel: 'medium',
|
|
3770
|
+
requiredFiles: ['package.json'],
|
|
3771
|
+
requiredServices: ['testing'],
|
|
3772
|
+
performanceRequirements: {},
|
|
3773
|
+
...finalConfig
|
|
3774
|
+
};
|
|
3775
|
+
break;
|
|
3776
|
+
default: // development
|
|
3777
|
+
finalConfig = {
|
|
3778
|
+
securityLevel: 'medium',
|
|
3779
|
+
requiredFiles: ['package.json'],
|
|
3780
|
+
requiredServices: [],
|
|
3781
|
+
performanceRequirements: {},
|
|
3782
|
+
...finalConfig
|
|
3783
|
+
};
|
|
3784
|
+
}
|
|
3785
|
+
}
|
|
3786
|
+
catch (error) {
|
|
3787
|
+
this.logger.warn(`Environment auto-detection failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3788
|
+
detectedEnvironment = 'development'; // fallback
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
return { detectedEnvironment, environmentConfig: finalConfig };
|
|
3792
|
+
}
|
|
3660
3793
|
/**
|
|
3661
3794
|
* Perform local ADR progress analysis without relying on AI execution
|
|
3662
3795
|
*/
|
|
3663
3796
|
async performLocalAdrProgressAnalysis(params) {
|
|
3664
|
-
const { todoContent, todoPath, discoveredAdrs, adrDirectory, projectStructure, projectPath, validationType, includeFileChecks, includeRuleValidation, deepCodeAnalysis, functionalValidation, strictMode } = params;
|
|
3797
|
+
const { todoContent, todoPath, discoveredAdrs, adrDirectory, projectStructure, projectPath, validationType, includeFileChecks, includeRuleValidation, deepCodeAnalysis, functionalValidation, strictMode, environment, environmentConfig, environmentValidation } = params;
|
|
3665
3798
|
const currentDate = new Date().toISOString().split('T')[0];
|
|
3666
3799
|
// Parse TODO content to extract tasks
|
|
3667
3800
|
const todoTasks = this.parseTodoTasks(todoContent);
|
|
@@ -3669,15 +3802,25 @@ ${importResult.content[0].text}
|
|
|
3669
3802
|
const totalAdrs = discoveredAdrs.length;
|
|
3670
3803
|
const totalTasks = todoTasks.length;
|
|
3671
3804
|
const completedTasks = todoTasks.filter(task => task.completed).length;
|
|
3672
|
-
// Calculate alignment score (simplified)
|
|
3673
|
-
const adrTaskMapping = this.mapTasksToAdrs(todoTasks, discoveredAdrs);
|
|
3805
|
+
// Calculate alignment score (simplified, now environment-aware)
|
|
3806
|
+
const adrTaskMapping = this.mapTasksToAdrs(todoTasks, discoveredAdrs, environment, environmentConfig);
|
|
3674
3807
|
const alignedTasks = adrTaskMapping.aligned.length;
|
|
3675
|
-
|
|
3808
|
+
let alignmentScore = totalTasks > 0 ? Math.round((alignedTasks / totalTasks) * 100) : 0;
|
|
3809
|
+
// Environment-aware scoring adjustments
|
|
3810
|
+
if (environmentValidation && environmentConfig) {
|
|
3811
|
+
const envScore = this.calculateEnvironmentScore(projectStructure, environment, environmentConfig);
|
|
3812
|
+
alignmentScore = Math.round((alignmentScore + envScore) / 2); // Blend scores
|
|
3813
|
+
}
|
|
3676
3814
|
// File existence checks
|
|
3677
3815
|
let fileCheckResults = '';
|
|
3678
3816
|
if (includeFileChecks && projectStructure) {
|
|
3679
3817
|
fileCheckResults = this.performFileExistenceChecks(todoTasks, projectStructure);
|
|
3680
3818
|
}
|
|
3819
|
+
// Environment compliance checks
|
|
3820
|
+
let environmentAnalysisResults = '';
|
|
3821
|
+
if (environmentValidation && environmentConfig) {
|
|
3822
|
+
environmentAnalysisResults = this.performEnvironmentComplianceAnalysis(projectStructure, environment, environmentConfig, strictMode);
|
|
3823
|
+
}
|
|
3681
3824
|
// Mock vs Production analysis
|
|
3682
3825
|
let mockAnalysisResults = '';
|
|
3683
3826
|
if (deepCodeAnalysis && projectStructure) {
|
|
@@ -3690,6 +3833,7 @@ ${importResult.content[0].text}
|
|
|
3690
3833
|
**Project Path**: ${projectPath}
|
|
3691
3834
|
**TODO Path**: ${todoPath}
|
|
3692
3835
|
**ADR Directory**: ${adrDirectory}
|
|
3836
|
+
**Environment**: ${environment}${environmentValidation ? ` (validation enabled)` : ''}
|
|
3693
3837
|
|
|
3694
3838
|
## Summary
|
|
3695
3839
|
- **Total ADRs**: ${totalAdrs}
|
|
@@ -3697,6 +3841,7 @@ ${importResult.content[0].text}
|
|
|
3697
3841
|
- **Completed Tasks**: ${completedTasks}
|
|
3698
3842
|
- **Alignment Score**: ${alignmentScore}%
|
|
3699
3843
|
- **Compliance Score**: ${Math.max(alignmentScore - 10, 0)}%
|
|
3844
|
+
- **Environment**: ${environment}
|
|
3700
3845
|
|
|
3701
3846
|
## Configuration
|
|
3702
3847
|
- **File Checks**: ${includeFileChecks ? 'Enabled' : 'Disabled'}
|
|
@@ -3704,6 +3849,13 @@ ${importResult.content[0].text}
|
|
|
3704
3849
|
- **Deep Code Analysis**: ${deepCodeAnalysis ? 'Enabled' : 'Disabled'}
|
|
3705
3850
|
- **Functional Validation**: ${functionalValidation ? 'Enabled' : 'Disabled'}
|
|
3706
3851
|
- **Strict Mode**: ${strictMode ? 'Enabled - High scrutiny for mock vs production' : 'Disabled'}
|
|
3852
|
+
- **Environment Validation**: ${environmentValidation ? 'Enabled' : 'Disabled'}
|
|
3853
|
+
|
|
3854
|
+
## Environment Context
|
|
3855
|
+
- **Target Environment**: ${environment}
|
|
3856
|
+
- **Security Level**: ${environmentConfig.securityLevel || 'Not specified'}
|
|
3857
|
+
- **Required Files**: ${environmentConfig.requiredFiles?.length || 0} files
|
|
3858
|
+
- **Required Services**: ${environmentConfig.requiredServices?.length || 0} services
|
|
3707
3859
|
|
|
3708
3860
|
## ADR Discovery Results
|
|
3709
3861
|
${totalAdrs > 0 ?
|
|
@@ -3736,6 +3888,8 @@ ${adrTaskMapping.missing.length > 0 ?
|
|
|
3736
3888
|
|
|
3737
3889
|
${fileCheckResults || '### File Existence Validation\n- File checks disabled or no project structure available'}
|
|
3738
3890
|
|
|
3891
|
+
${environmentAnalysisResults || ''}
|
|
3892
|
+
|
|
3739
3893
|
${mockAnalysisResults || ''}
|
|
3740
3894
|
|
|
3741
3895
|
## Recommendations
|
|
@@ -3746,10 +3900,14 @@ ${alignmentScore < 70 ?
|
|
|
3746
3900
|
'1. **Maintain Current Alignment**: Continue following ADR specifications'}
|
|
3747
3901
|
${completedTasks < totalTasks * 0.5 ?
|
|
3748
3902
|
'\n3. **Accelerate Implementation**: Focus on completing pending tasks' : ''}
|
|
3903
|
+
${environmentValidation && environment === 'production' && alignmentScore < 90 ?
|
|
3904
|
+
'\n4. **⚠️ Production Environment Warning**: Current alignment may not meet production requirements' : ''}
|
|
3749
3905
|
|
|
3750
3906
|
### Medium Priority Actions
|
|
3751
3907
|
1. **Review Implementation Quality**: ${strictMode ? 'Strict mode analysis above shows' : 'Consider enabling strict mode for'} detailed quality assessment
|
|
3752
3908
|
2. **Update Documentation**: Ensure TODO.md reflects current project state
|
|
3909
|
+
${environmentValidation ?
|
|
3910
|
+
`3. **Environment Compliance**: Ensure ${environment} environment requirements are met` : ''}
|
|
3753
3911
|
|
|
3754
3912
|
### Low Priority Actions
|
|
3755
3913
|
1. **Optimize Workflow**: Consider tools for automated ADR-TODO synchronization
|
|
@@ -3825,9 +3983,9 @@ To re-run this validation with strict mode:
|
|
|
3825
3983
|
return tasks;
|
|
3826
3984
|
}
|
|
3827
3985
|
/**
|
|
3828
|
-
* Map TODO tasks to ADRs to identify alignment
|
|
3986
|
+
* Map TODO tasks to ADRs to identify alignment (now environment-aware)
|
|
3829
3987
|
*/
|
|
3830
|
-
mapTasksToAdrs(tasks, adrs) {
|
|
3988
|
+
mapTasksToAdrs(tasks, adrs, environment, environmentConfig) {
|
|
3831
3989
|
const aligned = [];
|
|
3832
3990
|
const misaligned = [];
|
|
3833
3991
|
const missing = [];
|
|
@@ -3837,10 +3995,25 @@ To re-run this validation with strict mode:
|
|
|
3837
3995
|
...(adr.decision || '').toLowerCase().split(/\s+/).filter((w) => w.length > 4),
|
|
3838
3996
|
...(adr.context || '').toLowerCase().split(/\s+/).filter((w) => w.length > 4)
|
|
3839
3997
|
]);
|
|
3998
|
+
// Environment-specific keywords that should be prioritized
|
|
3999
|
+
const envKeywords = [];
|
|
4000
|
+
if (environment && environmentConfig) {
|
|
4001
|
+
if (environment === 'production') {
|
|
4002
|
+
envKeywords.push('deploy', 'production', 'monitoring', 'security', 'performance');
|
|
4003
|
+
}
|
|
4004
|
+
else if (environment === 'staging') {
|
|
4005
|
+
envKeywords.push('test', 'staging', 'integration', 'validation');
|
|
4006
|
+
}
|
|
4007
|
+
else if (environment === 'development') {
|
|
4008
|
+
envKeywords.push('setup', 'development', 'local', 'debug');
|
|
4009
|
+
}
|
|
4010
|
+
}
|
|
3840
4011
|
for (const task of tasks) {
|
|
3841
4012
|
const taskLower = task.title.toLowerCase();
|
|
3842
4013
|
const hasKeywordMatch = adrKeywords.some(keyword => taskLower.includes(keyword) || keyword.includes(taskLower.split(' ')[0]));
|
|
3843
|
-
|
|
4014
|
+
// Environment-aware alignment scoring
|
|
4015
|
+
const hasEnvKeywordMatch = envKeywords.some(keyword => taskLower.includes(keyword));
|
|
4016
|
+
if (hasKeywordMatch || hasEnvKeywordMatch) {
|
|
3844
4017
|
aligned.push(task);
|
|
3845
4018
|
}
|
|
3846
4019
|
else {
|
|
@@ -3860,6 +4033,25 @@ To re-run this validation with strict mode:
|
|
|
3860
4033
|
}
|
|
3861
4034
|
}
|
|
3862
4035
|
}
|
|
4036
|
+
// Environment-specific missing tasks
|
|
4037
|
+
if (environment && environmentConfig) {
|
|
4038
|
+
if (environmentConfig.requiredFiles) {
|
|
4039
|
+
for (const file of environmentConfig.requiredFiles) {
|
|
4040
|
+
const hasFileTask = tasks.some(task => task.title.toLowerCase().includes(file.toLowerCase()));
|
|
4041
|
+
if (!hasFileTask) {
|
|
4042
|
+
missing.push(`Create ${file} for ${environment} environment`);
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
}
|
|
4046
|
+
if (environmentConfig.requiredServices) {
|
|
4047
|
+
for (const service of environmentConfig.requiredServices) {
|
|
4048
|
+
const hasServiceTask = tasks.some(task => task.title.toLowerCase().includes(service.toLowerCase()));
|
|
4049
|
+
if (!hasServiceTask) {
|
|
4050
|
+
missing.push(`Setup ${service} service for ${environment}`);
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
}
|
|
3863
4055
|
return { aligned, misaligned, missing };
|
|
3864
4056
|
}
|
|
3865
4057
|
/**
|
|
@@ -3971,6 +4163,122 @@ To re-run this validation with strict mode:
|
|
|
3971
4163
|
}
|
|
3972
4164
|
return results;
|
|
3973
4165
|
}
|
|
4166
|
+
/**
|
|
4167
|
+
* Calculate environment-specific compliance score
|
|
4168
|
+
*/
|
|
4169
|
+
calculateEnvironmentScore(projectStructure, environment, environmentConfig) {
|
|
4170
|
+
if (!projectStructure || !environmentConfig)
|
|
4171
|
+
return 0;
|
|
4172
|
+
let score = 100; // Start with perfect score
|
|
4173
|
+
// Check required files
|
|
4174
|
+
if (environmentConfig.requiredFiles) {
|
|
4175
|
+
const allFiles = [
|
|
4176
|
+
...projectStructure.packageFiles || [],
|
|
4177
|
+
...projectStructure.configFiles || [],
|
|
4178
|
+
...projectStructure.buildFiles || [],
|
|
4179
|
+
...projectStructure.dockerFiles || [],
|
|
4180
|
+
...projectStructure.ciFiles || [],
|
|
4181
|
+
...projectStructure.scriptFiles || []
|
|
4182
|
+
];
|
|
4183
|
+
const existingFiles = allFiles.map(f => f.filename);
|
|
4184
|
+
const missingFiles = environmentConfig.requiredFiles.filter((file) => !existingFiles.includes(file));
|
|
4185
|
+
// Deduct 10 points per missing required file
|
|
4186
|
+
score -= missingFiles.length * 10;
|
|
4187
|
+
}
|
|
4188
|
+
// Environment-specific penalties
|
|
4189
|
+
if (environment === 'production') {
|
|
4190
|
+
// Production requires higher standards
|
|
4191
|
+
if (!projectStructure.dockerFiles?.length)
|
|
4192
|
+
score -= 15;
|
|
4193
|
+
if (!projectStructure.ciFiles?.length)
|
|
4194
|
+
score -= 10;
|
|
4195
|
+
}
|
|
4196
|
+
return Math.max(score, 0);
|
|
4197
|
+
}
|
|
4198
|
+
/**
|
|
4199
|
+
* Perform environment compliance analysis
|
|
4200
|
+
*/
|
|
4201
|
+
performEnvironmentComplianceAnalysis(projectStructure, environment, environmentConfig, strictMode) {
|
|
4202
|
+
if (!projectStructure || !environmentConfig) {
|
|
4203
|
+
return '\n### Environment Compliance Analysis\n- Environment analysis disabled or no project structure available\n';
|
|
4204
|
+
}
|
|
4205
|
+
let results = '\n### Environment Compliance Analysis\n';
|
|
4206
|
+
// Required files analysis
|
|
4207
|
+
if (environmentConfig.requiredFiles) {
|
|
4208
|
+
results += `#### Required Files for ${environment} Environment\n`;
|
|
4209
|
+
const allFiles = [
|
|
4210
|
+
...projectStructure.packageFiles || [],
|
|
4211
|
+
...projectStructure.configFiles || [],
|
|
4212
|
+
...projectStructure.buildFiles || [],
|
|
4213
|
+
...projectStructure.dockerFiles || [],
|
|
4214
|
+
...projectStructure.ciFiles || [],
|
|
4215
|
+
...projectStructure.scriptFiles || []
|
|
4216
|
+
];
|
|
4217
|
+
const existingFiles = allFiles.map(f => f.filename);
|
|
4218
|
+
for (const requiredFile of environmentConfig.requiredFiles) {
|
|
4219
|
+
const exists = existingFiles.includes(requiredFile);
|
|
4220
|
+
results += `- ${exists ? '✅' : '❌'} **${requiredFile}**: ${exists ? 'Found' : 'Missing'}\n`;
|
|
4221
|
+
}
|
|
4222
|
+
}
|
|
4223
|
+
// Security level compliance
|
|
4224
|
+
if (environmentConfig.securityLevel) {
|
|
4225
|
+
results += `\n#### Security Level: ${environmentConfig.securityLevel}\n`;
|
|
4226
|
+
const securityIndicators = this.analyzeSecurityCompliance(projectStructure, environmentConfig.securityLevel);
|
|
4227
|
+
results += securityIndicators;
|
|
4228
|
+
}
|
|
4229
|
+
// Environment-specific recommendations
|
|
4230
|
+
results += `\n#### ${environment} Environment Recommendations\n`;
|
|
4231
|
+
switch (environment) {
|
|
4232
|
+
case 'production':
|
|
4233
|
+
results += '- ⚠️ **Production Critical**: Ensure monitoring, logging, and backup strategies are implemented\n';
|
|
4234
|
+
results += '- 🔒 **Security**: Implement comprehensive security measures\n';
|
|
4235
|
+
results += '- 📊 **Performance**: Monitor and optimize for production workloads\n';
|
|
4236
|
+
if (strictMode) {
|
|
4237
|
+
results += '- 🔍 **Strict Mode**: Enhanced validation enabled for production environment\n';
|
|
4238
|
+
}
|
|
4239
|
+
break;
|
|
4240
|
+
case 'staging':
|
|
4241
|
+
results += '- 🧪 **Testing**: Ensure comprehensive test coverage and validation\n';
|
|
4242
|
+
results += '- 📋 **Validation**: Implement environment parity checks\n';
|
|
4243
|
+
break;
|
|
4244
|
+
case 'development':
|
|
4245
|
+
results += '- 🛠️ **Development**: Focus on developer experience and debugging tools\n';
|
|
4246
|
+
results += '- 🔄 **Iteration**: Ensure fast feedback loops\n';
|
|
4247
|
+
break;
|
|
4248
|
+
}
|
|
4249
|
+
return results;
|
|
4250
|
+
}
|
|
4251
|
+
/**
|
|
4252
|
+
* Analyze security compliance based on security level
|
|
4253
|
+
*/
|
|
4254
|
+
analyzeSecurityCompliance(projectStructure, securityLevel) {
|
|
4255
|
+
let results = '';
|
|
4256
|
+
const securityFiles = [
|
|
4257
|
+
...projectStructure.configFiles || [],
|
|
4258
|
+
...projectStructure.dockerFiles || []
|
|
4259
|
+
].filter(file => file.filename.includes('security') ||
|
|
4260
|
+
file.filename.includes('auth') ||
|
|
4261
|
+
file.filename.includes('.env') ||
|
|
4262
|
+
file.filename === 'Dockerfile');
|
|
4263
|
+
const hasSecurityConfig = securityFiles.length > 0;
|
|
4264
|
+
switch (securityLevel) {
|
|
4265
|
+
case 'critical':
|
|
4266
|
+
results += `- ${hasSecurityConfig ? '✅' : '❌'} **Critical Security**: ${hasSecurityConfig ? 'Security configuration found' : 'No security configuration detected'}\n`;
|
|
4267
|
+
if (!hasSecurityConfig) {
|
|
4268
|
+
results += ' - **Action Required**: Implement comprehensive security measures\n';
|
|
4269
|
+
}
|
|
4270
|
+
break;
|
|
4271
|
+
case 'high':
|
|
4272
|
+
results += `- ${hasSecurityConfig ? '✅' : '⚠️'} **High Security**: ${hasSecurityConfig ? 'Some security configuration found' : 'Limited security configuration'}\n`;
|
|
4273
|
+
break;
|
|
4274
|
+
case 'medium':
|
|
4275
|
+
results += `- ℹ️ **Medium Security**: Basic security measures recommended\n`;
|
|
4276
|
+
break;
|
|
4277
|
+
default:
|
|
4278
|
+
results += `- ℹ️ **Security Level**: ${securityLevel} (consider increasing for production)\n`;
|
|
4279
|
+
}
|
|
4280
|
+
return results;
|
|
4281
|
+
}
|
|
3974
4282
|
/**
|
|
3975
4283
|
* Content masking tool implementations
|
|
3976
4284
|
*/
|
|
@@ -4833,4 +5141,5 @@ if (process.argv[1] && (process.argv[1].endsWith('index.js') ||
|
|
|
4833
5141
|
process.exit(1);
|
|
4834
5142
|
});
|
|
4835
5143
|
}
|
|
5144
|
+
// Test comment for pre-commit hook
|
|
4836
5145
|
//# sourceMappingURL=index.js.map
|