mcp-adr-analysis-server 2.0.21 โ 2.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1380 -781
- package/dist/src/index.js.map +1 -1
- package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -1
- package/dist/src/tools/adr-suggestion-tool.js +32 -30
- package/dist/src/tools/adr-suggestion-tool.js.map +1 -1
- package/dist/src/tools/content-masking-tool.d.ts +4 -0
- package/dist/src/tools/content-masking-tool.d.ts.map +1 -1
- package/dist/src/tools/content-masking-tool.js +531 -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 +741 -79
- 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/mcp-planning-tool.d.ts.map +1 -1
- package/dist/src/tools/mcp-planning-tool.js +298 -173
- 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/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 +177 -223
- package/dist/src/tools/smart-git-push-tool.js.map +1 -1
- package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts +20 -11
- package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts.map +1 -1
- package/dist/src/tools/troubleshoot-guided-workflow-tool.js +506 -22
- package/dist/src/tools/troubleshoot-guided-workflow-tool.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/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/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/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/interactive-approval.d.ts +1 -1
- package/dist/src/utils/interactive-approval.d.ts.map +1 -1
- package/dist/src/utils/interactive-approval.js +20 -16
- package/dist/src/utils/interactive-approval.js.map +1 -1
- package/dist/src/utils/knowledge-graph-manager.d.ts +23 -1
- package/dist/src/utils/knowledge-graph-manager.d.ts.map +1 -1
- package/dist/src/utils/knowledge-graph-manager.js +297 -69
- package/dist/src/utils/knowledge-graph-manager.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 +848 -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 +834 -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 +481 -0
- package/dist/src/utils/memory-relationship-mapper.js.map +1 -0
- package/dist/src/utils/memory-rollback-manager.d.ts +93 -0
- package/dist/src/utils/memory-rollback-manager.d.ts.map +1 -0
- package/dist/src/utils/memory-rollback-manager.js +542 -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/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/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/package.json +22 -6
- 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/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,20 +1,23 @@
|
|
|
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';
|
|
@@ -23,34 +26,59 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
|
23
26
|
import { join } from 'path';
|
|
24
27
|
import { validateMcpResponse } from '../utils/mcp-response-validator.js';
|
|
25
28
|
import { jsonSafeError } from '../utils/json-safe.js';
|
|
29
|
+
import { MemoryEntityManager } from '../utils/memory-entity-manager.js';
|
|
30
|
+
import { EnhancedLogger } from '../utils/enhanced-logging.js';
|
|
26
31
|
// Core schemas
|
|
27
32
|
const DeploymentReadinessSchema = z.object({
|
|
28
|
-
operation: z
|
|
33
|
+
operation: z
|
|
34
|
+
.enum([
|
|
29
35
|
'check_readiness', // Full deployment readiness check
|
|
30
36
|
'validate_production', // Production-specific validation
|
|
31
37
|
'test_validation', // Test execution and failure analysis
|
|
32
38
|
'deployment_history', // Deployment history analysis
|
|
33
39
|
'full_audit', // Comprehensive audit (all checks)
|
|
34
|
-
'emergency_override' // Emergency bypass with justification
|
|
35
|
-
])
|
|
40
|
+
'emergency_override', // Emergency bypass with justification
|
|
41
|
+
])
|
|
42
|
+
.describe('Operation to perform'),
|
|
36
43
|
// Core Configuration
|
|
37
44
|
projectPath: z.string().optional().describe('Project root path'),
|
|
38
|
-
targetEnvironment: z
|
|
45
|
+
targetEnvironment: z
|
|
46
|
+
.enum(['staging', 'production', 'integration'])
|
|
47
|
+
.default('production')
|
|
48
|
+
.describe('Target deployment environment'),
|
|
39
49
|
strictMode: z.boolean().default(true).describe('Enable strict validation (recommended)'),
|
|
40
50
|
// Code Quality Gates
|
|
41
|
-
allowMockCode: z
|
|
42
|
-
|
|
51
|
+
allowMockCode: z
|
|
52
|
+
.boolean()
|
|
53
|
+
.default(false)
|
|
54
|
+
.describe('Allow mock code in deployment (NOT RECOMMENDED)'),
|
|
55
|
+
productionCodeThreshold: z
|
|
56
|
+
.number()
|
|
57
|
+
.default(85)
|
|
58
|
+
.describe('Minimum production code quality score (0-100)'),
|
|
43
59
|
mockCodeMaxAllowed: z.number().default(0).describe('Maximum mock code indicators allowed'),
|
|
44
60
|
// Test Failure Gates
|
|
45
|
-
maxTestFailures: z
|
|
61
|
+
maxTestFailures: z
|
|
62
|
+
.number()
|
|
63
|
+
.default(0)
|
|
64
|
+
.describe('Maximum test failures allowed (0 = zero tolerance)'),
|
|
46
65
|
requireTestCoverage: z.number().default(80).describe('Minimum test coverage percentage required'),
|
|
47
66
|
blockOnFailingTests: z.boolean().default(true).describe('Block deployment if tests are failing'),
|
|
48
|
-
testSuiteRequired: z
|
|
67
|
+
testSuiteRequired: z
|
|
68
|
+
.array(z.string())
|
|
69
|
+
.default([])
|
|
70
|
+
.describe('Required test suites that must pass'),
|
|
49
71
|
// Deployment History Gates
|
|
50
72
|
maxRecentFailures: z.number().default(2).describe('Maximum recent deployment failures allowed'),
|
|
51
|
-
deploymentSuccessThreshold: z
|
|
73
|
+
deploymentSuccessThreshold: z
|
|
74
|
+
.number()
|
|
75
|
+
.default(80)
|
|
76
|
+
.describe('Minimum deployment success rate required (%)'),
|
|
52
77
|
blockOnRecentFailures: z.boolean().default(true).describe('Block if recent deployments failed'),
|
|
53
|
-
rollbackFrequencyThreshold: z
|
|
78
|
+
rollbackFrequencyThreshold: z
|
|
79
|
+
.number()
|
|
80
|
+
.default(20)
|
|
81
|
+
.describe('Maximum rollback frequency allowed (%)'),
|
|
54
82
|
// Integration Rules
|
|
55
83
|
requireAdrCompliance: z.boolean().default(true).describe('Require ADR compliance validation'),
|
|
56
84
|
integrateTodoTasks: z.boolean().default(true).describe('Auto-create blocking tasks for issues'),
|
|
@@ -59,8 +87,480 @@ const DeploymentReadinessSchema = z.object({
|
|
|
59
87
|
// Human Override System
|
|
60
88
|
emergencyBypass: z.boolean().default(false).describe('Emergency bypass for critical fixes'),
|
|
61
89
|
businessJustification: z.string().optional().describe('Business justification for overrides'),
|
|
62
|
-
approvalRequired: z.boolean().default(true).describe('Require approval for overrides')
|
|
90
|
+
approvalRequired: z.boolean().default(true).describe('Require approval for overrides'),
|
|
91
|
+
// Memory Integration
|
|
92
|
+
enableMemoryIntegration: z.boolean().default(true).describe('Enable memory entity storage'),
|
|
93
|
+
migrateExistingHistory: z
|
|
94
|
+
.boolean()
|
|
95
|
+
.default(false)
|
|
96
|
+
.describe('Migrate existing deployment history to memory'),
|
|
63
97
|
});
|
|
98
|
+
/**
|
|
99
|
+
* Deployment Memory Manager for tracking deployment assessments and patterns
|
|
100
|
+
*/
|
|
101
|
+
class DeploymentMemoryManager {
|
|
102
|
+
memoryManager;
|
|
103
|
+
logger;
|
|
104
|
+
constructor() {
|
|
105
|
+
this.memoryManager = new MemoryEntityManager();
|
|
106
|
+
this.logger = new EnhancedLogger();
|
|
107
|
+
}
|
|
108
|
+
async initialize() {
|
|
109
|
+
await this.memoryManager.initialize();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Store deployment assessment as memory entity
|
|
113
|
+
*/
|
|
114
|
+
async storeDeploymentAssessment(environment, readinessData, validationResults, projectPath) {
|
|
115
|
+
try {
|
|
116
|
+
const assessmentData = {
|
|
117
|
+
environment: environment,
|
|
118
|
+
readinessScore: readinessData.overallScore / 100, // Convert to 0-1 range
|
|
119
|
+
validationResults: {
|
|
120
|
+
testResults: {
|
|
121
|
+
passed: readinessData.testValidationResult.testSuitesExecuted.reduce((sum, suite) => sum + suite.passedTests, 0),
|
|
122
|
+
failed: readinessData.testValidationResult.failureCount,
|
|
123
|
+
coverage: readinessData.testValidationResult.coveragePercentage / 100, // Convert to 0-1 range
|
|
124
|
+
criticalFailures: readinessData.testValidationResult.criticalTestFailures.map(f => f.testName),
|
|
125
|
+
},
|
|
126
|
+
securityValidation: {
|
|
127
|
+
vulnerabilities: 0, // Default - could be enhanced with actual security scan data
|
|
128
|
+
securityScore: 0.8, // Default - could be enhanced with actual security analysis
|
|
129
|
+
criticalIssues: readinessData.criticalBlockers
|
|
130
|
+
.filter(b => b.category === 'adr_compliance')
|
|
131
|
+
.map(b => b.title),
|
|
132
|
+
},
|
|
133
|
+
performanceValidation: {
|
|
134
|
+
performanceScore: Math.max(0, (readinessData.overallScore - 20) / 80), // Derived from overall score
|
|
135
|
+
bottlenecks: [],
|
|
136
|
+
resourceUtilization: {},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
blockingIssues: [
|
|
140
|
+
...readinessData.criticalBlockers.map(b => ({
|
|
141
|
+
issue: `${b.title}: ${b.description}`,
|
|
142
|
+
severity: b.severity,
|
|
143
|
+
category: this.mapBlockerCategory(b.category),
|
|
144
|
+
resolution: b.resolutionSteps.join('; '),
|
|
145
|
+
estimatedEffort: b.estimatedResolutionTime,
|
|
146
|
+
})),
|
|
147
|
+
...readinessData.testFailureBlockers.map(b => ({
|
|
148
|
+
issue: `${b.title}: ${b.description}`,
|
|
149
|
+
severity: b.severity,
|
|
150
|
+
category: 'test',
|
|
151
|
+
resolution: b.resolutionSteps.join('; '),
|
|
152
|
+
estimatedEffort: b.estimatedResolutionTime,
|
|
153
|
+
})),
|
|
154
|
+
...readinessData.deploymentHistoryBlockers.map(b => ({
|
|
155
|
+
issue: `${b.title}: ${b.description}`,
|
|
156
|
+
severity: b.severity,
|
|
157
|
+
category: 'configuration',
|
|
158
|
+
resolution: b.resolutionSteps.join('; '),
|
|
159
|
+
estimatedEffort: b.estimatedResolutionTime,
|
|
160
|
+
})),
|
|
161
|
+
],
|
|
162
|
+
deploymentStrategy: {
|
|
163
|
+
type: 'rolling', // Default strategy - could be made configurable
|
|
164
|
+
rollbackPlan: 'Automated rollback via deployment pipeline with health check validation',
|
|
165
|
+
monitoringPlan: 'Monitor application metrics, error rates, and performance indicators for 30 minutes post-deployment',
|
|
166
|
+
estimatedDowntime: readinessData.isDeploymentReady
|
|
167
|
+
? '0 minutes (rolling deployment)'
|
|
168
|
+
: 'Cannot deploy - blockers present',
|
|
169
|
+
},
|
|
170
|
+
complianceChecks: {
|
|
171
|
+
adrCompliance: readinessData.adrComplianceResult.score / 100, // Convert to 0-1 range
|
|
172
|
+
regulatoryCompliance: [], // Could be enhanced with actual compliance data
|
|
173
|
+
auditTrail: [
|
|
174
|
+
`Deployment assessment completed at ${new Date().toISOString()}`,
|
|
175
|
+
`Test validation: ${readinessData.testValidationResult.overallTestStatus}`,
|
|
176
|
+
`Overall readiness score: ${readinessData.overallScore}%`,
|
|
177
|
+
`Git push status: ${readinessData.gitPushStatus}`,
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
const entity = await this.memoryManager.upsertEntity({
|
|
182
|
+
type: 'deployment_assessment',
|
|
183
|
+
title: `Deployment Assessment: ${environment} - ${readinessData.isDeploymentReady ? 'READY' : 'BLOCKED'} - ${new Date().toISOString().split('T')[0]}`,
|
|
184
|
+
description: `Deployment readiness assessment for ${environment} environment${readinessData.isDeploymentReady ? ' - APPROVED' : ' - BLOCKED'}`,
|
|
185
|
+
tags: [
|
|
186
|
+
'deployment',
|
|
187
|
+
environment.toLowerCase(),
|
|
188
|
+
'readiness-assessment',
|
|
189
|
+
readinessData.isDeploymentReady ? 'approved' : 'blocked',
|
|
190
|
+
`score-${Math.floor(readinessData.overallScore / 10) * 10}`,
|
|
191
|
+
...(readinessData.criticalBlockers.length > 0 ? ['critical-issues'] : []),
|
|
192
|
+
...(readinessData.testValidationResult.failureCount > 0 ? ['test-failures'] : []),
|
|
193
|
+
...(readinessData.deploymentHistoryAnalysis.rollbackRate > 20
|
|
194
|
+
? ['high-rollback-risk']
|
|
195
|
+
: []),
|
|
196
|
+
],
|
|
197
|
+
assessmentData,
|
|
198
|
+
relationships: [],
|
|
199
|
+
context: {
|
|
200
|
+
projectPhase: 'deployment-validation',
|
|
201
|
+
technicalStack: this.extractTechnicalStack(validationResults),
|
|
202
|
+
environmentalFactors: [environment, projectPath || 'unknown-project'].filter(Boolean),
|
|
203
|
+
stakeholders: ['deployment-team', 'qa-team', 'infrastructure-team'],
|
|
204
|
+
},
|
|
205
|
+
accessPattern: {
|
|
206
|
+
lastAccessed: new Date().toISOString(),
|
|
207
|
+
accessCount: 1,
|
|
208
|
+
accessContext: ['deployment-assessment'],
|
|
209
|
+
},
|
|
210
|
+
evolution: {
|
|
211
|
+
origin: 'created',
|
|
212
|
+
transformations: [
|
|
213
|
+
{
|
|
214
|
+
timestamp: new Date().toISOString(),
|
|
215
|
+
type: 'assessment_creation',
|
|
216
|
+
description: `Deployment assessment created for ${environment}`,
|
|
217
|
+
agent: 'deployment-readiness-tool',
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
validation: {
|
|
222
|
+
isVerified: readinessData.isDeploymentReady,
|
|
223
|
+
verificationMethod: 'comprehensive-deployment-audit',
|
|
224
|
+
verificationTimestamp: new Date().toISOString(),
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
this.logger.info(`Deployment assessment stored for ${environment}`, 'DeploymentMemoryManager', {
|
|
228
|
+
environment,
|
|
229
|
+
entityId: entity.id,
|
|
230
|
+
readinessScore: readinessData.overallScore,
|
|
231
|
+
isReady: readinessData.isDeploymentReady,
|
|
232
|
+
blockingIssues: assessmentData.blockingIssues.length,
|
|
233
|
+
});
|
|
234
|
+
return entity.id;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
this.logger.error('Failed to store deployment assessment', 'DeploymentMemoryManager', error);
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Migrate existing deployment history to memory entities
|
|
243
|
+
*/
|
|
244
|
+
async migrateExistingHistory(historyPath) {
|
|
245
|
+
try {
|
|
246
|
+
if (!existsSync(historyPath)) {
|
|
247
|
+
this.logger.info('No existing deployment history found to migrate', 'DeploymentMemoryManager');
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const historyData = JSON.parse(readFileSync(historyPath, 'utf8'));
|
|
251
|
+
const deployments = historyData.deployments || [];
|
|
252
|
+
let migratedCount = 0;
|
|
253
|
+
for (const deployment of deployments) {
|
|
254
|
+
try {
|
|
255
|
+
await this.migrateDeploymentRecord(deployment);
|
|
256
|
+
migratedCount++;
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
this.logger.error(`Failed to migrate deployment ${deployment.deploymentId}`, 'DeploymentMemoryManager', error);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
this.logger.info(`Migration completed: ${migratedCount}/${deployments.length} deployments migrated`, 'DeploymentMemoryManager');
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
this.logger.error('Failed to migrate deployment history', 'DeploymentMemoryManager', error);
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Analyze deployment patterns across memory entities
|
|
271
|
+
*/
|
|
272
|
+
async analyzeDeploymentPatterns(environment) {
|
|
273
|
+
try {
|
|
274
|
+
const query = {
|
|
275
|
+
entityTypes: ['deployment_assessment'],
|
|
276
|
+
limit: 100,
|
|
277
|
+
sortBy: 'lastModified',
|
|
278
|
+
};
|
|
279
|
+
if (environment) {
|
|
280
|
+
query.tags = [environment.toLowerCase()];
|
|
281
|
+
}
|
|
282
|
+
const assessments = await this.memoryManager.queryEntities(query);
|
|
283
|
+
const patterns = this.detectDeploymentPatterns(assessments.entities);
|
|
284
|
+
const trends = this.calculateDeploymentTrends(assessments.entities);
|
|
285
|
+
const recommendations = this.generatePatternRecommendations(patterns, trends);
|
|
286
|
+
const riskFactors = this.identifyRiskFactors(assessments.entities);
|
|
287
|
+
return {
|
|
288
|
+
patterns,
|
|
289
|
+
trends,
|
|
290
|
+
recommendations,
|
|
291
|
+
riskFactors,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
this.logger.error('Failed to analyze deployment patterns', 'DeploymentMemoryManager', error);
|
|
296
|
+
throw error;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Compare current assessment with historical patterns
|
|
301
|
+
*/
|
|
302
|
+
async compareWithHistory(currentAssessment, environment) {
|
|
303
|
+
try {
|
|
304
|
+
const recentAssessments = await this.memoryManager.queryEntities({
|
|
305
|
+
entityTypes: ['deployment_assessment'],
|
|
306
|
+
tags: [environment.toLowerCase()],
|
|
307
|
+
limit: 10,
|
|
308
|
+
sortBy: 'lastModified',
|
|
309
|
+
});
|
|
310
|
+
if (recentAssessments.entities.length === 0) {
|
|
311
|
+
return {
|
|
312
|
+
isImprovement: true,
|
|
313
|
+
comparison: { type: 'first_assessment' },
|
|
314
|
+
insights: ['This is the first deployment assessment for this environment'],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
const lastAssessment = recentAssessments.entities[0];
|
|
318
|
+
const comparison = this.compareAssessments(currentAssessment, lastAssessment.assessmentData);
|
|
319
|
+
return {
|
|
320
|
+
isImprovement: comparison.scoreImprovement > 0,
|
|
321
|
+
comparison,
|
|
322
|
+
insights: this.generateComparisonInsights(comparison),
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
catch (error) {
|
|
326
|
+
this.logger.error('Failed to compare with history', 'DeploymentMemoryManager', error);
|
|
327
|
+
return {
|
|
328
|
+
isImprovement: false,
|
|
329
|
+
comparison: { type: 'comparison_failed' },
|
|
330
|
+
insights: ['Unable to compare with historical data'],
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
// Private helper methods
|
|
335
|
+
async migrateDeploymentRecord(deployment) {
|
|
336
|
+
const assessmentData = {
|
|
337
|
+
environment: deployment.environment,
|
|
338
|
+
readinessScore: deployment.status === 'success' ? 1.0 : 0.0, // Use 0-1 range
|
|
339
|
+
validationResults: {
|
|
340
|
+
testResults: deployment.testResults
|
|
341
|
+
? {
|
|
342
|
+
passed: deployment.testResults.testSuitesExecuted.reduce((sum, suite) => sum + suite.passedTests, 0),
|
|
343
|
+
failed: deployment.testResults.failureCount,
|
|
344
|
+
coverage: deployment.testResults.coveragePercentage / 100,
|
|
345
|
+
criticalFailures: deployment.testResults.criticalTestFailures.map(f => f.testName),
|
|
346
|
+
}
|
|
347
|
+
: {
|
|
348
|
+
passed: 0,
|
|
349
|
+
failed: 0,
|
|
350
|
+
coverage: 0,
|
|
351
|
+
criticalFailures: [],
|
|
352
|
+
},
|
|
353
|
+
securityValidation: {
|
|
354
|
+
vulnerabilities: 0,
|
|
355
|
+
securityScore: 0.8,
|
|
356
|
+
criticalIssues: [],
|
|
357
|
+
},
|
|
358
|
+
performanceValidation: {
|
|
359
|
+
performanceScore: deployment.status === 'success' ? 0.8 : 0.2,
|
|
360
|
+
bottlenecks: [],
|
|
361
|
+
resourceUtilization: {},
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
blockingIssues: deployment.failureReason
|
|
365
|
+
? [
|
|
366
|
+
{
|
|
367
|
+
issue: `Historical Deployment Failure: ${deployment.failureReason}`,
|
|
368
|
+
severity: 'high',
|
|
369
|
+
category: 'configuration',
|
|
370
|
+
resolution: 'Review and address historical failure causes',
|
|
371
|
+
},
|
|
372
|
+
]
|
|
373
|
+
: [],
|
|
374
|
+
deploymentStrategy: {
|
|
375
|
+
type: 'rolling',
|
|
376
|
+
rollbackPlan: 'Standard rollback procedure',
|
|
377
|
+
monitoringPlan: 'Basic monitoring',
|
|
378
|
+
estimatedDowntime: deployment.rollbackRequired ? 'Variable' : '0 minutes',
|
|
379
|
+
},
|
|
380
|
+
complianceChecks: {
|
|
381
|
+
adrCompliance: 1.0,
|
|
382
|
+
regulatoryCompliance: [],
|
|
383
|
+
auditTrail: [
|
|
384
|
+
`Migrated deployment record from ${deployment.timestamp}`,
|
|
385
|
+
`Original status: ${deployment.status}`,
|
|
386
|
+
`Rollback required: ${deployment.rollbackRequired}`,
|
|
387
|
+
],
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
await this.memoryManager.upsertEntity({
|
|
391
|
+
type: 'deployment_assessment',
|
|
392
|
+
title: `Historical Deployment: ${deployment.environment} - ${deployment.status.toUpperCase()} - ${deployment.timestamp.split('T')[0]}`,
|
|
393
|
+
description: `Migrated deployment record for ${deployment.environment} (ID: ${deployment.deploymentId})`,
|
|
394
|
+
tags: [
|
|
395
|
+
'deployment',
|
|
396
|
+
deployment.environment.toLowerCase(),
|
|
397
|
+
'migrated-record',
|
|
398
|
+
deployment.status,
|
|
399
|
+
...(deployment.rollbackRequired ? ['rollback-required'] : []),
|
|
400
|
+
],
|
|
401
|
+
assessmentData,
|
|
402
|
+
relationships: [],
|
|
403
|
+
context: {
|
|
404
|
+
projectPhase: 'deployment-execution',
|
|
405
|
+
technicalStack: [],
|
|
406
|
+
environmentalFactors: [deployment.environment],
|
|
407
|
+
stakeholders: ['deployment-team'],
|
|
408
|
+
},
|
|
409
|
+
accessPattern: {
|
|
410
|
+
lastAccessed: new Date().toISOString(),
|
|
411
|
+
accessCount: 1,
|
|
412
|
+
accessContext: ['migration'],
|
|
413
|
+
},
|
|
414
|
+
evolution: {
|
|
415
|
+
origin: 'imported',
|
|
416
|
+
transformations: [
|
|
417
|
+
{
|
|
418
|
+
timestamp: new Date().toISOString(),
|
|
419
|
+
type: 'migration',
|
|
420
|
+
description: `Migrated from deployment-history.json (original: ${deployment.timestamp})`,
|
|
421
|
+
agent: 'deployment-readiness-tool',
|
|
422
|
+
},
|
|
423
|
+
],
|
|
424
|
+
},
|
|
425
|
+
validation: {
|
|
426
|
+
isVerified: true,
|
|
427
|
+
verificationMethod: 'historical-migration',
|
|
428
|
+
verificationTimestamp: new Date().toISOString(),
|
|
429
|
+
},
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
extractTechnicalStack(_validationResults) {
|
|
433
|
+
// Extract technical stack from validation results
|
|
434
|
+
// This is a simplified implementation
|
|
435
|
+
return [];
|
|
436
|
+
}
|
|
437
|
+
detectDeploymentPatterns(assessments) {
|
|
438
|
+
// Analyze deployment patterns across assessments
|
|
439
|
+
const patterns = [];
|
|
440
|
+
// Pattern: Time-based failures
|
|
441
|
+
const timePatterns = this.analyzeTimePatterns(assessments);
|
|
442
|
+
if (timePatterns.length > 0) {
|
|
443
|
+
patterns.push({ type: 'time_based', patterns: timePatterns });
|
|
444
|
+
}
|
|
445
|
+
// Pattern: Environment-specific issues
|
|
446
|
+
const envPatterns = this.analyzeEnvironmentPatterns(assessments);
|
|
447
|
+
if (envPatterns.length > 0) {
|
|
448
|
+
patterns.push({ type: 'environment_specific', patterns: envPatterns });
|
|
449
|
+
}
|
|
450
|
+
return patterns;
|
|
451
|
+
}
|
|
452
|
+
calculateDeploymentTrends(assessments) {
|
|
453
|
+
if (assessments.length < 3)
|
|
454
|
+
return [];
|
|
455
|
+
const trends = [];
|
|
456
|
+
const scores = assessments.map((a) => a.assessmentData.readinessScore);
|
|
457
|
+
// Calculate score trend
|
|
458
|
+
const scoreTrend = this.calculateTrend(scores);
|
|
459
|
+
trends.push({
|
|
460
|
+
metric: 'readiness_score',
|
|
461
|
+
trend: scoreTrend > 0 ? 'improving' : scoreTrend < 0 ? 'declining' : 'stable',
|
|
462
|
+
change: scoreTrend,
|
|
463
|
+
});
|
|
464
|
+
return trends;
|
|
465
|
+
}
|
|
466
|
+
generatePatternRecommendations(patterns, trends) {
|
|
467
|
+
const recommendations = [];
|
|
468
|
+
// Generate recommendations based on patterns
|
|
469
|
+
patterns.forEach(pattern => {
|
|
470
|
+
if (pattern.type === 'time_based') {
|
|
471
|
+
recommendations.push('Consider scheduling deployments during low-risk time windows');
|
|
472
|
+
}
|
|
473
|
+
if (pattern.type === 'environment_specific') {
|
|
474
|
+
recommendations.push('Address environment-specific configuration issues');
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
// Generate recommendations based on trends
|
|
478
|
+
trends.forEach(trend => {
|
|
479
|
+
if (trend.metric === 'readiness_score' && trend.trend === 'declining') {
|
|
480
|
+
recommendations.push('Investigate causes of declining deployment readiness scores');
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
return recommendations;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Map deployment blocker category to schema-compliant category
|
|
487
|
+
*/
|
|
488
|
+
mapBlockerCategory(category) {
|
|
489
|
+
switch (category) {
|
|
490
|
+
case 'test_failure':
|
|
491
|
+
return 'test';
|
|
492
|
+
case 'adr_compliance':
|
|
493
|
+
case 'environment':
|
|
494
|
+
case 'deployment_history':
|
|
495
|
+
return 'configuration';
|
|
496
|
+
case 'code_quality':
|
|
497
|
+
return 'performance';
|
|
498
|
+
default:
|
|
499
|
+
return 'configuration';
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
identifyRiskFactors(assessments) {
|
|
503
|
+
const riskFactors = [];
|
|
504
|
+
// Analyze recent failures
|
|
505
|
+
const recentFailures = assessments
|
|
506
|
+
.filter((a) => !a.assessmentData.deploymentReady)
|
|
507
|
+
.slice(0, 5);
|
|
508
|
+
if (recentFailures.length >= 3) {
|
|
509
|
+
riskFactors.push({
|
|
510
|
+
factor: 'frequent_failures',
|
|
511
|
+
description: `${recentFailures.length} deployment blocks in recent assessments`,
|
|
512
|
+
severity: 'high',
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
return riskFactors;
|
|
516
|
+
}
|
|
517
|
+
compareAssessments(current, historical) {
|
|
518
|
+
return {
|
|
519
|
+
scoreImprovement: current.overallScore - historical.readinessScore,
|
|
520
|
+
confidenceChange: current.confidence - historical.confidence,
|
|
521
|
+
blockingIssuesChange: current.criticalBlockers.length - historical.blockingIssues.length,
|
|
522
|
+
testImprovements: {
|
|
523
|
+
failureCountChange: current.testValidationResult.failureCount -
|
|
524
|
+
(historical.validationResults?.testValidation?.failureCount || 0),
|
|
525
|
+
coverageChange: current.testValidationResult.coveragePercentage -
|
|
526
|
+
(historical.validationResults?.testValidation?.coveragePercentage || 0),
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
generateComparisonInsights(comparison) {
|
|
531
|
+
const insights = [];
|
|
532
|
+
if (comparison.scoreImprovement > 0) {
|
|
533
|
+
insights.push(`Deployment readiness improved by ${comparison.scoreImprovement} points`);
|
|
534
|
+
}
|
|
535
|
+
else if (comparison.scoreImprovement < 0) {
|
|
536
|
+
insights.push(`Deployment readiness declined by ${Math.abs(comparison.scoreImprovement)} points`);
|
|
537
|
+
}
|
|
538
|
+
if (comparison.testImprovements.failureCountChange < 0) {
|
|
539
|
+
insights.push(`Test stability improved: ${Math.abs(comparison.testImprovements.failureCountChange)} fewer failures`);
|
|
540
|
+
}
|
|
541
|
+
if (comparison.testImprovements.coverageChange > 0) {
|
|
542
|
+
insights.push(`Test coverage increased by ${comparison.testImprovements.coverageChange}%`);
|
|
543
|
+
}
|
|
544
|
+
return insights;
|
|
545
|
+
}
|
|
546
|
+
analyzeTimePatterns(_assessments) {
|
|
547
|
+
// Simplified time pattern analysis
|
|
548
|
+
return [];
|
|
549
|
+
}
|
|
550
|
+
analyzeEnvironmentPatterns(_assessments) {
|
|
551
|
+
// Simplified environment pattern analysis
|
|
552
|
+
return [];
|
|
553
|
+
}
|
|
554
|
+
calculateTrend(values) {
|
|
555
|
+
if (values.length < 2)
|
|
556
|
+
return 0;
|
|
557
|
+
const recent = values.slice(0, Math.min(5, values.length));
|
|
558
|
+
const older = values.slice(Math.min(5, values.length));
|
|
559
|
+
const recentAvg = recent.reduce((a, b) => a + b, 0) / recent.length;
|
|
560
|
+
const olderAvg = older.length > 0 ? older.reduce((a, b) => a + b, 0) / older.length : recentAvg;
|
|
561
|
+
return recentAvg - olderAvg;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
64
564
|
/**
|
|
65
565
|
* Main deployment readiness function
|
|
66
566
|
*/
|
|
@@ -76,6 +576,16 @@ export async function deploymentReadiness(args) {
|
|
|
76
576
|
if (!existsSync(cacheDir)) {
|
|
77
577
|
mkdirSync(cacheDir, { recursive: true });
|
|
78
578
|
}
|
|
579
|
+
// Initialize memory manager if enabled
|
|
580
|
+
let memoryManager = null;
|
|
581
|
+
if (validatedArgs.enableMemoryIntegration) {
|
|
582
|
+
memoryManager = new DeploymentMemoryManager();
|
|
583
|
+
await memoryManager.initialize();
|
|
584
|
+
// Migrate existing history if requested
|
|
585
|
+
if (validatedArgs.migrateExistingHistory) {
|
|
586
|
+
await memoryManager.migrateExistingHistory(deploymentHistoryPath);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
79
589
|
let result;
|
|
80
590
|
switch (validatedArgs.operation) {
|
|
81
591
|
case 'test_validation':
|
|
@@ -99,10 +609,68 @@ export async function deploymentReadiness(args) {
|
|
|
99
609
|
writeFileSync(readinessCachePath, JSON.stringify({
|
|
100
610
|
timestamp: new Date().toISOString(),
|
|
101
611
|
operation: validatedArgs.operation,
|
|
102
|
-
result
|
|
612
|
+
result,
|
|
103
613
|
}, null, 2));
|
|
104
|
-
//
|
|
105
|
-
|
|
614
|
+
// Memory integration: store assessment and analyze patterns
|
|
615
|
+
let memoryIntegrationInfo = '';
|
|
616
|
+
if (memoryManager) {
|
|
617
|
+
try {
|
|
618
|
+
// Store deployment assessment
|
|
619
|
+
const assessmentId = await memoryManager.storeDeploymentAssessment(validatedArgs.targetEnvironment, result, { projectPath, operation: validatedArgs.operation }, projectPath);
|
|
620
|
+
// Compare with historical patterns
|
|
621
|
+
const historyComparison = await memoryManager.compareWithHistory(result, validatedArgs.targetEnvironment);
|
|
622
|
+
// Analyze deployment patterns
|
|
623
|
+
const patternAnalysis = await memoryManager.analyzeDeploymentPatterns(validatedArgs.targetEnvironment);
|
|
624
|
+
memoryIntegrationInfo = `
|
|
625
|
+
|
|
626
|
+
## ๐ง Memory Integration Analysis
|
|
627
|
+
|
|
628
|
+
- **Assessment Stored**: โ
Deployment assessment saved (ID: ${assessmentId.substring(0, 8)}...)
|
|
629
|
+
- **Environment**: ${validatedArgs.targetEnvironment}
|
|
630
|
+
- **Historical Comparison**: ${historyComparison.isImprovement ? '๐ Improvement detected' : '๐ Baseline established'}
|
|
631
|
+
|
|
632
|
+
${historyComparison.insights.length > 0
|
|
633
|
+
? `### Historical Insights
|
|
634
|
+
${historyComparison.insights.map(insight => `- ${insight}`).join('\n')}
|
|
635
|
+
`
|
|
636
|
+
: ''}
|
|
637
|
+
|
|
638
|
+
${patternAnalysis.trends.length > 0
|
|
639
|
+
? `### Deployment Trends
|
|
640
|
+
${patternAnalysis.trends.map(trend => `- **${trend.metric}**: ${trend.trend} (${trend.change > 0 ? '+' : ''}${trend.change})`).join('\n')}
|
|
641
|
+
`
|
|
642
|
+
: ''}
|
|
643
|
+
|
|
644
|
+
${patternAnalysis.recommendations.length > 0
|
|
645
|
+
? `### Pattern-Based Recommendations
|
|
646
|
+
${patternAnalysis.recommendations.map(rec => `- ${rec}`).join('\n')}
|
|
647
|
+
`
|
|
648
|
+
: ''}
|
|
649
|
+
|
|
650
|
+
${patternAnalysis.riskFactors.length > 0
|
|
651
|
+
? `### Risk Factors Identified
|
|
652
|
+
${patternAnalysis.riskFactors.map(risk => `- **${risk.factor}**: ${risk.description} (${risk.severity})`).join('\n')}
|
|
653
|
+
`
|
|
654
|
+
: ''}
|
|
655
|
+
`;
|
|
656
|
+
}
|
|
657
|
+
catch (memoryError) {
|
|
658
|
+
memoryIntegrationInfo = `
|
|
659
|
+
|
|
660
|
+
## ๐ง Memory Integration Status
|
|
661
|
+
|
|
662
|
+
- **Status**: โ ๏ธ Memory integration failed - assessment continued without persistence
|
|
663
|
+
- **Error**: ${memoryError instanceof Error ? memoryError.message : 'Unknown error'}
|
|
664
|
+
`;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
// Generate enhanced response with memory integration
|
|
668
|
+
const baseResponse = generateDeploymentReadinessResponse(result, validatedArgs);
|
|
669
|
+
// Add memory integration info if available
|
|
670
|
+
if (memoryIntegrationInfo && baseResponse.content?.[0]?.text) {
|
|
671
|
+
baseResponse.content[0].text += memoryIntegrationInfo;
|
|
672
|
+
}
|
|
673
|
+
return baseResponse;
|
|
106
674
|
}
|
|
107
675
|
catch (error) {
|
|
108
676
|
throw new McpAdrError('DEPLOYMENT_READINESS_ERROR', `Deployment readiness check failed: ${jsonSafeError(error)}`);
|
|
@@ -126,10 +694,10 @@ async function performTestValidation(args, projectPath) {
|
|
|
126
694
|
'Run npm test to see detailed failures',
|
|
127
695
|
'Fix failing tests one by one',
|
|
128
696
|
'Ensure all tests pass before deployment',
|
|
129
|
-
'Consider increasing test coverage'
|
|
697
|
+
'Consider increasing test coverage',
|
|
130
698
|
],
|
|
131
699
|
estimatedResolutionTime: `${Math.ceil(testResult.failureCount * 0.5)} hours`,
|
|
132
|
-
blocksDeployment: args.blockOnFailingTests
|
|
700
|
+
blocksDeployment: args.blockOnFailingTests,
|
|
133
701
|
});
|
|
134
702
|
}
|
|
135
703
|
// Check test coverage
|
|
@@ -143,10 +711,10 @@ async function performTestValidation(args, projectPath) {
|
|
|
143
711
|
resolutionSteps: [
|
|
144
712
|
'Add tests for uncovered code',
|
|
145
713
|
'Run npm run test:coverage to see detailed coverage',
|
|
146
|
-
'Focus on critical business logic first'
|
|
714
|
+
'Focus on critical business logic first',
|
|
147
715
|
],
|
|
148
716
|
estimatedResolutionTime: '2-4 hours',
|
|
149
|
-
blocksDeployment: args.strictMode
|
|
717
|
+
blocksDeployment: args.strictMode,
|
|
150
718
|
});
|
|
151
719
|
}
|
|
152
720
|
// Basic result structure
|
|
@@ -154,10 +722,34 @@ async function performTestValidation(args, projectPath) {
|
|
|
154
722
|
isDeploymentReady: testBlockers.length === 0,
|
|
155
723
|
overallScore: calculateTestScore(testResult, args),
|
|
156
724
|
confidence: 85,
|
|
157
|
-
codeQualityAnalysis: {
|
|
725
|
+
codeQualityAnalysis: {
|
|
726
|
+
qualityScore: 75,
|
|
727
|
+
productionIndicators: 10,
|
|
728
|
+
mockIndicators: 2,
|
|
729
|
+
failingFiles: [],
|
|
730
|
+
recommendations: [],
|
|
731
|
+
},
|
|
158
732
|
testValidationResult: testResult,
|
|
159
|
-
deploymentHistoryAnalysis: {
|
|
160
|
-
|
|
733
|
+
deploymentHistoryAnalysis: {
|
|
734
|
+
recentDeployments: [],
|
|
735
|
+
successRate: 100,
|
|
736
|
+
rollbackRate: 0,
|
|
737
|
+
averageDeploymentTime: 0,
|
|
738
|
+
failurePatterns: [],
|
|
739
|
+
environmentStability: {
|
|
740
|
+
stabilityScore: 100,
|
|
741
|
+
riskLevel: 'low',
|
|
742
|
+
recommendation: 'Proceed with deployment',
|
|
743
|
+
},
|
|
744
|
+
recommendedAction: 'proceed',
|
|
745
|
+
},
|
|
746
|
+
adrComplianceResult: {
|
|
747
|
+
score: 100,
|
|
748
|
+
compliantAdrs: 0,
|
|
749
|
+
totalAdrs: 0,
|
|
750
|
+
missingImplementations: [],
|
|
751
|
+
recommendations: [],
|
|
752
|
+
},
|
|
161
753
|
criticalBlockers: testBlockers.filter(b => b.severity === 'critical'),
|
|
162
754
|
testFailureBlockers: testBlockers,
|
|
163
755
|
deploymentHistoryBlockers: [],
|
|
@@ -165,7 +757,7 @@ async function performTestValidation(args, projectPath) {
|
|
|
165
757
|
todoTasksCreated: [],
|
|
166
758
|
healthScoreUpdate: {},
|
|
167
759
|
gitPushStatus: testBlockers.length === 0 ? 'allowed' : 'blocked',
|
|
168
|
-
overrideStatus: {}
|
|
760
|
+
overrideStatus: {},
|
|
169
761
|
};
|
|
170
762
|
}
|
|
171
763
|
/**
|
|
@@ -183,7 +775,7 @@ async function executeTestSuite(projectPath, _requiredSuites) {
|
|
|
183
775
|
testOutput = execSync(command, {
|
|
184
776
|
cwd: projectPath,
|
|
185
777
|
encoding: 'utf8',
|
|
186
|
-
timeout: 300000 // 5 minute timeout
|
|
778
|
+
timeout: 300000, // 5 minute timeout
|
|
187
779
|
});
|
|
188
780
|
break;
|
|
189
781
|
}
|
|
@@ -206,7 +798,7 @@ async function executeTestSuite(projectPath, _requiredSuites) {
|
|
|
206
798
|
// Parse test results (simplified for now)
|
|
207
799
|
const testSuites = parseTestOutput(testOutput);
|
|
208
800
|
const totalFailures = testSuites.reduce((sum, suite) => sum + suite.failedTests, 0);
|
|
209
|
-
const overallStatus = exitCode === 0 ? 'passed' :
|
|
801
|
+
const overallStatus = exitCode === 0 ? 'passed' : totalFailures > 0 ? 'failed' : 'partial';
|
|
210
802
|
// Check coverage (simplified)
|
|
211
803
|
const coverage = await checkTestCoverage(projectPath);
|
|
212
804
|
return {
|
|
@@ -217,7 +809,7 @@ async function executeTestSuite(projectPath, _requiredSuites) {
|
|
|
217
809
|
requiredSuitesMissing: [],
|
|
218
810
|
criticalTestFailures: testSuites.flatMap(suite => suite.failureDetails.filter(f => f.severity === 'critical')),
|
|
219
811
|
testExecutionTime: executionTime,
|
|
220
|
-
lastTestRun: new Date().toISOString()
|
|
812
|
+
lastTestRun: new Date().toISOString(),
|
|
221
813
|
};
|
|
222
814
|
}
|
|
223
815
|
/**
|
|
@@ -241,7 +833,7 @@ function parseTestOutput(output) {
|
|
|
241
833
|
failedTests: 0,
|
|
242
834
|
coverage: 0,
|
|
243
835
|
executionTime: 0,
|
|
244
|
-
failureDetails: []
|
|
836
|
+
failureDetails: [],
|
|
245
837
|
};
|
|
246
838
|
}
|
|
247
839
|
// Count tests
|
|
@@ -258,7 +850,7 @@ function parseTestOutput(output) {
|
|
|
258
850
|
errorMessage: line,
|
|
259
851
|
severity: 'medium',
|
|
260
852
|
blocksDeployment: true,
|
|
261
|
-
relatedFiles: []
|
|
853
|
+
relatedFiles: [],
|
|
262
854
|
});
|
|
263
855
|
}
|
|
264
856
|
}
|
|
@@ -266,15 +858,19 @@ function parseTestOutput(output) {
|
|
|
266
858
|
if (currentSuite.suiteName) {
|
|
267
859
|
suites.push(currentSuite);
|
|
268
860
|
}
|
|
269
|
-
return suites.length > 0
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
861
|
+
return suites.length > 0
|
|
862
|
+
? suites
|
|
863
|
+
: [
|
|
864
|
+
{
|
|
865
|
+
suiteName: 'default',
|
|
866
|
+
status: output.includes('failing') ? 'failed' : 'passed',
|
|
867
|
+
passedTests: 0,
|
|
868
|
+
failedTests: output.includes('failing') ? 1 : 0,
|
|
869
|
+
coverage: 0,
|
|
870
|
+
executionTime: 0,
|
|
871
|
+
failureDetails: [],
|
|
872
|
+
},
|
|
873
|
+
];
|
|
278
874
|
}
|
|
279
875
|
/**
|
|
280
876
|
* Check test coverage
|
|
@@ -285,7 +881,7 @@ async function checkTestCoverage(projectPath) {
|
|
|
285
881
|
const coverageFiles = [
|
|
286
882
|
'coverage/lcov-report/index.html',
|
|
287
883
|
'coverage/coverage-summary.json',
|
|
288
|
-
'coverage/coverage-final.json'
|
|
884
|
+
'coverage/coverage-final.json',
|
|
289
885
|
];
|
|
290
886
|
for (const file of coverageFiles) {
|
|
291
887
|
const filePath = join(projectPath, file);
|
|
@@ -323,10 +919,10 @@ async function performDeploymentHistoryAnalysis(args, historyPath) {
|
|
|
323
919
|
'Review recent deployment failures',
|
|
324
920
|
'Fix underlying infrastructure issues',
|
|
325
921
|
'Improve deployment process reliability',
|
|
326
|
-
'Add more comprehensive pre-deployment checks'
|
|
922
|
+
'Add more comprehensive pre-deployment checks',
|
|
327
923
|
],
|
|
328
924
|
estimatedResolutionTime: '1-2 days',
|
|
329
|
-
blocksDeployment: args.blockOnRecentFailures
|
|
925
|
+
blocksDeployment: args.blockOnRecentFailures,
|
|
330
926
|
});
|
|
331
927
|
}
|
|
332
928
|
// Check rollback rate
|
|
@@ -341,20 +937,41 @@ async function performDeploymentHistoryAnalysis(args, historyPath) {
|
|
|
341
937
|
'Improve testing before deployment',
|
|
342
938
|
'Add more validation steps',
|
|
343
939
|
'Review rollback causes',
|
|
344
|
-
'Strengthen deployment pipeline'
|
|
940
|
+
'Strengthen deployment pipeline',
|
|
345
941
|
],
|
|
346
942
|
estimatedResolutionTime: '4-8 hours',
|
|
347
|
-
blocksDeployment: args.strictMode
|
|
943
|
+
blocksDeployment: args.strictMode,
|
|
348
944
|
});
|
|
349
945
|
}
|
|
350
946
|
return {
|
|
351
947
|
isDeploymentReady: historyBlockers.length === 0,
|
|
352
948
|
overallScore: Math.min(analysis.successRate, 100 - analysis.rollbackRate),
|
|
353
949
|
confidence: 80,
|
|
354
|
-
codeQualityAnalysis: {
|
|
355
|
-
|
|
950
|
+
codeQualityAnalysis: {
|
|
951
|
+
qualityScore: 75,
|
|
952
|
+
productionIndicators: 10,
|
|
953
|
+
mockIndicators: 2,
|
|
954
|
+
failingFiles: [],
|
|
955
|
+
recommendations: [],
|
|
956
|
+
},
|
|
957
|
+
testValidationResult: {
|
|
958
|
+
testSuitesExecuted: [],
|
|
959
|
+
overallTestStatus: 'not_run',
|
|
960
|
+
failureCount: 0,
|
|
961
|
+
coveragePercentage: 0,
|
|
962
|
+
requiredSuitesMissing: [],
|
|
963
|
+
criticalTestFailures: [],
|
|
964
|
+
testExecutionTime: 0,
|
|
965
|
+
lastTestRun: '',
|
|
966
|
+
},
|
|
356
967
|
deploymentHistoryAnalysis: analysis,
|
|
357
|
-
adrComplianceResult: {
|
|
968
|
+
adrComplianceResult: {
|
|
969
|
+
score: 100,
|
|
970
|
+
compliantAdrs: 0,
|
|
971
|
+
totalAdrs: 0,
|
|
972
|
+
missingImplementations: [],
|
|
973
|
+
recommendations: [],
|
|
974
|
+
},
|
|
358
975
|
criticalBlockers: historyBlockers.filter(b => b.severity === 'critical'),
|
|
359
976
|
testFailureBlockers: [],
|
|
360
977
|
deploymentHistoryBlockers: historyBlockers,
|
|
@@ -362,7 +979,7 @@ async function performDeploymentHistoryAnalysis(args, historyPath) {
|
|
|
362
979
|
todoTasksCreated: [],
|
|
363
980
|
healthScoreUpdate: {},
|
|
364
981
|
gitPushStatus: historyBlockers.length === 0 ? 'allowed' : 'blocked',
|
|
365
|
-
overrideStatus: {}
|
|
982
|
+
overrideStatus: {},
|
|
366
983
|
};
|
|
367
984
|
}
|
|
368
985
|
/**
|
|
@@ -399,7 +1016,7 @@ function analyzeDeploymentHistory(history, environment) {
|
|
|
399
1016
|
averageDeploymentTime: calculateAverageDeploymentTime(recentDeployments),
|
|
400
1017
|
failurePatterns,
|
|
401
1018
|
environmentStability: assessEnvironmentStability(successRate, rollbackRate),
|
|
402
|
-
recommendedAction: recommendAction(successRate, rollbackRate, failurePatterns.length)
|
|
1019
|
+
recommendedAction: recommendAction(successRate, rollbackRate, failurePatterns.length),
|
|
403
1020
|
};
|
|
404
1021
|
}
|
|
405
1022
|
/**
|
|
@@ -422,7 +1039,7 @@ function analyzeFailurePatterns(failedDeployments) {
|
|
|
422
1039
|
environments: [deployment.environment],
|
|
423
1040
|
lastOccurrence: deployment.timestamp,
|
|
424
1041
|
resolution: suggestResolution(category),
|
|
425
|
-
preventable: isPreventable(category)
|
|
1042
|
+
preventable: isPreventable(category),
|
|
426
1043
|
});
|
|
427
1044
|
}
|
|
428
1045
|
}
|
|
@@ -439,7 +1056,7 @@ async function performFullAudit(args, projectPath, historyPath) {
|
|
|
439
1056
|
const allBlockers = [
|
|
440
1057
|
...testResult.criticalBlockers,
|
|
441
1058
|
...testResult.testFailureBlockers,
|
|
442
|
-
...historyResult.deploymentHistoryBlockers
|
|
1059
|
+
...historyResult.deploymentHistoryBlockers,
|
|
443
1060
|
];
|
|
444
1061
|
const overallScore = (testResult.overallScore + historyResult.overallScore) / 2;
|
|
445
1062
|
const isReady = allBlockers.length === 0;
|
|
@@ -458,7 +1075,7 @@ async function performFullAudit(args, projectPath, historyPath) {
|
|
|
458
1075
|
todoTasksCreated: [],
|
|
459
1076
|
healthScoreUpdate: {},
|
|
460
1077
|
gitPushStatus: isReady ? 'allowed' : 'blocked',
|
|
461
|
-
overrideStatus: {}
|
|
1078
|
+
overrideStatus: {},
|
|
462
1079
|
};
|
|
463
1080
|
}
|
|
464
1081
|
/**
|
|
@@ -473,7 +1090,7 @@ async function performEmergencyOverride(args, projectPath) {
|
|
|
473
1090
|
timestamp: new Date().toISOString(),
|
|
474
1091
|
justification: args.businessJustification || 'No justification provided',
|
|
475
1092
|
environment: args.targetEnvironment,
|
|
476
|
-
overriddenBy: process.env['USER'] || 'unknown'
|
|
1093
|
+
overriddenBy: process.env['USER'] || 'unknown',
|
|
477
1094
|
};
|
|
478
1095
|
const overridePath = join(projectPath, '.mcp-adr-cache', 'emergency-overrides.json');
|
|
479
1096
|
const overrides = existsSync(overridePath) ? JSON.parse(readFileSync(overridePath, 'utf8')) : [];
|
|
@@ -483,10 +1100,43 @@ async function performEmergencyOverride(args, projectPath) {
|
|
|
483
1100
|
isDeploymentReady: true,
|
|
484
1101
|
overallScore: 100,
|
|
485
1102
|
confidence: 50, // Lower confidence for overrides
|
|
486
|
-
codeQualityAnalysis: {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
1103
|
+
codeQualityAnalysis: {
|
|
1104
|
+
qualityScore: 100,
|
|
1105
|
+
productionIndicators: 0,
|
|
1106
|
+
mockIndicators: 0,
|
|
1107
|
+
failingFiles: [],
|
|
1108
|
+
recommendations: ['Emergency override active - review post-deployment'],
|
|
1109
|
+
},
|
|
1110
|
+
testValidationResult: {
|
|
1111
|
+
testSuitesExecuted: [],
|
|
1112
|
+
overallTestStatus: 'not_run',
|
|
1113
|
+
failureCount: 0,
|
|
1114
|
+
coveragePercentage: 0,
|
|
1115
|
+
requiredSuitesMissing: [],
|
|
1116
|
+
criticalTestFailures: [],
|
|
1117
|
+
testExecutionTime: 0,
|
|
1118
|
+
lastTestRun: '',
|
|
1119
|
+
},
|
|
1120
|
+
deploymentHistoryAnalysis: {
|
|
1121
|
+
recentDeployments: [],
|
|
1122
|
+
successRate: 100,
|
|
1123
|
+
rollbackRate: 0,
|
|
1124
|
+
averageDeploymentTime: 0,
|
|
1125
|
+
failurePatterns: [],
|
|
1126
|
+
environmentStability: {
|
|
1127
|
+
stabilityScore: 50,
|
|
1128
|
+
riskLevel: 'medium',
|
|
1129
|
+
recommendation: 'Monitor closely post-deployment',
|
|
1130
|
+
},
|
|
1131
|
+
recommendedAction: 'proceed',
|
|
1132
|
+
},
|
|
1133
|
+
adrComplianceResult: {
|
|
1134
|
+
score: 100,
|
|
1135
|
+
compliantAdrs: 0,
|
|
1136
|
+
totalAdrs: 0,
|
|
1137
|
+
missingImplementations: [],
|
|
1138
|
+
recommendations: [],
|
|
1139
|
+
},
|
|
490
1140
|
criticalBlockers: [],
|
|
491
1141
|
testFailureBlockers: [],
|
|
492
1142
|
deploymentHistoryBlockers: [],
|
|
@@ -494,14 +1144,14 @@ async function performEmergencyOverride(args, projectPath) {
|
|
|
494
1144
|
todoTasksCreated: [],
|
|
495
1145
|
healthScoreUpdate: {},
|
|
496
1146
|
gitPushStatus: 'allowed',
|
|
497
|
-
overrideStatus: overrideRecord
|
|
1147
|
+
overrideStatus: overrideRecord,
|
|
498
1148
|
};
|
|
499
1149
|
}
|
|
500
1150
|
/**
|
|
501
1151
|
* Helper functions
|
|
502
1152
|
*/
|
|
503
1153
|
function calculateTestScore(testResult, _args) {
|
|
504
|
-
const failureScore = Math.max(0, 100 -
|
|
1154
|
+
const failureScore = Math.max(0, 100 - testResult.failureCount * 20);
|
|
505
1155
|
const coverageScore = testResult.coveragePercentage;
|
|
506
1156
|
return Math.min(failureScore, coverageScore);
|
|
507
1157
|
}
|
|
@@ -525,7 +1175,7 @@ function assessEnvironmentStability(successRate, rollbackRate) {
|
|
|
525
1175
|
return {
|
|
526
1176
|
stabilityScore,
|
|
527
1177
|
riskLevel,
|
|
528
|
-
recommendation: riskLevel === 'low' ? 'Proceed with deployment' : 'Investigate before deployment'
|
|
1178
|
+
recommendation: riskLevel === 'low' ? 'Proceed with deployment' : 'Investigate before deployment',
|
|
529
1179
|
};
|
|
530
1180
|
}
|
|
531
1181
|
function recommendAction(successRate, rollbackRate, failurePatternCount) {
|
|
@@ -544,7 +1194,7 @@ function categorizeFailure(failureReason) {
|
|
|
544
1194
|
{ regex: /dependency.*error/i, category: 'Dependency Issues' },
|
|
545
1195
|
{ regex: /timeout/i, category: 'Timeout Issues' },
|
|
546
1196
|
{ regex: /permission.*denied/i, category: 'Permission Issues' },
|
|
547
|
-
{ regex: /out.*of.*memory/i, category: 'Resource Issues' }
|
|
1197
|
+
{ regex: /out.*of.*memory/i, category: 'Resource Issues' },
|
|
548
1198
|
];
|
|
549
1199
|
for (const pattern of patterns) {
|
|
550
1200
|
if (pattern.regex.test(failureReason)) {
|
|
@@ -562,7 +1212,7 @@ function suggestResolution(category) {
|
|
|
562
1212
|
'Dependency Issues': 'Update and verify package dependencies',
|
|
563
1213
|
'Timeout Issues': 'Optimize performance and increase timeout values',
|
|
564
1214
|
'Permission Issues': 'Check file and directory permissions',
|
|
565
|
-
'Resource Issues': 'Increase available memory and resources'
|
|
1215
|
+
'Resource Issues': 'Increase available memory and resources',
|
|
566
1216
|
};
|
|
567
1217
|
return resolutions[category] || 'Investigate failure details and resolve underlying issue';
|
|
568
1218
|
}
|
|
@@ -571,7 +1221,7 @@ function isPreventable(category) {
|
|
|
571
1221
|
'Test Failures',
|
|
572
1222
|
'Environment Configuration',
|
|
573
1223
|
'Build Failures',
|
|
574
|
-
'Dependency Issues'
|
|
1224
|
+
'Dependency Issues',
|
|
575
1225
|
];
|
|
576
1226
|
return preventableCategories.includes(category);
|
|
577
1227
|
}
|
|
@@ -588,7 +1238,8 @@ function generateDeploymentReadinessResponse(result, args) {
|
|
|
588
1238
|
}
|
|
589
1239
|
function generateSuccessResponse(result, args) {
|
|
590
1240
|
return validateMcpResponse({
|
|
591
|
-
content: [
|
|
1241
|
+
content: [
|
|
1242
|
+
{
|
|
592
1243
|
type: 'text',
|
|
593
1244
|
text: `โ
**DEPLOYMENT READY - All Gates Passed**
|
|
594
1245
|
|
|
@@ -612,18 +1263,22 @@ function generateSuccessResponse(result, args) {
|
|
|
612
1263
|
## ๐ Deployment Approved
|
|
613
1264
|
${args.triggerSmartGitPush ? 'Triggering smart git push...' : 'Ready to proceed with deployment'}
|
|
614
1265
|
|
|
615
|
-
${result.warnings.length > 0
|
|
1266
|
+
${result.warnings.length > 0
|
|
1267
|
+
? `
|
|
616
1268
|
## โ ๏ธ Warnings
|
|
617
1269
|
${result.warnings.map(w => `- ${w}`).join('\n')}
|
|
618
|
-
`
|
|
1270
|
+
`
|
|
1271
|
+
: ''}
|
|
619
1272
|
|
|
620
|
-
**โ
DEPLOYMENT CAN PROCEED SAFELY
|
|
621
|
-
}
|
|
1273
|
+
**โ
DEPLOYMENT CAN PROCEED SAFELY**`,
|
|
1274
|
+
},
|
|
1275
|
+
],
|
|
622
1276
|
});
|
|
623
1277
|
}
|
|
624
1278
|
function generateBlockedResponse(result, args) {
|
|
625
1279
|
return validateMcpResponse({
|
|
626
|
-
content: [
|
|
1280
|
+
content: [
|
|
1281
|
+
{
|
|
627
1282
|
type: 'text',
|
|
628
1283
|
text: `๐จ **DEPLOYMENT BLOCKED - Critical Issues Found**
|
|
629
1284
|
|
|
@@ -634,30 +1289,36 @@ function generateBlockedResponse(result, args) {
|
|
|
634
1289
|
- **Target Environment**: ${args.targetEnvironment}
|
|
635
1290
|
|
|
636
1291
|
## ๐งช Test Validation Issues
|
|
637
|
-
${result.testFailureBlockers.length > 0
|
|
1292
|
+
${result.testFailureBlockers.length > 0
|
|
1293
|
+
? `
|
|
638
1294
|
**Test Failures**: ${result.testValidationResult.failureCount} failures detected
|
|
639
1295
|
**Coverage**: ${result.testValidationResult.coveragePercentage}% (Required: ${args.requireTestCoverage}%)
|
|
640
1296
|
|
|
641
1297
|
### Critical Test Failures:
|
|
642
1298
|
${result.testValidationResult.criticalTestFailures.map(f => `- โ ${f.testSuite}: ${f.testName}`).join('\n')}
|
|
643
|
-
`
|
|
1299
|
+
`
|
|
1300
|
+
: 'โ
Tests passing'}
|
|
644
1301
|
|
|
645
1302
|
## ๐ Deployment History Issues
|
|
646
|
-
${result.deploymentHistoryBlockers.length > 0
|
|
1303
|
+
${result.deploymentHistoryBlockers.length > 0
|
|
1304
|
+
? `
|
|
647
1305
|
**Success Rate**: ${result.deploymentHistoryAnalysis.successRate}% (Required: ${args.deploymentSuccessThreshold}%)
|
|
648
1306
|
**Rollback Rate**: ${result.deploymentHistoryAnalysis.rollbackRate}% (Threshold: ${args.rollbackFrequencyThreshold}%)
|
|
649
1307
|
|
|
650
1308
|
### Recent Failure Patterns:
|
|
651
1309
|
${result.deploymentHistoryAnalysis.failurePatterns.map(p => `- **${p.pattern}**: ${p.frequency} occurrences`).join('\n')}
|
|
652
|
-
`
|
|
1310
|
+
`
|
|
1311
|
+
: 'โ
Deployment history stable'}
|
|
653
1312
|
|
|
654
1313
|
## ๐จ Critical Blockers (Must Fix Before Deployment)
|
|
655
|
-
${result.criticalBlockers
|
|
1314
|
+
${result.criticalBlockers
|
|
1315
|
+
.map(blocker => `
|
|
656
1316
|
### ${blocker.category.toUpperCase()}: ${blocker.title}
|
|
657
1317
|
- **Impact**: ${blocker.impact}
|
|
658
1318
|
- **Resolution**: ${blocker.resolutionSteps.join(' โ ')}
|
|
659
1319
|
- **Estimated Time**: ${blocker.estimatedResolutionTime}
|
|
660
|
-
`)
|
|
1320
|
+
`)
|
|
1321
|
+
.join('\n')}
|
|
661
1322
|
|
|
662
1323
|
## ๐ ๏ธ Immediate Actions Required
|
|
663
1324
|
|
|
@@ -689,8 +1350,9 @@ For critical fixes only:
|
|
|
689
1350
|
deployment_readiness --operation emergency_override --business-justification "Your justification"
|
|
690
1351
|
\`\`\`
|
|
691
1352
|
|
|
692
|
-
**โ DEPLOYMENT CANNOT PROCEED UNTIL ALL CRITICAL BLOCKERS ARE RESOLVED
|
|
693
|
-
}
|
|
1353
|
+
**โ DEPLOYMENT CANNOT PROCEED UNTIL ALL CRITICAL BLOCKERS ARE RESOLVED**`,
|
|
1354
|
+
},
|
|
1355
|
+
],
|
|
694
1356
|
});
|
|
695
1357
|
}
|
|
696
1358
|
//# sourceMappingURL=deployment-readiness-tool.js.map
|