mcp-adr-analysis-server 2.0.21 → 2.1.0
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 +94 -839
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/config/ai-config.d.ts.map +1 -1
- package/dist/src/config/ai-config.js +9 -9
- package/dist/src/config/ai-config.js.map +1 -1
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1594 -837
- package/dist/src/index.js.map +1 -1
- package/dist/src/prompts/analysis-prompts.d.ts +4 -1
- package/dist/src/prompts/analysis-prompts.d.ts.map +1 -1
- package/dist/src/prompts/analysis-prompts.js +61 -30
- package/dist/src/prompts/analysis-prompts.js.map +1 -1
- package/dist/src/prompts/index.d.ts +17 -1
- package/dist/src/prompts/index.d.ts.map +1 -1
- package/dist/src/prompts/index.js +325 -1
- package/dist/src/prompts/index.js.map +1 -1
- package/dist/src/prompts/rule-generation-prompts.d.ts +5 -1
- package/dist/src/prompts/rule-generation-prompts.d.ts.map +1 -1
- package/dist/src/prompts/rule-generation-prompts.js +5 -1
- package/dist/src/prompts/rule-generation-prompts.js.map +1 -1
- package/dist/src/prompts/security-prompts.d.ts +6 -1
- package/dist/src/prompts/security-prompts.d.ts.map +1 -1
- package/dist/src/prompts/security-prompts.js +6 -1
- package/dist/src/prompts/security-prompts.js.map +1 -1
- package/dist/src/prompts/todo-prompts.d.ts +49 -0
- package/dist/src/prompts/todo-prompts.d.ts.map +1 -0
- package/dist/src/prompts/todo-prompts.js +824 -0
- package/dist/src/prompts/todo-prompts.js.map +1 -0
- package/dist/src/resources/index.d.ts.map +1 -1
- package/dist/src/resources/index.js +9 -7
- package/dist/src/resources/index.js.map +1 -1
- package/dist/src/tools/adr-bootstrap-validation-tool.d.ts +47 -0
- package/dist/src/tools/adr-bootstrap-validation-tool.d.ts.map +1 -0
- package/dist/src/tools/adr-bootstrap-validation-tool.js +979 -0
- package/dist/src/tools/adr-bootstrap-validation-tool.js.map +1 -0
- package/dist/src/tools/adr-suggestion-tool.d.ts +1 -0
- package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -1
- package/dist/src/tools/adr-suggestion-tool.js +330 -32
- package/dist/src/tools/adr-suggestion-tool.js.map +1 -1
- package/dist/src/tools/content-masking-tool.d.ts +5 -0
- package/dist/src/tools/content-masking-tool.d.ts.map +1 -1
- package/dist/src/tools/content-masking-tool.js +631 -28
- package/dist/src/tools/content-masking-tool.js.map +1 -1
- package/dist/src/tools/deployment-readiness-tool.d.ts +8 -5
- package/dist/src/tools/deployment-readiness-tool.d.ts.map +1 -1
- package/dist/src/tools/deployment-readiness-tool.js +1017 -93
- package/dist/src/tools/deployment-readiness-tool.js.map +1 -1
- package/dist/src/tools/environment-analysis-tool.d.ts +4 -0
- package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -1
- package/dist/src/tools/environment-analysis-tool.js +568 -24
- package/dist/src/tools/environment-analysis-tool.js.map +1 -1
- package/dist/src/tools/interactive-adr-planning-tool.d.ts.map +1 -1
- package/dist/src/tools/interactive-adr-planning-tool.js +270 -108
- package/dist/src/tools/interactive-adr-planning-tool.js.map +1 -1
- package/dist/src/tools/mcp-planning-tool.d.ts.map +1 -1
- package/dist/src/tools/mcp-planning-tool.js +316 -183
- package/dist/src/tools/mcp-planning-tool.js.map +1 -1
- package/dist/src/tools/memory-loading-tool.d.ts +60 -0
- package/dist/src/tools/memory-loading-tool.d.ts.map +1 -0
- package/dist/src/tools/memory-loading-tool.js +457 -0
- package/dist/src/tools/memory-loading-tool.js.map +1 -0
- package/dist/src/tools/research-integration-tool.d.ts +4 -1
- package/dist/src/tools/research-integration-tool.d.ts.map +1 -1
- package/dist/src/tools/research-integration-tool.js +5 -1
- package/dist/src/tools/research-integration-tool.js.map +1 -1
- package/dist/src/tools/review-existing-adrs-tool.d.ts +19 -0
- package/dist/src/tools/review-existing-adrs-tool.d.ts.map +1 -0
- package/dist/src/tools/review-existing-adrs-tool.js +1204 -0
- package/dist/src/tools/review-existing-adrs-tool.js.map +1 -0
- package/dist/src/tools/rule-generation-tool.d.ts +2 -0
- package/dist/src/tools/rule-generation-tool.d.ts.map +1 -1
- package/dist/src/tools/rule-generation-tool.js +274 -33
- package/dist/src/tools/rule-generation-tool.js.map +1 -1
- package/dist/src/tools/smart-git-push-tool-v2.d.ts +4 -0
- package/dist/src/tools/smart-git-push-tool-v2.d.ts.map +1 -1
- package/dist/src/tools/smart-git-push-tool-v2.js +423 -229
- package/dist/src/tools/smart-git-push-tool-v2.js.map +1 -1
- package/dist/src/tools/smart-git-push-tool.d.ts +3 -0
- package/dist/src/tools/smart-git-push-tool.d.ts.map +1 -1
- package/dist/src/tools/smart-git-push-tool.js +241 -235
- package/dist/src/tools/smart-git-push-tool.js.map +1 -1
- package/dist/src/tools/tool-chain-orchestrator.d.ts +2 -2
- package/dist/src/tools/tool-chain-orchestrator.d.ts.map +1 -1
- package/dist/src/tools/tool-chain-orchestrator.js +152 -93
- package/dist/src/tools/tool-chain-orchestrator.js.map +1 -1
- package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts +22 -13
- package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts.map +1 -1
- package/dist/src/tools/troubleshoot-guided-workflow-tool.js +660 -28
- package/dist/src/tools/troubleshoot-guided-workflow-tool.js.map +1 -1
- package/dist/src/types/ape-framework.d.ts +93 -0
- package/dist/src/types/ape-framework.d.ts.map +1 -1
- package/dist/src/types/ape-framework.js +10 -10
- package/dist/src/types/ape-framework.js.map +1 -1
- package/dist/src/types/enhanced-errors.d.ts +173 -0
- package/dist/src/types/enhanced-errors.d.ts.map +1 -0
- package/dist/src/types/enhanced-errors.js +668 -0
- package/dist/src/types/enhanced-errors.js.map +1 -0
- package/dist/src/types/index.d.ts +129 -3
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +15 -0
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/knowledge-generation.d.ts +78 -0
- package/dist/src/types/knowledge-generation.d.ts.map +1 -1
- package/dist/src/types/knowledge-generation.js +10 -6
- package/dist/src/types/knowledge-generation.js.map +1 -1
- package/dist/src/types/knowledge-graph-schemas.d.ts +92 -0
- package/dist/src/types/knowledge-graph-schemas.d.ts.map +1 -1
- package/dist/src/types/knowledge-graph-schemas.js +45 -17
- package/dist/src/types/knowledge-graph-schemas.js.map +1 -1
- package/dist/src/types/memory-entities.d.ts +7209 -0
- package/dist/src/types/memory-entities.d.ts.map +1 -0
- package/dist/src/types/memory-entities.js +395 -0
- package/dist/src/types/memory-entities.js.map +1 -0
- package/dist/src/types/reflexion-framework.d.ts +44 -0
- package/dist/src/types/reflexion-framework.d.ts.map +1 -1
- package/dist/src/types/reflexion-framework.js +7 -7
- package/dist/src/types/reflexion-framework.js.map +1 -1
- package/dist/src/types/todo-json-schemas.d.ts +7 -653
- package/dist/src/types/todo-json-schemas.d.ts.map +1 -1
- package/dist/src/types/todo-json-schemas.js +6 -110
- package/dist/src/types/todo-json-schemas.js.map +1 -1
- package/dist/src/types/tool-arguments.d.ts +224 -0
- package/dist/src/types/tool-arguments.d.ts.map +1 -0
- package/dist/src/types/tool-arguments.js +6 -0
- package/dist/src/types/tool-arguments.js.map +1 -0
- package/dist/src/utils/actual-file-operations.d.ts.map +1 -1
- package/dist/src/utils/actual-file-operations.js +25 -9
- package/dist/src/utils/actual-file-operations.js.map +1 -1
- package/dist/src/utils/adr-discovery.d.ts +33 -1
- package/dist/src/utils/adr-discovery.d.ts.map +1 -1
- package/dist/src/utils/adr-discovery.js +14 -9
- package/dist/src/utils/adr-discovery.js.map +1 -1
- package/dist/src/utils/adr-suggestions.d.ts +72 -0
- package/dist/src/utils/adr-suggestions.d.ts.map +1 -1
- package/dist/src/utils/adr-suggestions.js +6 -0
- package/dist/src/utils/adr-suggestions.js.map +1 -1
- package/dist/src/utils/cache.d.ts.map +1 -1
- package/dist/src/utils/cache.js +22 -19
- package/dist/src/utils/cache.js.map +1 -1
- package/dist/src/utils/chain-of-thought-template.d.ts +13 -1
- package/dist/src/utils/chain-of-thought-template.d.ts.map +1 -1
- package/dist/src/utils/chain-of-thought-template.js +31 -22
- package/dist/src/utils/chain-of-thought-template.js.map +1 -1
- package/dist/src/utils/config.d.ts.map +1 -1
- package/dist/src/utils/config.js +1 -0
- package/dist/src/utils/config.js.map +1 -1
- package/dist/src/utils/directory-compat.js +1 -1
- package/dist/src/utils/directory-compat.js.map +1 -1
- package/dist/src/utils/enhanced-logging.d.ts +195 -0
- package/dist/src/utils/enhanced-logging.d.ts.map +1 -0
- package/dist/src/utils/enhanced-logging.js +449 -0
- package/dist/src/utils/enhanced-logging.js.map +1 -0
- package/dist/src/utils/file-system.d.ts +182 -34
- package/dist/src/utils/file-system.d.ts.map +1 -1
- package/dist/src/utils/file-system.js +648 -774
- package/dist/src/utils/file-system.js.map +1 -1
- package/dist/src/utils/gitleaks-detector.d.ts +50 -0
- package/dist/src/utils/gitleaks-detector.d.ts.map +1 -0
- package/dist/src/utils/gitleaks-detector.js +334 -0
- package/dist/src/utils/gitleaks-detector.js.map +1 -0
- package/dist/src/utils/interactive-approval.d.ts +1 -1
- package/dist/src/utils/interactive-approval.d.ts.map +1 -1
- package/dist/src/utils/interactive-approval.js +22 -17
- package/dist/src/utils/interactive-approval.js.map +1 -1
- package/dist/src/utils/json-safe.d.ts.map +1 -1
- package/dist/src/utils/json-safe.js +9 -6
- package/dist/src/utils/json-safe.js.map +1 -1
- package/dist/src/utils/knowledge-graph-manager.d.ts +37 -1
- package/dist/src/utils/knowledge-graph-manager.d.ts.map +1 -1
- package/dist/src/utils/knowledge-graph-manager.js +315 -70
- package/dist/src/utils/knowledge-graph-manager.js.map +1 -1
- package/dist/src/utils/location-filter.d.ts +35 -10
- package/dist/src/utils/location-filter.d.ts.map +1 -1
- package/dist/src/utils/location-filter.js +360 -94
- package/dist/src/utils/location-filter.js.map +1 -1
- package/dist/src/utils/mcp-response-validator.d.ts.map +1 -1
- package/dist/src/utils/mcp-response-validator.js +34 -19
- package/dist/src/utils/mcp-response-validator.js.map +1 -1
- package/dist/src/utils/memory-entity-manager.d.ts +134 -0
- package/dist/src/utils/memory-entity-manager.d.ts.map +1 -0
- package/dist/src/utils/memory-entity-manager.js +851 -0
- package/dist/src/utils/memory-entity-manager.js.map +1 -0
- package/dist/src/utils/memory-health-scoring.d.ts +125 -0
- package/dist/src/utils/memory-health-scoring.d.ts.map +1 -0
- package/dist/src/utils/memory-health-scoring.js +277 -0
- package/dist/src/utils/memory-health-scoring.js.map +1 -0
- package/dist/src/utils/memory-migration-manager.d.ts +93 -0
- package/dist/src/utils/memory-migration-manager.d.ts.map +1 -0
- package/dist/src/utils/memory-migration-manager.js +842 -0
- package/dist/src/utils/memory-migration-manager.js.map +1 -0
- package/dist/src/utils/memory-relationship-mapper.d.ts +87 -0
- package/dist/src/utils/memory-relationship-mapper.d.ts.map +1 -0
- package/dist/src/utils/memory-relationship-mapper.js +482 -0
- package/dist/src/utils/memory-relationship-mapper.js.map +1 -0
- package/dist/src/utils/memory-rollback-manager.d.ts +105 -0
- package/dist/src/utils/memory-rollback-manager.d.ts.map +1 -0
- package/dist/src/utils/memory-rollback-manager.js +575 -0
- package/dist/src/utils/memory-rollback-manager.js.map +1 -0
- package/dist/src/utils/memory-transformation.d.ts +59 -0
- package/dist/src/utils/memory-transformation.d.ts.map +1 -0
- package/dist/src/utils/memory-transformation.js +742 -0
- package/dist/src/utils/memory-transformation.js.map +1 -0
- package/dist/src/utils/output-masking.d.ts +12 -0
- package/dist/src/utils/output-masking.d.ts.map +1 -1
- package/dist/src/utils/output-masking.js +5 -0
- package/dist/src/utils/output-masking.js.map +1 -1
- package/dist/src/utils/prompt-execution.d.ts.map +1 -1
- package/dist/src/utils/prompt-execution.js +72 -51
- package/dist/src/utils/prompt-execution.js.map +1 -1
- package/dist/src/utils/release-readiness-detector.d.ts.map +1 -1
- package/dist/src/utils/release-readiness-detector.js +43 -42
- package/dist/src/utils/release-readiness-detector.js.map +1 -1
- package/dist/src/utils/research-integration.d.ts.map +1 -1
- package/dist/src/utils/research-integration.js +73 -44
- package/dist/src/utils/research-integration.js.map +1 -1
- package/dist/src/utils/research-questions.d.ts.map +1 -1
- package/dist/src/utils/research-questions.js +40 -14
- package/dist/src/utils/research-questions.js.map +1 -1
- package/dist/src/utils/ripgrep-wrapper.d.ts +84 -0
- package/dist/src/utils/ripgrep-wrapper.d.ts.map +1 -0
- package/dist/src/utils/ripgrep-wrapper.js +255 -0
- package/dist/src/utils/ripgrep-wrapper.js.map +1 -0
- package/dist/src/utils/rule-generation.d.ts.map +1 -1
- package/dist/src/utils/rule-generation.js +26 -15
- package/dist/src/utils/rule-generation.js.map +1 -1
- package/dist/src/utils/todo-file-watcher.d.ts +11 -23
- package/dist/src/utils/todo-file-watcher.d.ts.map +1 -1
- package/dist/src/utils/todo-file-watcher.js +18 -156
- package/dist/src/utils/todo-file-watcher.js.map +1 -1
- package/dist/src/utils/tree-sitter-analyzer.d.ts +185 -0
- package/dist/src/utils/tree-sitter-analyzer.d.ts.map +1 -0
- package/dist/src/utils/tree-sitter-analyzer.js +885 -0
- package/dist/src/utils/tree-sitter-analyzer.js.map +1 -0
- package/package.json +51 -10
- package/dist/src/tools/smart-score-tool.d.ts +0 -173
- package/dist/src/tools/smart-score-tool.d.ts.map +0 -1
- package/dist/src/tools/smart-score-tool.js +0 -681
- package/dist/src/tools/smart-score-tool.js.map +0 -1
- package/dist/src/tools/todo-management-tool-v2.d.ts +0 -368
- package/dist/src/tools/todo-management-tool-v2.d.ts.map +0 -1
- package/dist/src/tools/todo-management-tool-v2.js +0 -922
- package/dist/src/tools/todo-management-tool-v2.js.map +0 -1
- package/dist/src/utils/enhanced-sensitive-detector.d.ts +0 -61
- package/dist/src/utils/enhanced-sensitive-detector.d.ts.map +0 -1
- package/dist/src/utils/enhanced-sensitive-detector.js +0 -437
- package/dist/src/utils/enhanced-sensitive-detector.js.map +0 -1
- package/dist/src/utils/project-health-scoring.d.ts +0 -177
- package/dist/src/utils/project-health-scoring.d.ts.map +0 -1
- package/dist/src/utils/project-health-scoring.js +0 -370
- package/dist/src/utils/project-health-scoring.js.map +0 -1
- package/dist/src/utils/todo-json-manager.d.ts +0 -71
- package/dist/src/utils/todo-json-manager.d.ts.map +0 -1
- package/dist/src/utils/todo-json-manager.js +0 -396
- package/dist/src/utils/todo-json-manager.js.map +0 -1
- package/dist/src/utils/todo-markdown-converter.d.ts +0 -16
- package/dist/src/utils/todo-markdown-converter.d.ts.map +0 -1
- package/dist/src/utils/todo-markdown-converter.js +0 -362
- package/dist/src/utils/todo-markdown-converter.js.map +0 -1
- package/dist/src/utils/todo-migration.d.ts +0 -47
- package/dist/src/utils/todo-migration.d.ts.map +0 -1
- package/dist/src/utils/todo-migration.js +0 -261
- package/dist/src/utils/todo-migration.js.map +0 -1
|
@@ -1,56 +1,87 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Deployment Readiness Tool - Version
|
|
2
|
+
* Deployment Readiness Tool - Version 2.0
|
|
3
3
|
*
|
|
4
4
|
* Comprehensive deployment validation with test failure tracking, deployment history analysis,
|
|
5
5
|
* and hard blocking integration with smart git push.
|
|
6
|
+
* Enhanced with memory integration for deployment assessment tracking and pattern recognition.
|
|
6
7
|
*
|
|
7
8
|
* IMPORTANT FOR AI ASSISTANTS: This tool provides:
|
|
8
9
|
* 1. Test Execution Validation: Zero tolerance for test failures
|
|
9
10
|
* 2. Deployment History Analysis: Pattern detection and success rate tracking
|
|
10
11
|
* 3. Code Quality Gates: Mock vs production code detection
|
|
11
12
|
* 4. Hard Blocking: Prevents unsafe deployments via smart git push integration
|
|
13
|
+
* 5. Memory Integration: Stores deployment assessments as memory entities
|
|
12
14
|
*
|
|
13
|
-
*
|
|
14
|
-
* - CREATES
|
|
15
|
-
* -
|
|
15
|
+
* Memory Dependencies:
|
|
16
|
+
* - CREATES: deployment_assessment memory entities
|
|
17
|
+
* - MIGRATES: Existing deployment history to memory entities
|
|
18
|
+
* - ANALYZES: Deployment patterns across memory entities
|
|
16
19
|
* - INTEGRATES: smart-git-push-tool for deployment blocking
|
|
17
|
-
* - INTEGRATES: todo-
|
|
20
|
+
* - INTEGRATES: todo-file-watcher for automatic task creation
|
|
18
21
|
*/
|
|
19
22
|
import { z } from 'zod';
|
|
20
23
|
import { McpAdrError } from '../types/index.js';
|
|
21
24
|
import { execSync } from 'child_process';
|
|
22
25
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
23
|
-
import { join } from 'path';
|
|
26
|
+
import { join, basename } from 'path';
|
|
27
|
+
import * as os from 'os';
|
|
24
28
|
import { validateMcpResponse } from '../utils/mcp-response-validator.js';
|
|
25
29
|
import { jsonSafeError } from '../utils/json-safe.js';
|
|
30
|
+
import { MemoryEntityManager } from '../utils/memory-entity-manager.js';
|
|
31
|
+
import { EnhancedLogger } from '../utils/enhanced-logging.js';
|
|
32
|
+
import { TreeSitterAnalyzer } from '../utils/tree-sitter-analyzer.js';
|
|
33
|
+
import { findFiles, findRelatedCode } from '../utils/file-system.js';
|
|
26
34
|
// Core schemas
|
|
27
35
|
const DeploymentReadinessSchema = z.object({
|
|
28
|
-
operation: z
|
|
36
|
+
operation: z
|
|
37
|
+
.enum([
|
|
29
38
|
'check_readiness', // Full deployment readiness check
|
|
30
39
|
'validate_production', // Production-specific validation
|
|
31
40
|
'test_validation', // Test execution and failure analysis
|
|
32
41
|
'deployment_history', // Deployment history analysis
|
|
33
42
|
'full_audit', // Comprehensive audit (all checks)
|
|
34
|
-
'emergency_override' // Emergency bypass with justification
|
|
35
|
-
])
|
|
43
|
+
'emergency_override', // Emergency bypass with justification
|
|
44
|
+
])
|
|
45
|
+
.describe('Operation to perform'),
|
|
36
46
|
// Core Configuration
|
|
37
47
|
projectPath: z.string().optional().describe('Project root path'),
|
|
38
|
-
targetEnvironment: z
|
|
48
|
+
targetEnvironment: z
|
|
49
|
+
.enum(['staging', 'production', 'integration'])
|
|
50
|
+
.default('production')
|
|
51
|
+
.describe('Target deployment environment'),
|
|
39
52
|
strictMode: z.boolean().default(true).describe('Enable strict validation (recommended)'),
|
|
40
53
|
// Code Quality Gates
|
|
41
|
-
allowMockCode: z
|
|
42
|
-
|
|
54
|
+
allowMockCode: z
|
|
55
|
+
.boolean()
|
|
56
|
+
.default(false)
|
|
57
|
+
.describe('Allow mock code in deployment (NOT RECOMMENDED)'),
|
|
58
|
+
productionCodeThreshold: z
|
|
59
|
+
.number()
|
|
60
|
+
.default(85)
|
|
61
|
+
.describe('Minimum production code quality score (0-100)'),
|
|
43
62
|
mockCodeMaxAllowed: z.number().default(0).describe('Maximum mock code indicators allowed'),
|
|
44
63
|
// Test Failure Gates
|
|
45
|
-
maxTestFailures: z
|
|
64
|
+
maxTestFailures: z
|
|
65
|
+
.number()
|
|
66
|
+
.default(0)
|
|
67
|
+
.describe('Maximum test failures allowed (0 = zero tolerance)'),
|
|
46
68
|
requireTestCoverage: z.number().default(80).describe('Minimum test coverage percentage required'),
|
|
47
69
|
blockOnFailingTests: z.boolean().default(true).describe('Block deployment if tests are failing'),
|
|
48
|
-
testSuiteRequired: z
|
|
70
|
+
testSuiteRequired: z
|
|
71
|
+
.array(z.string())
|
|
72
|
+
.default([])
|
|
73
|
+
.describe('Required test suites that must pass'),
|
|
49
74
|
// Deployment History Gates
|
|
50
75
|
maxRecentFailures: z.number().default(2).describe('Maximum recent deployment failures allowed'),
|
|
51
|
-
deploymentSuccessThreshold: z
|
|
76
|
+
deploymentSuccessThreshold: z
|
|
77
|
+
.number()
|
|
78
|
+
.default(80)
|
|
79
|
+
.describe('Minimum deployment success rate required (%)'),
|
|
52
80
|
blockOnRecentFailures: z.boolean().default(true).describe('Block if recent deployments failed'),
|
|
53
|
-
rollbackFrequencyThreshold: z
|
|
81
|
+
rollbackFrequencyThreshold: z
|
|
82
|
+
.number()
|
|
83
|
+
.default(20)
|
|
84
|
+
.describe('Maximum rollback frequency allowed (%)'),
|
|
54
85
|
// Integration Rules
|
|
55
86
|
requireAdrCompliance: z.boolean().default(true).describe('Require ADR compliance validation'),
|
|
56
87
|
integrateTodoTasks: z.boolean().default(true).describe('Auto-create blocking tasks for issues'),
|
|
@@ -59,8 +90,489 @@ const DeploymentReadinessSchema = z.object({
|
|
|
59
90
|
// Human Override System
|
|
60
91
|
emergencyBypass: z.boolean().default(false).describe('Emergency bypass for critical fixes'),
|
|
61
92
|
businessJustification: z.string().optional().describe('Business justification for overrides'),
|
|
62
|
-
approvalRequired: z.boolean().default(true).describe('Require approval for overrides')
|
|
93
|
+
approvalRequired: z.boolean().default(true).describe('Require approval for overrides'),
|
|
94
|
+
// Memory Integration
|
|
95
|
+
enableMemoryIntegration: z.boolean().default(true).describe('Enable memory entity storage'),
|
|
96
|
+
migrateExistingHistory: z
|
|
97
|
+
.boolean()
|
|
98
|
+
.default(false)
|
|
99
|
+
.describe('Migrate existing deployment history to memory'),
|
|
100
|
+
// Tree-sitter Analysis
|
|
101
|
+
enableTreeSitterAnalysis: z
|
|
102
|
+
.boolean()
|
|
103
|
+
.default(true)
|
|
104
|
+
.describe('Use tree-sitter for enhanced code analysis'),
|
|
105
|
+
treeSitterLanguages: z
|
|
106
|
+
.array(z.string())
|
|
107
|
+
.default(['typescript', 'javascript', 'python', 'yaml', 'hcl'])
|
|
108
|
+
.describe('Languages to analyze with tree-sitter'),
|
|
63
109
|
});
|
|
110
|
+
/**
|
|
111
|
+
* Deployment Memory Manager for tracking deployment assessments and patterns
|
|
112
|
+
*/
|
|
113
|
+
class DeploymentMemoryManager {
|
|
114
|
+
memoryManager;
|
|
115
|
+
logger;
|
|
116
|
+
constructor() {
|
|
117
|
+
this.memoryManager = new MemoryEntityManager();
|
|
118
|
+
this.logger = new EnhancedLogger();
|
|
119
|
+
}
|
|
120
|
+
async initialize() {
|
|
121
|
+
await this.memoryManager.initialize();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Store deployment assessment as memory entity
|
|
125
|
+
*/
|
|
126
|
+
async storeDeploymentAssessment(environment, readinessData, validationResults, projectPath) {
|
|
127
|
+
try {
|
|
128
|
+
const assessmentData = {
|
|
129
|
+
environment: environment,
|
|
130
|
+
readinessScore: readinessData.overallScore / 100, // Convert to 0-1 range
|
|
131
|
+
validationResults: {
|
|
132
|
+
testResults: {
|
|
133
|
+
passed: readinessData.testValidationResult.testSuitesExecuted.reduce((sum, suite) => sum + suite.passedTests, 0),
|
|
134
|
+
failed: readinessData.testValidationResult.failureCount,
|
|
135
|
+
coverage: readinessData.testValidationResult.coveragePercentage / 100, // Convert to 0-1 range
|
|
136
|
+
criticalFailures: readinessData.testValidationResult.criticalTestFailures.map(f => f.testName),
|
|
137
|
+
},
|
|
138
|
+
securityValidation: {
|
|
139
|
+
vulnerabilities: 0, // Default - could be enhanced with actual security scan data
|
|
140
|
+
securityScore: 0.8, // Default - could be enhanced with actual security analysis
|
|
141
|
+
criticalIssues: readinessData.criticalBlockers
|
|
142
|
+
.filter(b => b.category === 'adr_compliance')
|
|
143
|
+
.map(b => b.title),
|
|
144
|
+
},
|
|
145
|
+
performanceValidation: {
|
|
146
|
+
performanceScore: Math.max(0, (readinessData.overallScore - 20) / 80), // Derived from overall score
|
|
147
|
+
bottlenecks: [],
|
|
148
|
+
resourceUtilization: {},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
blockingIssues: [
|
|
152
|
+
...readinessData.criticalBlockers.map(b => ({
|
|
153
|
+
issue: `${b.title}: ${b.description}`,
|
|
154
|
+
severity: b.severity,
|
|
155
|
+
category: this.mapBlockerCategory(b.category),
|
|
156
|
+
resolution: b.resolutionSteps.join('; '),
|
|
157
|
+
estimatedEffort: b.estimatedResolutionTime,
|
|
158
|
+
})),
|
|
159
|
+
...readinessData.testFailureBlockers.map(b => ({
|
|
160
|
+
issue: `${b.title}: ${b.description}`,
|
|
161
|
+
severity: b.severity,
|
|
162
|
+
category: 'test',
|
|
163
|
+
resolution: b.resolutionSteps.join('; '),
|
|
164
|
+
estimatedEffort: b.estimatedResolutionTime,
|
|
165
|
+
})),
|
|
166
|
+
...readinessData.deploymentHistoryBlockers.map(b => ({
|
|
167
|
+
issue: `${b.title}: ${b.description}`,
|
|
168
|
+
severity: b.severity,
|
|
169
|
+
category: 'configuration',
|
|
170
|
+
resolution: b.resolutionSteps.join('; '),
|
|
171
|
+
estimatedEffort: b.estimatedResolutionTime,
|
|
172
|
+
})),
|
|
173
|
+
],
|
|
174
|
+
deploymentStrategy: {
|
|
175
|
+
type: 'rolling', // Default strategy - could be made configurable
|
|
176
|
+
rollbackPlan: 'Automated rollback via deployment pipeline with health check validation',
|
|
177
|
+
monitoringPlan: 'Monitor application metrics, error rates, and performance indicators for 30 minutes post-deployment',
|
|
178
|
+
estimatedDowntime: readinessData.isDeploymentReady
|
|
179
|
+
? '0 minutes (rolling deployment)'
|
|
180
|
+
: 'Cannot deploy - blockers present',
|
|
181
|
+
},
|
|
182
|
+
complianceChecks: {
|
|
183
|
+
adrCompliance: readinessData.adrComplianceResult.score / 100, // Convert to 0-1 range
|
|
184
|
+
regulatoryCompliance: [], // Could be enhanced with actual compliance data
|
|
185
|
+
auditTrail: [
|
|
186
|
+
`Deployment assessment completed at ${new Date().toISOString()}`,
|
|
187
|
+
`Test validation: ${readinessData.testValidationResult.overallTestStatus}`,
|
|
188
|
+
`Overall readiness score: ${readinessData.overallScore}%`,
|
|
189
|
+
`Git push status: ${readinessData.gitPushStatus}`,
|
|
190
|
+
],
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
const entity = await this.memoryManager.upsertEntity({
|
|
194
|
+
type: 'deployment_assessment',
|
|
195
|
+
title: `Deployment Assessment: ${environment} - ${readinessData.isDeploymentReady ? 'READY' : 'BLOCKED'} - ${new Date().toISOString().split('T')[0]}`,
|
|
196
|
+
description: `Deployment readiness assessment for ${environment} environment${readinessData.isDeploymentReady ? ' - APPROVED' : ' - BLOCKED'}`,
|
|
197
|
+
tags: [
|
|
198
|
+
'deployment',
|
|
199
|
+
environment.toLowerCase(),
|
|
200
|
+
'readiness-assessment',
|
|
201
|
+
readinessData.isDeploymentReady ? 'approved' : 'blocked',
|
|
202
|
+
`score-${Math.floor(readinessData.overallScore / 10) * 10}`,
|
|
203
|
+
...(readinessData.criticalBlockers.length > 0 ? ['critical-issues'] : []),
|
|
204
|
+
...(readinessData.testValidationResult.failureCount > 0 ? ['test-failures'] : []),
|
|
205
|
+
...(readinessData.deploymentHistoryAnalysis.rollbackRate > 20
|
|
206
|
+
? ['high-rollback-risk']
|
|
207
|
+
: []),
|
|
208
|
+
],
|
|
209
|
+
assessmentData,
|
|
210
|
+
relationships: [],
|
|
211
|
+
context: {
|
|
212
|
+
projectPhase: 'deployment-validation',
|
|
213
|
+
technicalStack: this.extractTechnicalStack(validationResults),
|
|
214
|
+
environmentalFactors: [environment, projectPath || 'unknown-project'].filter(Boolean),
|
|
215
|
+
stakeholders: ['deployment-team', 'qa-team', 'infrastructure-team'],
|
|
216
|
+
},
|
|
217
|
+
accessPattern: {
|
|
218
|
+
lastAccessed: new Date().toISOString(),
|
|
219
|
+
accessCount: 1,
|
|
220
|
+
accessContext: ['deployment-assessment'],
|
|
221
|
+
},
|
|
222
|
+
evolution: {
|
|
223
|
+
origin: 'created',
|
|
224
|
+
transformations: [
|
|
225
|
+
{
|
|
226
|
+
timestamp: new Date().toISOString(),
|
|
227
|
+
type: 'assessment_creation',
|
|
228
|
+
description: `Deployment assessment created for ${environment}`,
|
|
229
|
+
agent: 'deployment-readiness-tool',
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
},
|
|
233
|
+
validation: {
|
|
234
|
+
isVerified: readinessData.isDeploymentReady,
|
|
235
|
+
verificationMethod: 'comprehensive-deployment-audit',
|
|
236
|
+
verificationTimestamp: new Date().toISOString(),
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
this.logger.info(`Deployment assessment stored for ${environment}`, 'DeploymentMemoryManager', {
|
|
240
|
+
environment,
|
|
241
|
+
entityId: entity.id,
|
|
242
|
+
readinessScore: readinessData.overallScore,
|
|
243
|
+
isReady: readinessData.isDeploymentReady,
|
|
244
|
+
blockingIssues: assessmentData.blockingIssues.length,
|
|
245
|
+
});
|
|
246
|
+
return entity.id;
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
this.logger.error('Failed to store deployment assessment', 'DeploymentMemoryManager', error);
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Migrate existing deployment history to memory entities
|
|
255
|
+
*/
|
|
256
|
+
async migrateExistingHistory(historyPath) {
|
|
257
|
+
try {
|
|
258
|
+
if (!existsSync(historyPath)) {
|
|
259
|
+
this.logger.info('No existing deployment history found to migrate', 'DeploymentMemoryManager');
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
const historyData = JSON.parse(readFileSync(historyPath, 'utf8'));
|
|
263
|
+
const deployments = historyData.deployments || [];
|
|
264
|
+
let migratedCount = 0;
|
|
265
|
+
for (const deployment of deployments) {
|
|
266
|
+
try {
|
|
267
|
+
await this.migrateDeploymentRecord(deployment);
|
|
268
|
+
migratedCount++;
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
this.logger.error(`Failed to migrate deployment ${deployment.deploymentId}`, 'DeploymentMemoryManager', error);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
this.logger.info(`Migration completed: ${migratedCount}/${deployments.length} deployments migrated`, 'DeploymentMemoryManager');
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
this.logger.error('Failed to migrate deployment history', 'DeploymentMemoryManager', error);
|
|
278
|
+
throw error;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Analyze deployment patterns across memory entities
|
|
283
|
+
*/
|
|
284
|
+
async analyzeDeploymentPatterns(environment) {
|
|
285
|
+
try {
|
|
286
|
+
const query = {
|
|
287
|
+
entityTypes: ['deployment_assessment'],
|
|
288
|
+
limit: 100,
|
|
289
|
+
sortBy: 'lastModified',
|
|
290
|
+
};
|
|
291
|
+
if (environment) {
|
|
292
|
+
query.tags = [environment.toLowerCase()];
|
|
293
|
+
}
|
|
294
|
+
const assessments = await this.memoryManager.queryEntities(query);
|
|
295
|
+
const patterns = this.detectDeploymentPatterns(assessments.entities);
|
|
296
|
+
const trends = this.calculateDeploymentTrends(assessments.entities);
|
|
297
|
+
const recommendations = this.generatePatternRecommendations(patterns, trends);
|
|
298
|
+
const riskFactors = this.identifyRiskFactors(assessments.entities);
|
|
299
|
+
return {
|
|
300
|
+
patterns,
|
|
301
|
+
trends,
|
|
302
|
+
recommendations,
|
|
303
|
+
riskFactors,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
this.logger.error('Failed to analyze deployment patterns', 'DeploymentMemoryManager', error);
|
|
308
|
+
throw error;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Compare current assessment with historical patterns
|
|
313
|
+
*/
|
|
314
|
+
async compareWithHistory(currentAssessment, environment) {
|
|
315
|
+
try {
|
|
316
|
+
const recentAssessments = await this.memoryManager.queryEntities({
|
|
317
|
+
entityTypes: ['deployment_assessment'],
|
|
318
|
+
tags: [environment.toLowerCase()],
|
|
319
|
+
limit: 10,
|
|
320
|
+
sortBy: 'lastModified',
|
|
321
|
+
});
|
|
322
|
+
if (recentAssessments.entities.length === 0) {
|
|
323
|
+
return {
|
|
324
|
+
isImprovement: true,
|
|
325
|
+
comparison: { type: 'first_assessment' },
|
|
326
|
+
insights: ['This is the first deployment assessment for this environment'],
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
const lastAssessment = recentAssessments.entities[0];
|
|
330
|
+
const comparison = this.compareAssessments(currentAssessment, lastAssessment.assessmentData);
|
|
331
|
+
return {
|
|
332
|
+
isImprovement: comparison.scoreImprovement > 0,
|
|
333
|
+
comparison,
|
|
334
|
+
insights: this.generateComparisonInsights(comparison),
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
this.logger.error('Failed to compare with history', 'DeploymentMemoryManager', error);
|
|
339
|
+
return {
|
|
340
|
+
isImprovement: false,
|
|
341
|
+
comparison: { type: 'comparison_failed' },
|
|
342
|
+
insights: ['Unable to compare with historical data'],
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
// Private helper methods
|
|
347
|
+
async migrateDeploymentRecord(deployment) {
|
|
348
|
+
const assessmentData = {
|
|
349
|
+
environment: deployment.environment,
|
|
350
|
+
readinessScore: deployment.status === 'success' ? 1.0 : 0.0, // Use 0-1 range
|
|
351
|
+
validationResults: {
|
|
352
|
+
testResults: deployment.testResults
|
|
353
|
+
? {
|
|
354
|
+
passed: deployment.testResults.testSuitesExecuted.reduce((sum, suite) => sum + suite.passedTests, 0),
|
|
355
|
+
failed: deployment.testResults.failureCount,
|
|
356
|
+
coverage: deployment.testResults.coveragePercentage / 100,
|
|
357
|
+
criticalFailures: deployment.testResults.criticalTestFailures.map(f => f.testName),
|
|
358
|
+
}
|
|
359
|
+
: {
|
|
360
|
+
passed: 0,
|
|
361
|
+
failed: 0,
|
|
362
|
+
coverage: 0,
|
|
363
|
+
criticalFailures: [],
|
|
364
|
+
},
|
|
365
|
+
securityValidation: {
|
|
366
|
+
vulnerabilities: 0,
|
|
367
|
+
securityScore: 0.8,
|
|
368
|
+
criticalIssues: [],
|
|
369
|
+
},
|
|
370
|
+
performanceValidation: {
|
|
371
|
+
performanceScore: deployment.status === 'success' ? 0.8 : 0.2,
|
|
372
|
+
bottlenecks: [],
|
|
373
|
+
resourceUtilization: {},
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
blockingIssues: deployment.failureReason
|
|
377
|
+
? [
|
|
378
|
+
{
|
|
379
|
+
issue: `Historical Deployment Failure: ${deployment.failureReason}`,
|
|
380
|
+
severity: 'high',
|
|
381
|
+
category: 'configuration',
|
|
382
|
+
resolution: 'Review and address historical failure causes',
|
|
383
|
+
},
|
|
384
|
+
]
|
|
385
|
+
: [],
|
|
386
|
+
deploymentStrategy: {
|
|
387
|
+
type: 'rolling',
|
|
388
|
+
rollbackPlan: 'Standard rollback procedure',
|
|
389
|
+
monitoringPlan: 'Basic monitoring',
|
|
390
|
+
estimatedDowntime: deployment.rollbackRequired ? 'Variable' : '0 minutes',
|
|
391
|
+
},
|
|
392
|
+
complianceChecks: {
|
|
393
|
+
adrCompliance: 1.0,
|
|
394
|
+
regulatoryCompliance: [],
|
|
395
|
+
auditTrail: [
|
|
396
|
+
`Migrated deployment record from ${deployment.timestamp}`,
|
|
397
|
+
`Original status: ${deployment.status}`,
|
|
398
|
+
`Rollback required: ${deployment.rollbackRequired}`,
|
|
399
|
+
],
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
await this.memoryManager.upsertEntity({
|
|
403
|
+
type: 'deployment_assessment',
|
|
404
|
+
title: `Historical Deployment: ${deployment.environment} - ${deployment.status.toUpperCase()} - ${deployment.timestamp.split('T')[0]}`,
|
|
405
|
+
description: `Migrated deployment record for ${deployment.environment} (ID: ${deployment.deploymentId})`,
|
|
406
|
+
tags: [
|
|
407
|
+
'deployment',
|
|
408
|
+
deployment.environment.toLowerCase(),
|
|
409
|
+
'migrated-record',
|
|
410
|
+
deployment.status,
|
|
411
|
+
...(deployment.rollbackRequired ? ['rollback-required'] : []),
|
|
412
|
+
],
|
|
413
|
+
assessmentData,
|
|
414
|
+
relationships: [],
|
|
415
|
+
context: {
|
|
416
|
+
projectPhase: 'deployment-execution',
|
|
417
|
+
technicalStack: [],
|
|
418
|
+
environmentalFactors: [deployment.environment],
|
|
419
|
+
stakeholders: ['deployment-team'],
|
|
420
|
+
},
|
|
421
|
+
accessPattern: {
|
|
422
|
+
lastAccessed: new Date().toISOString(),
|
|
423
|
+
accessCount: 1,
|
|
424
|
+
accessContext: ['migration'],
|
|
425
|
+
},
|
|
426
|
+
evolution: {
|
|
427
|
+
origin: 'imported',
|
|
428
|
+
transformations: [
|
|
429
|
+
{
|
|
430
|
+
timestamp: new Date().toISOString(),
|
|
431
|
+
type: 'migration',
|
|
432
|
+
description: `Migrated from deployment-history.json (original: ${deployment.timestamp})`,
|
|
433
|
+
agent: 'deployment-readiness-tool',
|
|
434
|
+
},
|
|
435
|
+
],
|
|
436
|
+
},
|
|
437
|
+
validation: {
|
|
438
|
+
isVerified: true,
|
|
439
|
+
verificationMethod: 'historical-migration',
|
|
440
|
+
verificationTimestamp: new Date().toISOString(),
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
extractTechnicalStack(_validationResults) {
|
|
445
|
+
// Extract technical stack from validation results
|
|
446
|
+
// This is a simplified implementation
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
detectDeploymentPatterns(assessments) {
|
|
450
|
+
// Analyze deployment patterns across assessments
|
|
451
|
+
const patterns = [];
|
|
452
|
+
// Pattern: Time-based failures
|
|
453
|
+
const timePatterns = this.analyzeTimePatterns(assessments);
|
|
454
|
+
if (timePatterns.length > 0) {
|
|
455
|
+
patterns.push({ type: 'time_based', patterns: timePatterns });
|
|
456
|
+
}
|
|
457
|
+
// Pattern: Environment-specific issues
|
|
458
|
+
const envPatterns = this.analyzeEnvironmentPatterns(assessments);
|
|
459
|
+
if (envPatterns.length > 0) {
|
|
460
|
+
patterns.push({ type: 'environment_specific', patterns: envPatterns });
|
|
461
|
+
}
|
|
462
|
+
return patterns;
|
|
463
|
+
}
|
|
464
|
+
calculateDeploymentTrends(assessments) {
|
|
465
|
+
if (assessments.length < 3)
|
|
466
|
+
return [];
|
|
467
|
+
const trends = [];
|
|
468
|
+
const scores = assessments.map((a) => a.assessmentData.readinessScore);
|
|
469
|
+
// Calculate score trend
|
|
470
|
+
const scoreTrend = this.calculateTrend(scores);
|
|
471
|
+
trends.push({
|
|
472
|
+
metric: 'readiness_score',
|
|
473
|
+
trend: scoreTrend > 0 ? 'improving' : scoreTrend < 0 ? 'declining' : 'stable',
|
|
474
|
+
change: scoreTrend,
|
|
475
|
+
});
|
|
476
|
+
return trends;
|
|
477
|
+
}
|
|
478
|
+
generatePatternRecommendations(patterns, trends) {
|
|
479
|
+
const recommendations = [];
|
|
480
|
+
// Generate recommendations based on patterns
|
|
481
|
+
patterns.forEach(pattern => {
|
|
482
|
+
if (pattern.type === 'time_based') {
|
|
483
|
+
recommendations.push('Consider scheduling deployments during low-risk time windows');
|
|
484
|
+
}
|
|
485
|
+
if (pattern.type === 'environment_specific') {
|
|
486
|
+
recommendations.push('Address environment-specific configuration issues');
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
// Generate recommendations based on trends
|
|
490
|
+
trends.forEach(trend => {
|
|
491
|
+
if (trend.metric === 'readiness_score' && trend.trend === 'declining') {
|
|
492
|
+
recommendations.push('Investigate causes of declining deployment readiness scores');
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
return recommendations;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Map deployment blocker category to schema-compliant category
|
|
499
|
+
*/
|
|
500
|
+
mapBlockerCategory(category) {
|
|
501
|
+
switch (category) {
|
|
502
|
+
case 'test_failure':
|
|
503
|
+
return 'test';
|
|
504
|
+
case 'adr_compliance':
|
|
505
|
+
case 'environment':
|
|
506
|
+
case 'deployment_history':
|
|
507
|
+
return 'configuration';
|
|
508
|
+
case 'code_quality':
|
|
509
|
+
return 'performance';
|
|
510
|
+
default:
|
|
511
|
+
return 'configuration';
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
identifyRiskFactors(assessments) {
|
|
515
|
+
const riskFactors = [];
|
|
516
|
+
// Analyze recent failures
|
|
517
|
+
const recentFailures = assessments
|
|
518
|
+
.filter((a) => !a.assessmentData.deploymentReady)
|
|
519
|
+
.slice(0, 5);
|
|
520
|
+
if (recentFailures.length >= 3) {
|
|
521
|
+
riskFactors.push({
|
|
522
|
+
factor: 'frequent_failures',
|
|
523
|
+
description: `${recentFailures.length} deployment blocks in recent assessments`,
|
|
524
|
+
severity: 'high',
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
return riskFactors;
|
|
528
|
+
}
|
|
529
|
+
compareAssessments(current, historical) {
|
|
530
|
+
return {
|
|
531
|
+
scoreImprovement: current.overallScore - historical.readinessScore,
|
|
532
|
+
confidenceChange: current.confidence - historical.confidence,
|
|
533
|
+
blockingIssuesChange: current.criticalBlockers.length - historical.blockingIssues.length,
|
|
534
|
+
testImprovements: {
|
|
535
|
+
failureCountChange: current.testValidationResult.failureCount -
|
|
536
|
+
(historical.validationResults?.testValidation?.failureCount || 0),
|
|
537
|
+
coverageChange: current.testValidationResult.coveragePercentage -
|
|
538
|
+
(historical.validationResults?.testValidation?.coveragePercentage || 0),
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
generateComparisonInsights(comparison) {
|
|
543
|
+
const insights = [];
|
|
544
|
+
if (comparison.scoreImprovement > 0) {
|
|
545
|
+
insights.push(`Deployment readiness improved by ${comparison.scoreImprovement} points`);
|
|
546
|
+
}
|
|
547
|
+
else if (comparison.scoreImprovement < 0) {
|
|
548
|
+
insights.push(`Deployment readiness declined by ${Math.abs(comparison.scoreImprovement)} points`);
|
|
549
|
+
}
|
|
550
|
+
if (comparison.testImprovements.failureCountChange < 0) {
|
|
551
|
+
insights.push(`Test stability improved: ${Math.abs(comparison.testImprovements.failureCountChange)} fewer failures`);
|
|
552
|
+
}
|
|
553
|
+
if (comparison.testImprovements.coverageChange > 0) {
|
|
554
|
+
insights.push(`Test coverage increased by ${comparison.testImprovements.coverageChange}%`);
|
|
555
|
+
}
|
|
556
|
+
return insights;
|
|
557
|
+
}
|
|
558
|
+
analyzeTimePatterns(_assessments) {
|
|
559
|
+
// Simplified time pattern analysis
|
|
560
|
+
return [];
|
|
561
|
+
}
|
|
562
|
+
analyzeEnvironmentPatterns(_assessments) {
|
|
563
|
+
// Simplified environment pattern analysis
|
|
564
|
+
return [];
|
|
565
|
+
}
|
|
566
|
+
calculateTrend(values) {
|
|
567
|
+
if (values.length < 2)
|
|
568
|
+
return 0;
|
|
569
|
+
const recent = values.slice(0, Math.min(5, values.length));
|
|
570
|
+
const older = values.slice(Math.min(5, values.length));
|
|
571
|
+
const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length;
|
|
572
|
+
const olderAvg = older.length > 0 ? older.reduce((a, b) => a + b, 0) / older.length : recentAvg;
|
|
573
|
+
return recentAvg - olderAvg;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
64
576
|
/**
|
|
65
577
|
* Main deployment readiness function
|
|
66
578
|
*/
|
|
@@ -69,13 +581,24 @@ export async function deploymentReadiness(args) {
|
|
|
69
581
|
const validatedArgs = DeploymentReadinessSchema.parse(args);
|
|
70
582
|
// Initialize paths and cache
|
|
71
583
|
const projectPath = validatedArgs.projectPath || process.cwd();
|
|
72
|
-
const
|
|
584
|
+
const projectName = basename(projectPath);
|
|
585
|
+
const cacheDir = join(os.tmpdir(), projectName, 'cache');
|
|
73
586
|
const deploymentHistoryPath = join(cacheDir, 'deployment-history.json');
|
|
74
587
|
const readinessCachePath = join(cacheDir, 'deployment-readiness-cache.json');
|
|
75
588
|
// Ensure cache directory exists
|
|
76
589
|
if (!existsSync(cacheDir)) {
|
|
77
590
|
mkdirSync(cacheDir, { recursive: true });
|
|
78
591
|
}
|
|
592
|
+
// Initialize memory manager if enabled
|
|
593
|
+
let memoryManager = null;
|
|
594
|
+
if (validatedArgs.enableMemoryIntegration) {
|
|
595
|
+
memoryManager = new DeploymentMemoryManager();
|
|
596
|
+
await memoryManager.initialize();
|
|
597
|
+
// Migrate existing history if requested
|
|
598
|
+
if (validatedArgs.migrateExistingHistory) {
|
|
599
|
+
await memoryManager.migrateExistingHistory(deploymentHistoryPath);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
79
602
|
let result;
|
|
80
603
|
switch (validatedArgs.operation) {
|
|
81
604
|
case 'test_validation':
|
|
@@ -99,10 +622,68 @@ export async function deploymentReadiness(args) {
|
|
|
99
622
|
writeFileSync(readinessCachePath, JSON.stringify({
|
|
100
623
|
timestamp: new Date().toISOString(),
|
|
101
624
|
operation: validatedArgs.operation,
|
|
102
|
-
result
|
|
625
|
+
result,
|
|
103
626
|
}, null, 2));
|
|
104
|
-
//
|
|
105
|
-
|
|
627
|
+
// Memory integration: store assessment and analyze patterns
|
|
628
|
+
let memoryIntegrationInfo = '';
|
|
629
|
+
if (memoryManager) {
|
|
630
|
+
try {
|
|
631
|
+
// Store deployment assessment
|
|
632
|
+
const assessmentId = await memoryManager.storeDeploymentAssessment(validatedArgs.targetEnvironment, result, { projectPath, operation: validatedArgs.operation }, projectPath);
|
|
633
|
+
// Compare with historical patterns
|
|
634
|
+
const historyComparison = await memoryManager.compareWithHistory(result, validatedArgs.targetEnvironment);
|
|
635
|
+
// Analyze deployment patterns
|
|
636
|
+
const patternAnalysis = await memoryManager.analyzeDeploymentPatterns(validatedArgs.targetEnvironment);
|
|
637
|
+
memoryIntegrationInfo = `
|
|
638
|
+
|
|
639
|
+
## 🧠 Memory Integration Analysis
|
|
640
|
+
|
|
641
|
+
- **Assessment Stored**: ✅ Deployment assessment saved (ID: ${assessmentId.substring(0, 8)}...)
|
|
642
|
+
- **Environment**: ${validatedArgs.targetEnvironment}
|
|
643
|
+
- **Historical Comparison**: ${historyComparison.isImprovement ? '📈 Improvement detected' : '📊 Baseline established'}
|
|
644
|
+
|
|
645
|
+
${historyComparison.insights.length > 0
|
|
646
|
+
? `### Historical Insights
|
|
647
|
+
${historyComparison.insights.map(insight => `- ${insight}`).join('\n')}
|
|
648
|
+
`
|
|
649
|
+
: ''}
|
|
650
|
+
|
|
651
|
+
${patternAnalysis.trends.length > 0
|
|
652
|
+
? `### Deployment Trends
|
|
653
|
+
${patternAnalysis.trends.map(trend => `- **${trend.metric}**: ${trend.trend} (${trend.change > 0 ? '+' : ''}${trend.change})`).join('\n')}
|
|
654
|
+
`
|
|
655
|
+
: ''}
|
|
656
|
+
|
|
657
|
+
${patternAnalysis.recommendations.length > 0
|
|
658
|
+
? `### Pattern-Based Recommendations
|
|
659
|
+
${patternAnalysis.recommendations.map(rec => `- ${rec}`).join('\n')}
|
|
660
|
+
`
|
|
661
|
+
: ''}
|
|
662
|
+
|
|
663
|
+
${patternAnalysis.riskFactors.length > 0
|
|
664
|
+
? `### Risk Factors Identified
|
|
665
|
+
${patternAnalysis.riskFactors.map(risk => `- **${risk.factor}**: ${risk.description} (${risk.severity})`).join('\n')}
|
|
666
|
+
`
|
|
667
|
+
: ''}
|
|
668
|
+
`;
|
|
669
|
+
}
|
|
670
|
+
catch (memoryError) {
|
|
671
|
+
memoryIntegrationInfo = `
|
|
672
|
+
|
|
673
|
+
## 🧠 Memory Integration Status
|
|
674
|
+
|
|
675
|
+
- **Status**: ⚠️ Memory integration failed - assessment continued without persistence
|
|
676
|
+
- **Error**: ${memoryError instanceof Error ? memoryError.message : 'Unknown error'}
|
|
677
|
+
`;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
// Generate enhanced response with memory integration
|
|
681
|
+
const baseResponse = generateDeploymentReadinessResponse(result, validatedArgs);
|
|
682
|
+
// Add memory integration info if available
|
|
683
|
+
if (memoryIntegrationInfo && baseResponse.content?.[0]?.text) {
|
|
684
|
+
baseResponse.content[0].text += memoryIntegrationInfo;
|
|
685
|
+
}
|
|
686
|
+
return baseResponse;
|
|
106
687
|
}
|
|
107
688
|
catch (error) {
|
|
108
689
|
throw new McpAdrError('DEPLOYMENT_READINESS_ERROR', `Deployment readiness check failed: ${jsonSafeError(error)}`);
|
|
@@ -126,10 +707,10 @@ async function performTestValidation(args, projectPath) {
|
|
|
126
707
|
'Run npm test to see detailed failures',
|
|
127
708
|
'Fix failing tests one by one',
|
|
128
709
|
'Ensure all tests pass before deployment',
|
|
129
|
-
'Consider increasing test coverage'
|
|
710
|
+
'Consider increasing test coverage',
|
|
130
711
|
],
|
|
131
712
|
estimatedResolutionTime: `${Math.ceil(testResult.failureCount * 0.5)} hours`,
|
|
132
|
-
blocksDeployment: args.blockOnFailingTests
|
|
713
|
+
blocksDeployment: args.blockOnFailingTests,
|
|
133
714
|
});
|
|
134
715
|
}
|
|
135
716
|
// Check test coverage
|
|
@@ -143,10 +724,10 @@ async function performTestValidation(args, projectPath) {
|
|
|
143
724
|
resolutionSteps: [
|
|
144
725
|
'Add tests for uncovered code',
|
|
145
726
|
'Run npm run test:coverage to see detailed coverage',
|
|
146
|
-
'Focus on critical business logic first'
|
|
727
|
+
'Focus on critical business logic first',
|
|
147
728
|
],
|
|
148
729
|
estimatedResolutionTime: '2-4 hours',
|
|
149
|
-
blocksDeployment: args.strictMode
|
|
730
|
+
blocksDeployment: args.strictMode,
|
|
150
731
|
});
|
|
151
732
|
}
|
|
152
733
|
// Basic result structure
|
|
@@ -154,10 +735,28 @@ async function performTestValidation(args, projectPath) {
|
|
|
154
735
|
isDeploymentReady: testBlockers.length === 0,
|
|
155
736
|
overallScore: calculateTestScore(testResult, args),
|
|
156
737
|
confidence: 85,
|
|
157
|
-
codeQualityAnalysis:
|
|
738
|
+
codeQualityAnalysis: await analyzeCodeQualityWithTreeSitter(args.projectPath || process.cwd(), args.enableTreeSitterAnalysis, args.treeSitterLanguages),
|
|
158
739
|
testValidationResult: testResult,
|
|
159
|
-
deploymentHistoryAnalysis: {
|
|
160
|
-
|
|
740
|
+
deploymentHistoryAnalysis: {
|
|
741
|
+
recentDeployments: [],
|
|
742
|
+
successRate: 100,
|
|
743
|
+
rollbackRate: 0,
|
|
744
|
+
averageDeploymentTime: 0,
|
|
745
|
+
failurePatterns: [],
|
|
746
|
+
environmentStability: {
|
|
747
|
+
stabilityScore: 100,
|
|
748
|
+
riskLevel: 'low',
|
|
749
|
+
recommendation: 'Proceed with deployment',
|
|
750
|
+
},
|
|
751
|
+
recommendedAction: 'proceed',
|
|
752
|
+
},
|
|
753
|
+
adrComplianceResult: {
|
|
754
|
+
score: 100,
|
|
755
|
+
compliantAdrs: 0,
|
|
756
|
+
totalAdrs: 0,
|
|
757
|
+
missingImplementations: [],
|
|
758
|
+
recommendations: [],
|
|
759
|
+
},
|
|
161
760
|
criticalBlockers: testBlockers.filter(b => b.severity === 'critical'),
|
|
162
761
|
testFailureBlockers: testBlockers,
|
|
163
762
|
deploymentHistoryBlockers: [],
|
|
@@ -165,7 +764,7 @@ async function performTestValidation(args, projectPath) {
|
|
|
165
764
|
todoTasksCreated: [],
|
|
166
765
|
healthScoreUpdate: {},
|
|
167
766
|
gitPushStatus: testBlockers.length === 0 ? 'allowed' : 'blocked',
|
|
168
|
-
overrideStatus: {}
|
|
767
|
+
overrideStatus: {},
|
|
169
768
|
};
|
|
170
769
|
}
|
|
171
770
|
/**
|
|
@@ -183,7 +782,7 @@ async function executeTestSuite(projectPath, _requiredSuites) {
|
|
|
183
782
|
testOutput = execSync(command, {
|
|
184
783
|
cwd: projectPath,
|
|
185
784
|
encoding: 'utf8',
|
|
186
|
-
timeout: 300000 // 5 minute timeout
|
|
785
|
+
timeout: 300000, // 5 minute timeout
|
|
187
786
|
});
|
|
188
787
|
break;
|
|
189
788
|
}
|
|
@@ -206,7 +805,7 @@ async function executeTestSuite(projectPath, _requiredSuites) {
|
|
|
206
805
|
// Parse test results (simplified for now)
|
|
207
806
|
const testSuites = parseTestOutput(testOutput);
|
|
208
807
|
const totalFailures = testSuites.reduce((sum, suite) => sum + suite.failedTests, 0);
|
|
209
|
-
const overallStatus = exitCode === 0 ? 'passed' :
|
|
808
|
+
const overallStatus = exitCode === 0 ? 'passed' : totalFailures > 0 ? 'failed' : 'partial';
|
|
210
809
|
// Check coverage (simplified)
|
|
211
810
|
const coverage = await checkTestCoverage(projectPath);
|
|
212
811
|
return {
|
|
@@ -217,7 +816,7 @@ async function executeTestSuite(projectPath, _requiredSuites) {
|
|
|
217
816
|
requiredSuitesMissing: [],
|
|
218
817
|
criticalTestFailures: testSuites.flatMap(suite => suite.failureDetails.filter(f => f.severity === 'critical')),
|
|
219
818
|
testExecutionTime: executionTime,
|
|
220
|
-
lastTestRun: new Date().toISOString()
|
|
819
|
+
lastTestRun: new Date().toISOString(),
|
|
221
820
|
};
|
|
222
821
|
}
|
|
223
822
|
/**
|
|
@@ -241,7 +840,7 @@ function parseTestOutput(output) {
|
|
|
241
840
|
failedTests: 0,
|
|
242
841
|
coverage: 0,
|
|
243
842
|
executionTime: 0,
|
|
244
|
-
failureDetails: []
|
|
843
|
+
failureDetails: [],
|
|
245
844
|
};
|
|
246
845
|
}
|
|
247
846
|
// Count tests
|
|
@@ -258,7 +857,7 @@ function parseTestOutput(output) {
|
|
|
258
857
|
errorMessage: line,
|
|
259
858
|
severity: 'medium',
|
|
260
859
|
blocksDeployment: true,
|
|
261
|
-
relatedFiles: []
|
|
860
|
+
relatedFiles: [],
|
|
262
861
|
});
|
|
263
862
|
}
|
|
264
863
|
}
|
|
@@ -266,15 +865,19 @@ function parseTestOutput(output) {
|
|
|
266
865
|
if (currentSuite.suiteName) {
|
|
267
866
|
suites.push(currentSuite);
|
|
268
867
|
}
|
|
269
|
-
return suites.length > 0
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
868
|
+
return suites.length > 0
|
|
869
|
+
? suites
|
|
870
|
+
: [
|
|
871
|
+
{
|
|
872
|
+
suiteName: 'default',
|
|
873
|
+
status: output.includes('failing') ? 'failed' : 'passed',
|
|
874
|
+
passedTests: 0,
|
|
875
|
+
failedTests: output.includes('failing') ? 1 : 0,
|
|
876
|
+
coverage: 0,
|
|
877
|
+
executionTime: 0,
|
|
878
|
+
failureDetails: [],
|
|
879
|
+
},
|
|
880
|
+
];
|
|
278
881
|
}
|
|
279
882
|
/**
|
|
280
883
|
* Check test coverage
|
|
@@ -285,7 +888,7 @@ async function checkTestCoverage(projectPath) {
|
|
|
285
888
|
const coverageFiles = [
|
|
286
889
|
'coverage/lcov-report/index.html',
|
|
287
890
|
'coverage/coverage-summary.json',
|
|
288
|
-
'coverage/coverage-final.json'
|
|
891
|
+
'coverage/coverage-final.json',
|
|
289
892
|
];
|
|
290
893
|
for (const file of coverageFiles) {
|
|
291
894
|
const filePath = join(projectPath, file);
|
|
@@ -299,7 +902,7 @@ async function checkTestCoverage(projectPath) {
|
|
|
299
902
|
}
|
|
300
903
|
}
|
|
301
904
|
}
|
|
302
|
-
catch
|
|
905
|
+
catch {
|
|
303
906
|
// Coverage not available
|
|
304
907
|
}
|
|
305
908
|
return 0; // Default to 0 if coverage cannot be determined
|
|
@@ -323,10 +926,10 @@ async function performDeploymentHistoryAnalysis(args, historyPath) {
|
|
|
323
926
|
'Review recent deployment failures',
|
|
324
927
|
'Fix underlying infrastructure issues',
|
|
325
928
|
'Improve deployment process reliability',
|
|
326
|
-
'Add more comprehensive pre-deployment checks'
|
|
929
|
+
'Add more comprehensive pre-deployment checks',
|
|
327
930
|
],
|
|
328
931
|
estimatedResolutionTime: '1-2 days',
|
|
329
|
-
blocksDeployment: args.blockOnRecentFailures
|
|
932
|
+
blocksDeployment: args.blockOnRecentFailures,
|
|
330
933
|
});
|
|
331
934
|
}
|
|
332
935
|
// Check rollback rate
|
|
@@ -341,20 +944,35 @@ async function performDeploymentHistoryAnalysis(args, historyPath) {
|
|
|
341
944
|
'Improve testing before deployment',
|
|
342
945
|
'Add more validation steps',
|
|
343
946
|
'Review rollback causes',
|
|
344
|
-
'Strengthen deployment pipeline'
|
|
947
|
+
'Strengthen deployment pipeline',
|
|
345
948
|
],
|
|
346
949
|
estimatedResolutionTime: '4-8 hours',
|
|
347
|
-
blocksDeployment: args.strictMode
|
|
950
|
+
blocksDeployment: args.strictMode,
|
|
348
951
|
});
|
|
349
952
|
}
|
|
350
953
|
return {
|
|
351
954
|
isDeploymentReady: historyBlockers.length === 0,
|
|
352
955
|
overallScore: Math.min(analysis.successRate, 100 - analysis.rollbackRate),
|
|
353
956
|
confidence: 80,
|
|
354
|
-
codeQualityAnalysis:
|
|
355
|
-
testValidationResult: {
|
|
957
|
+
codeQualityAnalysis: await analyzeCodeQualityWithTreeSitter(args.projectPath || process.cwd(), args.enableTreeSitterAnalysis, args.treeSitterLanguages),
|
|
958
|
+
testValidationResult: {
|
|
959
|
+
testSuitesExecuted: [],
|
|
960
|
+
overallTestStatus: 'not_run',
|
|
961
|
+
failureCount: 0,
|
|
962
|
+
coveragePercentage: 0,
|
|
963
|
+
requiredSuitesMissing: [],
|
|
964
|
+
criticalTestFailures: [],
|
|
965
|
+
testExecutionTime: 0,
|
|
966
|
+
lastTestRun: '',
|
|
967
|
+
},
|
|
356
968
|
deploymentHistoryAnalysis: analysis,
|
|
357
|
-
adrComplianceResult: {
|
|
969
|
+
adrComplianceResult: {
|
|
970
|
+
score: 100,
|
|
971
|
+
compliantAdrs: 0,
|
|
972
|
+
totalAdrs: 0,
|
|
973
|
+
missingImplementations: [],
|
|
974
|
+
recommendations: [],
|
|
975
|
+
},
|
|
358
976
|
criticalBlockers: historyBlockers.filter(b => b.severity === 'critical'),
|
|
359
977
|
testFailureBlockers: [],
|
|
360
978
|
deploymentHistoryBlockers: historyBlockers,
|
|
@@ -362,7 +980,7 @@ async function performDeploymentHistoryAnalysis(args, historyPath) {
|
|
|
362
980
|
todoTasksCreated: [],
|
|
363
981
|
healthScoreUpdate: {},
|
|
364
982
|
gitPushStatus: historyBlockers.length === 0 ? 'allowed' : 'blocked',
|
|
365
|
-
overrideStatus: {}
|
|
983
|
+
overrideStatus: {},
|
|
366
984
|
};
|
|
367
985
|
}
|
|
368
986
|
/**
|
|
@@ -376,7 +994,7 @@ function loadDeploymentHistory(historyPath) {
|
|
|
376
994
|
const content = readFileSync(historyPath, 'utf8');
|
|
377
995
|
return JSON.parse(content);
|
|
378
996
|
}
|
|
379
|
-
catch
|
|
997
|
+
catch {
|
|
380
998
|
return { deployments: [] };
|
|
381
999
|
}
|
|
382
1000
|
}
|
|
@@ -399,7 +1017,7 @@ function analyzeDeploymentHistory(history, environment) {
|
|
|
399
1017
|
averageDeploymentTime: calculateAverageDeploymentTime(recentDeployments),
|
|
400
1018
|
failurePatterns,
|
|
401
1019
|
environmentStability: assessEnvironmentStability(successRate, rollbackRate),
|
|
402
|
-
recommendedAction: recommendAction(successRate, rollbackRate, failurePatterns.length)
|
|
1020
|
+
recommendedAction: recommendAction(successRate, rollbackRate, failurePatterns.length),
|
|
403
1021
|
};
|
|
404
1022
|
}
|
|
405
1023
|
/**
|
|
@@ -422,7 +1040,7 @@ function analyzeFailurePatterns(failedDeployments) {
|
|
|
422
1040
|
environments: [deployment.environment],
|
|
423
1041
|
lastOccurrence: deployment.timestamp,
|
|
424
1042
|
resolution: suggestResolution(category),
|
|
425
|
-
preventable: isPreventable(category)
|
|
1043
|
+
preventable: isPreventable(category),
|
|
426
1044
|
});
|
|
427
1045
|
}
|
|
428
1046
|
}
|
|
@@ -436,21 +1054,123 @@ async function performFullAudit(args, projectPath, historyPath) {
|
|
|
436
1054
|
// Combine all validations
|
|
437
1055
|
const testResult = await performTestValidation(args, projectPath);
|
|
438
1056
|
const historyResult = await performDeploymentHistoryAnalysis(args, historyPath);
|
|
1057
|
+
// Smart Code Linking - Enhanced deployment readiness with ADR analysis
|
|
1058
|
+
let smartCodeAnalysis = '';
|
|
1059
|
+
let adrComplianceResult = testResult.adrComplianceResult;
|
|
1060
|
+
if (args.requireAdrCompliance) {
|
|
1061
|
+
try {
|
|
1062
|
+
// Discover ADRs in the project
|
|
1063
|
+
const { discoverAdrsInDirectory } = await import('../utils/adr-discovery.js');
|
|
1064
|
+
const adrDirectory = 'docs/adrs';
|
|
1065
|
+
const discoveryResult = await discoverAdrsInDirectory(adrDirectory, true, projectPath);
|
|
1066
|
+
if (discoveryResult.adrs.length > 0) {
|
|
1067
|
+
// Combine all ADR content for Smart Code Linking analysis
|
|
1068
|
+
const combinedAdrContent = discoveryResult.adrs
|
|
1069
|
+
.map(adr => `# ${adr.title}\n${adr.content || ''}`)
|
|
1070
|
+
.join('\n\n');
|
|
1071
|
+
const relatedCodeResult = await findRelatedCode('deployment-readiness-analysis', combinedAdrContent, projectPath, {
|
|
1072
|
+
useAI: true,
|
|
1073
|
+
useRipgrep: true,
|
|
1074
|
+
maxFiles: 25,
|
|
1075
|
+
includeContent: false,
|
|
1076
|
+
});
|
|
1077
|
+
// Enhanced ADR compliance analysis with related code context
|
|
1078
|
+
const deploymentCriticalFiles = relatedCodeResult.relatedFiles.filter(file => {
|
|
1079
|
+
const deploymentKeywords = [
|
|
1080
|
+
'deploy',
|
|
1081
|
+
'config',
|
|
1082
|
+
'env',
|
|
1083
|
+
'docker',
|
|
1084
|
+
'k8s',
|
|
1085
|
+
'terraform',
|
|
1086
|
+
'ci',
|
|
1087
|
+
'cd',
|
|
1088
|
+
];
|
|
1089
|
+
return deploymentKeywords.some(keyword => file.path.toLowerCase().includes(keyword) ||
|
|
1090
|
+
file.directory.toLowerCase().includes(keyword));
|
|
1091
|
+
});
|
|
1092
|
+
adrComplianceResult = {
|
|
1093
|
+
score: Math.min(100, 70 + relatedCodeResult.confidence * 30),
|
|
1094
|
+
compliantAdrs: discoveryResult.adrs.length,
|
|
1095
|
+
totalAdrs: discoveryResult.adrs.length,
|
|
1096
|
+
missingImplementations: deploymentCriticalFiles.length === 0
|
|
1097
|
+
? ['Deployment-specific implementations not found in related code']
|
|
1098
|
+
: [],
|
|
1099
|
+
recommendations: [
|
|
1100
|
+
...(deploymentCriticalFiles.length > 0
|
|
1101
|
+
? [`Found ${deploymentCriticalFiles.length} deployment-critical files linked to ADRs`]
|
|
1102
|
+
: ['Consider documenting deployment procedures in ADRs']),
|
|
1103
|
+
...(relatedCodeResult.relatedFiles.length > 10
|
|
1104
|
+
? ['High code-ADR linkage indicates good architectural documentation']
|
|
1105
|
+
: ['Consider improving ADR-to-code traceability']),
|
|
1106
|
+
...(relatedCodeResult.confidence > 0.8
|
|
1107
|
+
? ['Strong architectural alignment detected between ADRs and implementation']
|
|
1108
|
+
: ['Review ADR implementation alignment before deployment']),
|
|
1109
|
+
],
|
|
1110
|
+
};
|
|
1111
|
+
smartCodeAnalysis = `
|
|
1112
|
+
|
|
1113
|
+
## 🔗 Smart Code Linking - Deployment Analysis
|
|
1114
|
+
|
|
1115
|
+
**ADR Discovery**: Found ${discoveryResult.adrs.length} architectural decision records
|
|
1116
|
+
**Related Code Files**: ${relatedCodeResult.relatedFiles.length} files linked to ADRs
|
|
1117
|
+
**Deployment-Critical Files**: ${deploymentCriticalFiles.length} files identified
|
|
1118
|
+
|
|
1119
|
+
### Deployment-Critical Code Analysis
|
|
1120
|
+
${deploymentCriticalFiles.length > 0
|
|
1121
|
+
? deploymentCriticalFiles
|
|
1122
|
+
.slice(0, 5)
|
|
1123
|
+
.map((file, index) => `${index + 1}. **${file.path}** - ${file.extension} file (${file.size} bytes)`)
|
|
1124
|
+
.join('\n')
|
|
1125
|
+
: '*No deployment-specific files found in ADR-related code*'}
|
|
1126
|
+
|
|
1127
|
+
### Architectural Alignment
|
|
1128
|
+
- **ADR-Code Confidence**: ${(relatedCodeResult.confidence * 100).toFixed(1)}%
|
|
1129
|
+
- **Keywords Used**: ${relatedCodeResult.keywords.join(', ')}
|
|
1130
|
+
- **Implementation Coverage**: ${relatedCodeResult.relatedFiles.length > 0 ? 'Adequate' : 'Needs Review'}
|
|
1131
|
+
|
|
1132
|
+
**Deployment Impact**: ${deploymentCriticalFiles.length > 0
|
|
1133
|
+
? 'ADR-guided deployment files found - architectural decisions are implemented'
|
|
1134
|
+
: 'Limited deployment-specific code found - verify manual deployment procedures'}
|
|
1135
|
+
`;
|
|
1136
|
+
}
|
|
1137
|
+
else {
|
|
1138
|
+
smartCodeAnalysis = `
|
|
1139
|
+
|
|
1140
|
+
## 🔗 Smart Code Linking - Deployment Analysis
|
|
1141
|
+
|
|
1142
|
+
**Status**: No ADRs found in project
|
|
1143
|
+
**Recommendation**: Consider creating ADRs to document deployment architecture and decisions
|
|
1144
|
+
**Impact**: Proceeding with deployment readiness check without architectural guidance
|
|
1145
|
+
`;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
catch (error) {
|
|
1149
|
+
console.warn('[WARNING] Smart Code Linking for deployment analysis failed:', error);
|
|
1150
|
+
smartCodeAnalysis = `
|
|
1151
|
+
|
|
1152
|
+
## 🔗 Smart Code Linking - Deployment Analysis
|
|
1153
|
+
|
|
1154
|
+
**Status**: ⚠️ ADR analysis failed - continuing with standard deployment checks
|
|
1155
|
+
**Error**: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
1156
|
+
`;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
439
1159
|
const allBlockers = [
|
|
440
1160
|
...testResult.criticalBlockers,
|
|
441
1161
|
...testResult.testFailureBlockers,
|
|
442
|
-
...historyResult.deploymentHistoryBlockers
|
|
1162
|
+
...historyResult.deploymentHistoryBlockers,
|
|
443
1163
|
];
|
|
444
1164
|
const overallScore = (testResult.overallScore + historyResult.overallScore) / 2;
|
|
445
1165
|
const isReady = allBlockers.length === 0;
|
|
446
|
-
|
|
1166
|
+
const result = {
|
|
447
1167
|
isDeploymentReady: isReady,
|
|
448
1168
|
overallScore,
|
|
449
1169
|
confidence: Math.min(testResult.confidence, historyResult.confidence),
|
|
450
1170
|
codeQualityAnalysis: testResult.codeQualityAnalysis,
|
|
451
1171
|
testValidationResult: testResult.testValidationResult,
|
|
452
1172
|
deploymentHistoryAnalysis: historyResult.deploymentHistoryAnalysis,
|
|
453
|
-
adrComplianceResult
|
|
1173
|
+
adrComplianceResult,
|
|
454
1174
|
criticalBlockers: allBlockers.filter(b => b.severity === 'critical'),
|
|
455
1175
|
testFailureBlockers: testResult.testFailureBlockers,
|
|
456
1176
|
deploymentHistoryBlockers: historyResult.deploymentHistoryBlockers,
|
|
@@ -458,8 +1178,10 @@ async function performFullAudit(args, projectPath, historyPath) {
|
|
|
458
1178
|
todoTasksCreated: [],
|
|
459
1179
|
healthScoreUpdate: {},
|
|
460
1180
|
gitPushStatus: isReady ? 'allowed' : 'blocked',
|
|
461
|
-
overrideStatus: {}
|
|
1181
|
+
overrideStatus: {},
|
|
1182
|
+
smartCodeAnalysis, // Include Smart Code Linking analysis
|
|
462
1183
|
};
|
|
1184
|
+
return result;
|
|
463
1185
|
}
|
|
464
1186
|
/**
|
|
465
1187
|
* Perform emergency override
|
|
@@ -473,9 +1195,11 @@ async function performEmergencyOverride(args, projectPath) {
|
|
|
473
1195
|
timestamp: new Date().toISOString(),
|
|
474
1196
|
justification: args.businessJustification || 'No justification provided',
|
|
475
1197
|
environment: args.targetEnvironment,
|
|
476
|
-
overriddenBy: process.env['USER'] || 'unknown'
|
|
1198
|
+
overriddenBy: process.env['USER'] || 'unknown',
|
|
477
1199
|
};
|
|
478
|
-
const
|
|
1200
|
+
const projectName = basename(projectPath);
|
|
1201
|
+
const cacheDir = join(os.tmpdir(), projectName, 'cache');
|
|
1202
|
+
const overridePath = join(cacheDir, 'emergency-overrides.json');
|
|
479
1203
|
const overrides = existsSync(overridePath) ? JSON.parse(readFileSync(overridePath, 'utf8')) : [];
|
|
480
1204
|
overrides.push(overrideRecord);
|
|
481
1205
|
writeFileSync(overridePath, JSON.stringify(overrides, null, 2));
|
|
@@ -483,10 +1207,37 @@ async function performEmergencyOverride(args, projectPath) {
|
|
|
483
1207
|
isDeploymentReady: true,
|
|
484
1208
|
overallScore: 100,
|
|
485
1209
|
confidence: 50, // Lower confidence for overrides
|
|
486
|
-
codeQualityAnalysis:
|
|
487
|
-
testValidationResult: {
|
|
488
|
-
|
|
489
|
-
|
|
1210
|
+
codeQualityAnalysis: createDefaultCodeQualityAnalysis(100, 0, 0),
|
|
1211
|
+
testValidationResult: {
|
|
1212
|
+
testSuitesExecuted: [],
|
|
1213
|
+
overallTestStatus: 'not_run',
|
|
1214
|
+
failureCount: 0,
|
|
1215
|
+
coveragePercentage: 0,
|
|
1216
|
+
requiredSuitesMissing: [],
|
|
1217
|
+
criticalTestFailures: [],
|
|
1218
|
+
testExecutionTime: 0,
|
|
1219
|
+
lastTestRun: '',
|
|
1220
|
+
},
|
|
1221
|
+
deploymentHistoryAnalysis: {
|
|
1222
|
+
recentDeployments: [],
|
|
1223
|
+
successRate: 100,
|
|
1224
|
+
rollbackRate: 0,
|
|
1225
|
+
averageDeploymentTime: 0,
|
|
1226
|
+
failurePatterns: [],
|
|
1227
|
+
environmentStability: {
|
|
1228
|
+
stabilityScore: 50,
|
|
1229
|
+
riskLevel: 'medium',
|
|
1230
|
+
recommendation: 'Monitor closely post-deployment',
|
|
1231
|
+
},
|
|
1232
|
+
recommendedAction: 'proceed',
|
|
1233
|
+
},
|
|
1234
|
+
adrComplianceResult: {
|
|
1235
|
+
score: 100,
|
|
1236
|
+
compliantAdrs: 0,
|
|
1237
|
+
totalAdrs: 0,
|
|
1238
|
+
missingImplementations: [],
|
|
1239
|
+
recommendations: [],
|
|
1240
|
+
},
|
|
490
1241
|
criticalBlockers: [],
|
|
491
1242
|
testFailureBlockers: [],
|
|
492
1243
|
deploymentHistoryBlockers: [],
|
|
@@ -494,14 +1245,14 @@ async function performEmergencyOverride(args, projectPath) {
|
|
|
494
1245
|
todoTasksCreated: [],
|
|
495
1246
|
healthScoreUpdate: {},
|
|
496
1247
|
gitPushStatus: 'allowed',
|
|
497
|
-
overrideStatus: overrideRecord
|
|
1248
|
+
overrideStatus: overrideRecord,
|
|
498
1249
|
};
|
|
499
1250
|
}
|
|
500
1251
|
/**
|
|
501
1252
|
* Helper functions
|
|
502
1253
|
*/
|
|
503
1254
|
function calculateTestScore(testResult, _args) {
|
|
504
|
-
const failureScore = Math.max(0, 100 -
|
|
1255
|
+
const failureScore = Math.max(0, 100 - testResult.failureCount * 20);
|
|
505
1256
|
const coverageScore = testResult.coveragePercentage;
|
|
506
1257
|
return Math.min(failureScore, coverageScore);
|
|
507
1258
|
}
|
|
@@ -525,7 +1276,7 @@ function assessEnvironmentStability(successRate, rollbackRate) {
|
|
|
525
1276
|
return {
|
|
526
1277
|
stabilityScore,
|
|
527
1278
|
riskLevel,
|
|
528
|
-
recommendation: riskLevel === 'low' ? 'Proceed with deployment' : 'Investigate before deployment'
|
|
1279
|
+
recommendation: riskLevel === 'low' ? 'Proceed with deployment' : 'Investigate before deployment',
|
|
529
1280
|
};
|
|
530
1281
|
}
|
|
531
1282
|
function recommendAction(successRate, rollbackRate, failurePatternCount) {
|
|
@@ -544,7 +1295,7 @@ function categorizeFailure(failureReason) {
|
|
|
544
1295
|
{ regex: /dependency.*error/i, category: 'Dependency Issues' },
|
|
545
1296
|
{ regex: /timeout/i, category: 'Timeout Issues' },
|
|
546
1297
|
{ regex: /permission.*denied/i, category: 'Permission Issues' },
|
|
547
|
-
{ regex: /out.*of.*memory/i, category: 'Resource Issues' }
|
|
1298
|
+
{ regex: /out.*of.*memory/i, category: 'Resource Issues' },
|
|
548
1299
|
];
|
|
549
1300
|
for (const pattern of patterns) {
|
|
550
1301
|
if (pattern.regex.test(failureReason)) {
|
|
@@ -562,7 +1313,7 @@ function suggestResolution(category) {
|
|
|
562
1313
|
'Dependency Issues': 'Update and verify package dependencies',
|
|
563
1314
|
'Timeout Issues': 'Optimize performance and increase timeout values',
|
|
564
1315
|
'Permission Issues': 'Check file and directory permissions',
|
|
565
|
-
'Resource Issues': 'Increase available memory and resources'
|
|
1316
|
+
'Resource Issues': 'Increase available memory and resources',
|
|
566
1317
|
};
|
|
567
1318
|
return resolutions[category] || 'Investigate failure details and resolve underlying issue';
|
|
568
1319
|
}
|
|
@@ -571,7 +1322,7 @@ function isPreventable(category) {
|
|
|
571
1322
|
'Test Failures',
|
|
572
1323
|
'Environment Configuration',
|
|
573
1324
|
'Build Failures',
|
|
574
|
-
'Dependency Issues'
|
|
1325
|
+
'Dependency Issues',
|
|
575
1326
|
];
|
|
576
1327
|
return preventableCategories.includes(category);
|
|
577
1328
|
}
|
|
@@ -588,7 +1339,8 @@ function generateDeploymentReadinessResponse(result, args) {
|
|
|
588
1339
|
}
|
|
589
1340
|
function generateSuccessResponse(result, args) {
|
|
590
1341
|
return validateMcpResponse({
|
|
591
|
-
content: [
|
|
1342
|
+
content: [
|
|
1343
|
+
{
|
|
592
1344
|
type: 'text',
|
|
593
1345
|
text: `✅ **DEPLOYMENT READY - All Gates Passed**
|
|
594
1346
|
|
|
@@ -597,6 +1349,7 @@ function generateSuccessResponse(result, args) {
|
|
|
597
1349
|
- **Readiness Score**: ${result.overallScore}%
|
|
598
1350
|
- **Confidence**: ${result.confidence}%
|
|
599
1351
|
- **Target Environment**: ${args.targetEnvironment}
|
|
1352
|
+
- **Fast File Discovery**: ✅ Enhanced with fast-glob
|
|
600
1353
|
|
|
601
1354
|
## 🧪 Test Validation
|
|
602
1355
|
- **Test Status**: ✅ ${result.testValidationResult.overallTestStatus.toUpperCase()}
|
|
@@ -609,55 +1362,76 @@ function generateSuccessResponse(result, args) {
|
|
|
609
1362
|
- **Rollback Rate**: ${result.deploymentHistoryAnalysis.rollbackRate}%
|
|
610
1363
|
- **Environment Stability**: ${result.deploymentHistoryAnalysis.environmentStability.riskLevel}
|
|
611
1364
|
|
|
1365
|
+
## 🏛️ ADR Compliance
|
|
1366
|
+
- **Compliance Score**: ${result.adrComplianceResult.score}%
|
|
1367
|
+
- **ADRs Analyzed**: ${result.adrComplianceResult.compliantAdrs}/${result.adrComplianceResult.totalAdrs}
|
|
1368
|
+
- **Missing Implementations**: ${result.adrComplianceResult.missingImplementations.length} items
|
|
1369
|
+
|
|
1370
|
+
${result.smartCodeAnalysis || ''}
|
|
1371
|
+
|
|
612
1372
|
## 🚀 Deployment Approved
|
|
613
1373
|
${args.triggerSmartGitPush ? 'Triggering smart git push...' : 'Ready to proceed with deployment'}
|
|
614
1374
|
|
|
615
|
-
${result.warnings.length > 0
|
|
1375
|
+
${result.warnings.length > 0
|
|
1376
|
+
? `
|
|
616
1377
|
## ⚠️ Warnings
|
|
617
1378
|
${result.warnings.map(w => `- ${w}`).join('\n')}
|
|
618
|
-
`
|
|
1379
|
+
`
|
|
1380
|
+
: ''}
|
|
619
1381
|
|
|
620
|
-
**✅ DEPLOYMENT CAN PROCEED SAFELY
|
|
621
|
-
}
|
|
1382
|
+
**✅ DEPLOYMENT CAN PROCEED SAFELY**`,
|
|
1383
|
+
},
|
|
1384
|
+
],
|
|
622
1385
|
});
|
|
623
1386
|
}
|
|
624
1387
|
function generateBlockedResponse(result, args) {
|
|
625
1388
|
return validateMcpResponse({
|
|
626
|
-
content: [
|
|
1389
|
+
content: [
|
|
1390
|
+
{
|
|
627
1391
|
type: 'text',
|
|
628
|
-
text:
|
|
1392
|
+
text: `# 🚨 DEPLOYMENT BLOCKED - Critical Issues Detected
|
|
629
1393
|
|
|
630
|
-
##
|
|
631
|
-
- **
|
|
632
|
-
- **Readiness Score**: ${result.overallScore}%
|
|
1394
|
+
## ⚠️ Deployment Readiness: ${result.isDeploymentReady ? '✅ READY' : '❌ BLOCKED'}
|
|
1395
|
+
- **Overall Score**: ${result.overallScore}/100
|
|
633
1396
|
- **Confidence**: ${result.confidence}%
|
|
634
1397
|
- **Target Environment**: ${args.targetEnvironment}
|
|
1398
|
+
- **Tree-sitter Analysis**: ${args.enableTreeSitterAnalysis ? '✅ Enhanced' : '❌ Basic'}
|
|
1399
|
+
- **Fast File Discovery**: ✅ Enhanced with fast-glob
|
|
1400
|
+
- **Smart Code Linking**: ${args.requireAdrCompliance ? '✅ ADR Analysis Enabled' : '❌ Disabled'}
|
|
635
1401
|
|
|
636
1402
|
## 🧪 Test Validation Issues
|
|
637
|
-
${result.testFailureBlockers.length > 0
|
|
1403
|
+
${result.testFailureBlockers.length > 0
|
|
1404
|
+
? `
|
|
638
1405
|
**Test Failures**: ${result.testValidationResult.failureCount} failures detected
|
|
639
1406
|
**Coverage**: ${result.testValidationResult.coveragePercentage}% (Required: ${args.requireTestCoverage}%)
|
|
640
1407
|
|
|
641
1408
|
### Critical Test Failures:
|
|
642
1409
|
${result.testValidationResult.criticalTestFailures.map(f => `- ❌ ${f.testSuite}: ${f.testName}`).join('\n')}
|
|
643
|
-
`
|
|
1410
|
+
`
|
|
1411
|
+
: '✅ Tests passing'}
|
|
644
1412
|
|
|
645
1413
|
## 📊 Deployment History Issues
|
|
646
|
-
${result.deploymentHistoryBlockers.length > 0
|
|
1414
|
+
${result.deploymentHistoryBlockers.length > 0
|
|
1415
|
+
? `
|
|
647
1416
|
**Success Rate**: ${result.deploymentHistoryAnalysis.successRate}% (Required: ${args.deploymentSuccessThreshold}%)
|
|
648
1417
|
**Rollback Rate**: ${result.deploymentHistoryAnalysis.rollbackRate}% (Threshold: ${args.rollbackFrequencyThreshold}%)
|
|
649
1418
|
|
|
650
1419
|
### Recent Failure Patterns:
|
|
651
1420
|
${result.deploymentHistoryAnalysis.failurePatterns.map(p => `- **${p.pattern}**: ${p.frequency} occurrences`).join('\n')}
|
|
652
|
-
`
|
|
1421
|
+
`
|
|
1422
|
+
: '✅ Deployment history stable'}
|
|
1423
|
+
|
|
1424
|
+
${result.smartCodeAnalysis || ''}
|
|
653
1425
|
|
|
654
1426
|
## 🚨 Critical Blockers (Must Fix Before Deployment)
|
|
655
|
-
${result.criticalBlockers
|
|
1427
|
+
${result.criticalBlockers
|
|
1428
|
+
.map(blocker => `
|
|
656
1429
|
### ${blocker.category.toUpperCase()}: ${blocker.title}
|
|
657
1430
|
- **Impact**: ${blocker.impact}
|
|
658
1431
|
- **Resolution**: ${blocker.resolutionSteps.join(' → ')}
|
|
659
1432
|
- **Estimated Time**: ${blocker.estimatedResolutionTime}
|
|
660
|
-
`)
|
|
1433
|
+
`)
|
|
1434
|
+
.join('\n')}
|
|
661
1435
|
|
|
662
1436
|
## 🛠️ Immediate Actions Required
|
|
663
1437
|
|
|
@@ -683,14 +1457,164 @@ npm run test:coverage
|
|
|
683
1457
|
deployment_readiness --operation full_audit --target-environment ${args.targetEnvironment}
|
|
684
1458
|
\`\`\`
|
|
685
1459
|
|
|
686
|
-
|
|
687
|
-
For critical fixes only:
|
|
1460
|
+
### 3. Emergency Override (If Justified)
|
|
688
1461
|
\`\`\`bash
|
|
689
|
-
|
|
1462
|
+
# Only if business critical and approved
|
|
1463
|
+
npm run deploy:emergency -- --justification="Critical security fix"
|
|
690
1464
|
\`\`\`
|
|
691
1465
|
|
|
692
|
-
|
|
693
|
-
|
|
1466
|
+
**⚠️ WARNING**: Emergency overrides bypass safety checks. Use only when absolutely necessary.
|
|
1467
|
+
`,
|
|
1468
|
+
},
|
|
1469
|
+
],
|
|
694
1470
|
});
|
|
695
1471
|
}
|
|
1472
|
+
/**
|
|
1473
|
+
* Create default CodeQualityAnalysis structure
|
|
1474
|
+
*/
|
|
1475
|
+
function createDefaultCodeQualityAnalysis(qualityScore = 75, productionIndicators = 10, mockIndicators = 2) {
|
|
1476
|
+
return {
|
|
1477
|
+
qualityScore,
|
|
1478
|
+
productionIndicators,
|
|
1479
|
+
mockIndicators,
|
|
1480
|
+
failingFiles: [],
|
|
1481
|
+
recommendations: [],
|
|
1482
|
+
securityIssues: [],
|
|
1483
|
+
architecturalViolations: [],
|
|
1484
|
+
codeComplexity: {
|
|
1485
|
+
averageComplexity: 0,
|
|
1486
|
+
highComplexityFiles: [],
|
|
1487
|
+
totalFunctions: 0,
|
|
1488
|
+
},
|
|
1489
|
+
dependencyAnalysis: {
|
|
1490
|
+
dangerousImports: [],
|
|
1491
|
+
frameworksDetected: [],
|
|
1492
|
+
securityLibraries: [],
|
|
1493
|
+
},
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
/**
|
|
1497
|
+
* Perform tree-sitter enhanced code quality analysis
|
|
1498
|
+
*/
|
|
1499
|
+
async function analyzeCodeQualityWithTreeSitter(projectPath, enableTreeSitter, _languages) {
|
|
1500
|
+
const baseAnalysis = createDefaultCodeQualityAnalysis();
|
|
1501
|
+
if (!enableTreeSitter) {
|
|
1502
|
+
return baseAnalysis;
|
|
1503
|
+
}
|
|
1504
|
+
try {
|
|
1505
|
+
const analyzer = new TreeSitterAnalyzer();
|
|
1506
|
+
// Use fast-glob based file discovery for enhanced performance
|
|
1507
|
+
const findResult = await findFiles(projectPath, ['**/*.{ts,js,py,yml,yaml,tf,hcl,sh}']);
|
|
1508
|
+
// Analyze files (limit to first 20 for performance)
|
|
1509
|
+
const sourceFiles = findResult.files.map(f => f.path);
|
|
1510
|
+
const filesToAnalyze = sourceFiles.slice(0, 20);
|
|
1511
|
+
let totalComplexity = 0;
|
|
1512
|
+
let totalFunctions = 0;
|
|
1513
|
+
const highComplexityFiles = [];
|
|
1514
|
+
for (const filePath of filesToAnalyze) {
|
|
1515
|
+
try {
|
|
1516
|
+
const analysis = await analyzer.analyzeFile(filePath);
|
|
1517
|
+
// Security issues
|
|
1518
|
+
if (analysis.hasSecrets && analysis.secrets.length > 0) {
|
|
1519
|
+
analysis.secrets.forEach(secret => {
|
|
1520
|
+
baseAnalysis.securityIssues.push({
|
|
1521
|
+
type: secret.type,
|
|
1522
|
+
severity: secret.confidence > 0.8 ? 'high' : secret.confidence > 0.6 ? 'medium' : 'low',
|
|
1523
|
+
message: `${secret.type} detected: ${secret.context}`,
|
|
1524
|
+
file: filePath,
|
|
1525
|
+
line: secret.location.line,
|
|
1526
|
+
});
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
// Security issues from general analysis
|
|
1530
|
+
if (analysis.securityIssues && analysis.securityIssues.length > 0) {
|
|
1531
|
+
analysis.securityIssues.forEach(issue => {
|
|
1532
|
+
baseAnalysis.securityIssues.push({
|
|
1533
|
+
type: issue.type,
|
|
1534
|
+
severity: issue.severity,
|
|
1535
|
+
message: issue.message,
|
|
1536
|
+
file: filePath,
|
|
1537
|
+
line: issue.location.line,
|
|
1538
|
+
});
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
// Dangerous imports
|
|
1542
|
+
if (analysis.imports) {
|
|
1543
|
+
analysis.imports.forEach(imp => {
|
|
1544
|
+
if (imp.isDangerous) {
|
|
1545
|
+
baseAnalysis.dependencyAnalysis.dangerousImports.push({
|
|
1546
|
+
module: imp.module,
|
|
1547
|
+
file: filePath,
|
|
1548
|
+
reason: imp.reason || 'Potentially dangerous import',
|
|
1549
|
+
});
|
|
1550
|
+
}
|
|
1551
|
+
// Detect frameworks
|
|
1552
|
+
const frameworks = ['express', 'react', 'vue', 'angular', 'fastapi', 'django', 'flask'];
|
|
1553
|
+
frameworks.forEach(framework => {
|
|
1554
|
+
if (imp.module.toLowerCase().includes(framework) &&
|
|
1555
|
+
!baseAnalysis.dependencyAnalysis.frameworksDetected.includes(framework)) {
|
|
1556
|
+
baseAnalysis.dependencyAnalysis.frameworksDetected.push(framework);
|
|
1557
|
+
}
|
|
1558
|
+
});
|
|
1559
|
+
// Detect security libraries
|
|
1560
|
+
const securityLibs = ['bcrypt', 'crypto', 'jwt', 'passport', 'helmet'];
|
|
1561
|
+
securityLibs.forEach(lib => {
|
|
1562
|
+
if (imp.module.toLowerCase().includes(lib) &&
|
|
1563
|
+
!baseAnalysis.dependencyAnalysis.securityLibraries.includes(lib)) {
|
|
1564
|
+
baseAnalysis.dependencyAnalysis.securityLibraries.push(lib);
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
// Function complexity analysis
|
|
1570
|
+
if (analysis.functions) {
|
|
1571
|
+
analysis.functions.forEach(func => {
|
|
1572
|
+
totalFunctions++;
|
|
1573
|
+
totalComplexity += func.complexity;
|
|
1574
|
+
if (func.complexity > 10) {
|
|
1575
|
+
highComplexityFiles.push(`${filePath}:${func.name} (complexity: ${func.complexity})`);
|
|
1576
|
+
}
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
// Architectural violations (basic detection)
|
|
1580
|
+
if (analysis.architecturalViolations && analysis.architecturalViolations.length > 0) {
|
|
1581
|
+
analysis.architecturalViolations.forEach(violation => {
|
|
1582
|
+
baseAnalysis.architecturalViolations.push(`${filePath}: ${violation.message}`);
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
catch (error) {
|
|
1587
|
+
// Skip files that can't be analyzed
|
|
1588
|
+
console.warn(`Could not analyze file ${filePath}:`, error);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
// Update complexity metrics
|
|
1592
|
+
baseAnalysis.codeComplexity = {
|
|
1593
|
+
averageComplexity: totalFunctions > 0 ? totalComplexity / totalFunctions : 0,
|
|
1594
|
+
highComplexityFiles: highComplexityFiles.slice(0, 10), // Limit to top 10
|
|
1595
|
+
totalFunctions,
|
|
1596
|
+
};
|
|
1597
|
+
// Calculate enhanced quality score
|
|
1598
|
+
let qualityScore = 85; // Base score
|
|
1599
|
+
// Deduct for security issues
|
|
1600
|
+
const criticalSecurity = baseAnalysis.securityIssues.filter(i => i.severity === 'critical').length;
|
|
1601
|
+
const highSecurity = baseAnalysis.securityIssues.filter(i => i.severity === 'high').length;
|
|
1602
|
+
qualityScore -= criticalSecurity * 20 + highSecurity * 10;
|
|
1603
|
+
// Deduct for dangerous imports
|
|
1604
|
+
qualityScore -= Math.min(baseAnalysis.dependencyAnalysis.dangerousImports.length * 5, 20);
|
|
1605
|
+
// Deduct for high complexity
|
|
1606
|
+
qualityScore -= Math.min(highComplexityFiles.length * 2, 15);
|
|
1607
|
+
// Bonus for security libraries
|
|
1608
|
+
qualityScore += Math.min(baseAnalysis.dependencyAnalysis.securityLibraries.length * 2, 10);
|
|
1609
|
+
baseAnalysis.qualityScore = Math.max(0, Math.min(100, qualityScore));
|
|
1610
|
+
// Update production/mock indicators based on analysis
|
|
1611
|
+
baseAnalysis.productionIndicators = Math.max(10, baseAnalysis.qualityScore - 20);
|
|
1612
|
+
baseAnalysis.mockIndicators = Math.max(0, 100 - baseAnalysis.qualityScore) / 10;
|
|
1613
|
+
return baseAnalysis;
|
|
1614
|
+
}
|
|
1615
|
+
catch (error) {
|
|
1616
|
+
console.warn('Tree-sitter analysis failed, using basic analysis:', error);
|
|
1617
|
+
return baseAnalysis;
|
|
1618
|
+
}
|
|
1619
|
+
}
|
|
696
1620
|
//# sourceMappingURL=deployment-readiness-tool.js.map
|