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
|
@@ -23,24 +23,27 @@
|
|
|
23
23
|
import { McpAdrError } from '../types/index.js';
|
|
24
24
|
import { execSync } from 'child_process';
|
|
25
25
|
import { readFileSync, writeFileSync, existsSync, statSync, mkdirSync } from 'fs';
|
|
26
|
-
import { join, extname } from 'path';
|
|
26
|
+
import { join, extname, basename } from 'path';
|
|
27
|
+
import * as os from 'os';
|
|
27
28
|
import { jsonSafeFilePath, jsonSafeError, jsonSafeUserInput } from '../utils/json-safe.js';
|
|
28
29
|
import { validateMcpResponse } from '../utils/mcp-response-validator.js';
|
|
29
30
|
/**
|
|
30
31
|
* Main smart git push function - Security and Metrics Focused
|
|
31
32
|
*/
|
|
32
|
-
async function smartGitPushV2(args) {
|
|
33
|
-
const { branch, message, testResults, skipSecurity = false, dryRun = false, projectPath = process.cwd(), forceUnsafe = false, humanOverrides = [], requestHumanConfirmation = false, checkDeploymentReadiness = false, targetEnvironment = 'production', enforceDeploymentReadiness = false, strictDeploymentMode = true } = args;
|
|
33
|
+
export async function smartGitPushV2(args) {
|
|
34
|
+
const { branch, message, testResults, skipSecurity = false, dryRun = false, projectPath = process.cwd(), forceUnsafe = false, humanOverrides = [], requestHumanConfirmation = false, checkDeploymentReadiness = false, targetEnvironment = 'production', enforceDeploymentReadiness = false, strictDeploymentMode = true, } = args;
|
|
34
35
|
try {
|
|
35
36
|
// Step 1: Get staged files
|
|
36
37
|
const stagedFiles = await getStagedFiles(projectPath);
|
|
37
38
|
if (stagedFiles.length === 0) {
|
|
38
39
|
const metricsText = await getDeploymentMetricsSummary(projectPath);
|
|
39
40
|
return {
|
|
40
|
-
content: [
|
|
41
|
+
content: [
|
|
42
|
+
{
|
|
41
43
|
type: 'text',
|
|
42
|
-
text: createNoChangesResponse(metricsText)
|
|
43
|
-
}
|
|
44
|
+
text: createNoChangesResponse(metricsText),
|
|
45
|
+
},
|
|
46
|
+
],
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
// Step 2: Security scan (unless skipped)
|
|
@@ -55,10 +58,12 @@ async function smartGitPushV2(args) {
|
|
|
55
58
|
// Step 5: Check for confirmation requests
|
|
56
59
|
if (confirmationRequests.length > 0 && requestHumanConfirmation) {
|
|
57
60
|
return {
|
|
58
|
-
content: [
|
|
61
|
+
content: [
|
|
62
|
+
{
|
|
59
63
|
type: 'text',
|
|
60
|
-
text: generateConfirmationRequestResponse(confirmationRequests, stagedFiles)
|
|
61
|
-
}
|
|
64
|
+
text: generateConfirmationRequestResponse(confirmationRequests, stagedFiles),
|
|
65
|
+
},
|
|
66
|
+
],
|
|
62
67
|
};
|
|
63
68
|
}
|
|
64
69
|
// Step 5.5: Deployment Readiness Check (NEW)
|
|
@@ -80,19 +85,24 @@ async function smartGitPushV2(args) {
|
|
|
80
85
|
rollbackFrequencyThreshold: 20,
|
|
81
86
|
// Integration with existing systems
|
|
82
87
|
integrateTodoTasks: true,
|
|
83
|
-
updateHealthScoring: true
|
|
88
|
+
updateHealthScoring: true,
|
|
84
89
|
});
|
|
85
90
|
// Hard block if deployment is not ready and enforcement is enabled
|
|
86
|
-
if (!readinessCheck.isDeploymentReady &&
|
|
91
|
+
if (!readinessCheck.isDeploymentReady &&
|
|
92
|
+
(enforceDeploymentReadiness || strictDeploymentMode)) {
|
|
87
93
|
return {
|
|
88
|
-
content: [
|
|
94
|
+
content: [
|
|
95
|
+
{
|
|
89
96
|
type: 'text',
|
|
90
|
-
text: generateDeploymentReadinessBlockResponse(readinessCheck, stagedFiles, targetEnvironment)
|
|
91
|
-
}
|
|
97
|
+
text: generateDeploymentReadinessBlockResponse(readinessCheck, stagedFiles, targetEnvironment),
|
|
98
|
+
},
|
|
99
|
+
],
|
|
92
100
|
};
|
|
93
101
|
}
|
|
94
102
|
// Soft warning if just checking but not enforcing
|
|
95
|
-
if (!readinessCheck.isDeploymentReady &&
|
|
103
|
+
if (!readinessCheck.isDeploymentReady &&
|
|
104
|
+
checkDeploymentReadiness &&
|
|
105
|
+
!enforceDeploymentReadiness) {
|
|
96
106
|
// Continue with push but include warning in success response
|
|
97
107
|
}
|
|
98
108
|
}
|
|
@@ -102,10 +112,12 @@ async function smartGitPushV2(args) {
|
|
|
102
112
|
const shouldBlock = (hasCriticalSecurity || hasFailedTests) && !forceUnsafe;
|
|
103
113
|
if (shouldBlock) {
|
|
104
114
|
return {
|
|
105
|
-
content: [
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
106
117
|
type: 'text',
|
|
107
|
-
text: generateBlockedResponse(filteredSecurityIssues, filteredIrrelevantFiles, testResults, humanOverrides)
|
|
108
|
-
}
|
|
118
|
+
text: generateBlockedResponse(filteredSecurityIssues, filteredIrrelevantFiles, testResults, humanOverrides),
|
|
119
|
+
},
|
|
120
|
+
],
|
|
109
121
|
};
|
|
110
122
|
}
|
|
111
123
|
// Step 5: Execute push if not dry run
|
|
@@ -115,22 +127,26 @@ async function smartGitPushV2(args) {
|
|
|
115
127
|
await updateDeploymentHistory(projectPath, {
|
|
116
128
|
success: true,
|
|
117
129
|
...(testResults && { testResults }),
|
|
118
|
-
filesChanged: stagedFiles.length
|
|
130
|
+
filesChanged: stagedFiles.length,
|
|
119
131
|
});
|
|
120
132
|
return {
|
|
121
|
-
content: [
|
|
133
|
+
content: [
|
|
134
|
+
{
|
|
122
135
|
type: 'text',
|
|
123
|
-
text: generateSuccessResponse(stagedFiles, filteredSecurityIssues, filteredIrrelevantFiles, testResults, pushResult, branch, humanOverrides)
|
|
124
|
-
}
|
|
136
|
+
text: generateSuccessResponse(stagedFiles, filteredSecurityIssues, filteredIrrelevantFiles, testResults, pushResult, branch, humanOverrides),
|
|
137
|
+
},
|
|
138
|
+
],
|
|
125
139
|
};
|
|
126
140
|
}
|
|
127
141
|
else {
|
|
128
142
|
// Dry run response
|
|
129
143
|
return {
|
|
130
|
-
content: [
|
|
144
|
+
content: [
|
|
145
|
+
{
|
|
131
146
|
type: 'text',
|
|
132
|
-
text: generateDryRunResponse(stagedFiles, filteredSecurityIssues, filteredIrrelevantFiles, testResults, branch)
|
|
133
|
-
}
|
|
147
|
+
text: generateDryRunResponse(stagedFiles, filteredSecurityIssues, filteredIrrelevantFiles, testResults, branch),
|
|
148
|
+
},
|
|
149
|
+
],
|
|
134
150
|
};
|
|
135
151
|
}
|
|
136
152
|
}
|
|
@@ -139,7 +155,7 @@ async function smartGitPushV2(args) {
|
|
|
139
155
|
await updateDeploymentHistory(projectPath, {
|
|
140
156
|
success: false,
|
|
141
157
|
testResults: testResults || { success: false, testsRun: 0, testsPassed: 0, testsFailed: 0 },
|
|
142
|
-
filesChanged: 0
|
|
158
|
+
filesChanged: 0,
|
|
143
159
|
});
|
|
144
160
|
throw new McpAdrError('Smart git push failed: ' + jsonSafeError(error), 'GIT_PUSH_ERROR');
|
|
145
161
|
}
|
|
@@ -151,7 +167,7 @@ async function getStagedFiles(projectPath) {
|
|
|
151
167
|
try {
|
|
152
168
|
const gitOutput = execSync('git diff --cached --name-status', {
|
|
153
169
|
cwd: projectPath,
|
|
154
|
-
encoding: 'utf8'
|
|
170
|
+
encoding: 'utf8',
|
|
155
171
|
});
|
|
156
172
|
if (!gitOutput.trim()) {
|
|
157
173
|
return [];
|
|
@@ -173,7 +189,7 @@ async function getStagedFiles(projectPath) {
|
|
|
173
189
|
content = readFileSync(fullPath, 'utf8');
|
|
174
190
|
}
|
|
175
191
|
}
|
|
176
|
-
catch
|
|
192
|
+
catch {
|
|
177
193
|
// Ignore read errors
|
|
178
194
|
}
|
|
179
195
|
}
|
|
@@ -181,7 +197,7 @@ async function getStagedFiles(projectPath) {
|
|
|
181
197
|
path,
|
|
182
198
|
status: mapGitStatus(status || 'M'),
|
|
183
199
|
content: content || '',
|
|
184
|
-
size
|
|
200
|
+
size,
|
|
185
201
|
});
|
|
186
202
|
}
|
|
187
203
|
return files;
|
|
@@ -196,22 +212,25 @@ async function getStagedFiles(projectPath) {
|
|
|
196
212
|
async function scanForSecurityIssues(files, _projectPath) {
|
|
197
213
|
const issues = [];
|
|
198
214
|
try {
|
|
199
|
-
const { analyzeSensitiveContent } = await import('../utils/
|
|
215
|
+
const { analyzeSensitiveContent } = await import('../utils/gitleaks-detector.js');
|
|
200
216
|
for (const file of files) {
|
|
201
217
|
if (file.status === 'deleted' || !file.content)
|
|
202
218
|
continue;
|
|
203
219
|
const result = await analyzeSensitiveContent(file.path, file.content);
|
|
204
220
|
for (const match of result.matches) {
|
|
205
221
|
// Map to our simplified security issue format
|
|
206
|
-
const severity = match.pattern.severity === 'critical'
|
|
207
|
-
|
|
222
|
+
const severity = match.pattern.severity === 'critical'
|
|
223
|
+
? 'critical'
|
|
224
|
+
: match.pattern.severity === 'high'
|
|
225
|
+
? 'high'
|
|
226
|
+
: 'medium';
|
|
208
227
|
issues.push({
|
|
209
228
|
type: mapPatternToType(match.pattern.name),
|
|
210
229
|
severity,
|
|
211
230
|
file: file.path,
|
|
212
231
|
line: match.line,
|
|
213
232
|
pattern: match.pattern.name,
|
|
214
|
-
recommendation: getSecurityRecommendation(match.pattern.name)
|
|
233
|
+
recommendation: getSecurityRecommendation(match.pattern.name),
|
|
215
234
|
});
|
|
216
235
|
}
|
|
217
236
|
}
|
|
@@ -231,7 +250,7 @@ async function checkIrrelevantFiles(files) {
|
|
|
231
250
|
'build-artifact': /^(dist|build|out|target|bin|obj)\//,
|
|
232
251
|
'ide-config': /^\.(vscode|idea|eclipse|sublime-|atom|brackets)\//,
|
|
233
252
|
'log-file': /\.(log|logs)$/i,
|
|
234
|
-
'cache-file': /^(\.(cache|npm|yarn|pnpm)|node_modules|__pycache__|\.pytest_cache)
|
|
253
|
+
'cache-file': /^(\.(cache|npm|yarn|pnpm)|node_modules|__pycache__|\.pytest_cache)\//,
|
|
235
254
|
};
|
|
236
255
|
for (const file of files) {
|
|
237
256
|
if (file.status === 'deleted')
|
|
@@ -241,7 +260,7 @@ async function checkIrrelevantFiles(files) {
|
|
|
241
260
|
irrelevant.push({
|
|
242
261
|
path: file.path,
|
|
243
262
|
reason: reason,
|
|
244
|
-
recommendation: getIrrelevantFileRecommendation(reason)
|
|
263
|
+
recommendation: getIrrelevantFileRecommendation(reason),
|
|
245
264
|
});
|
|
246
265
|
break;
|
|
247
266
|
}
|
|
@@ -251,7 +270,7 @@ async function checkIrrelevantFiles(files) {
|
|
|
251
270
|
irrelevant.push({
|
|
252
271
|
path: file.path,
|
|
253
272
|
reason: 'build-artifact',
|
|
254
|
-
recommendation: 'Large file (' + Math.round(file.size / 1024 / 1024) + 'MB) - consider using Git LFS'
|
|
273
|
+
recommendation: 'Large file (' + Math.round(file.size / 1024 / 1024) + 'MB) - consider using Git LFS',
|
|
255
274
|
});
|
|
256
275
|
}
|
|
257
276
|
}
|
|
@@ -261,7 +280,8 @@ async function checkIrrelevantFiles(files) {
|
|
|
261
280
|
* Update deployment history
|
|
262
281
|
*/
|
|
263
282
|
async function updateDeploymentHistory(projectPath, result) {
|
|
264
|
-
const
|
|
283
|
+
const projectName = basename(projectPath);
|
|
284
|
+
const cacheDir = join(os.tmpdir(), projectName, 'cache');
|
|
265
285
|
const historyFile = join(cacheDir, 'deploy-history.json');
|
|
266
286
|
// Ensure cache directory exists
|
|
267
287
|
if (!existsSync(cacheDir)) {
|
|
@@ -276,16 +296,16 @@ async function updateDeploymentHistory(projectPath, result) {
|
|
|
276
296
|
totalTestsPassed: 0,
|
|
277
297
|
totalTestsFailed: 0,
|
|
278
298
|
averageDuration: 0,
|
|
279
|
-
testTypes: {}
|
|
299
|
+
testTypes: {},
|
|
280
300
|
},
|
|
281
301
|
successRate: 0,
|
|
282
|
-
testPassRate: 0
|
|
302
|
+
testPassRate: 0,
|
|
283
303
|
};
|
|
284
304
|
if (existsSync(historyFile)) {
|
|
285
305
|
try {
|
|
286
306
|
history = JSON.parse(readFileSync(historyFile, 'utf8'));
|
|
287
307
|
}
|
|
288
|
-
catch
|
|
308
|
+
catch {
|
|
289
309
|
// Ignore parse errors
|
|
290
310
|
}
|
|
291
311
|
}
|
|
@@ -322,7 +342,9 @@ async function updateDeploymentHistory(projectPath, result) {
|
|
|
322
342
|
const currentAvg = history.testResults.averageDuration || 0;
|
|
323
343
|
const totalRuns = history.successful + history.failed;
|
|
324
344
|
history.testResults.averageDuration =
|
|
325
|
-
totalRuns > 1
|
|
345
|
+
totalRuns > 1
|
|
346
|
+
? (currentAvg * (totalRuns - 1) + result.testResults.duration) / totalRuns
|
|
347
|
+
: result.testResults.duration;
|
|
326
348
|
}
|
|
327
349
|
// Set last test suite if command provided
|
|
328
350
|
if (result.testResults.command) {
|
|
@@ -331,11 +353,11 @@ async function updateDeploymentHistory(projectPath, result) {
|
|
|
331
353
|
}
|
|
332
354
|
// Calculate rates
|
|
333
355
|
const totalDeploys = history.successful + history.failed;
|
|
334
|
-
history.successRate =
|
|
335
|
-
Math.round((history.successful / totalDeploys) * 100) : 0;
|
|
356
|
+
history.successRate =
|
|
357
|
+
totalDeploys > 0 ? Math.round((history.successful / totalDeploys) * 100) : 0;
|
|
336
358
|
const totalTests = history.testResults.totalTestsPassed + history.testResults.totalTestsFailed;
|
|
337
|
-
history.testPassRate =
|
|
338
|
-
Math.round((history.testResults.totalTestsPassed / totalTests) * 100) : 0;
|
|
359
|
+
history.testPassRate =
|
|
360
|
+
totalTests > 0 ? Math.round((history.testResults.totalTestsPassed / totalTests) * 100) : 0;
|
|
339
361
|
// Save updated history
|
|
340
362
|
writeFileSync(historyFile, JSON.stringify(history, null, 2));
|
|
341
363
|
}
|
|
@@ -343,23 +365,48 @@ async function updateDeploymentHistory(projectPath, result) {
|
|
|
343
365
|
* Get deployment metrics summary
|
|
344
366
|
*/
|
|
345
367
|
async function getDeploymentMetricsSummary(projectPath) {
|
|
346
|
-
const
|
|
368
|
+
const projectName = basename(projectPath);
|
|
369
|
+
const cacheDir = join(os.tmpdir(), projectName, 'cache');
|
|
370
|
+
const historyFile = join(cacheDir, 'deploy-history.json');
|
|
347
371
|
if (!existsSync(historyFile)) {
|
|
348
372
|
return '- No deployment history available';
|
|
349
373
|
}
|
|
350
374
|
try {
|
|
351
375
|
const history = JSON.parse(readFileSync(historyFile, 'utf8'));
|
|
352
376
|
const lines = [
|
|
353
|
-
'- **Deploy Success Rate**: ' +
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
377
|
+
'- **Deploy Success Rate**: ' +
|
|
378
|
+
history.successRate +
|
|
379
|
+
'% (' +
|
|
380
|
+
history.successful +
|
|
381
|
+
'/' +
|
|
382
|
+
(history.successful + history.failed) +
|
|
383
|
+
')',
|
|
384
|
+
'- **Test Pass Rate**: ' +
|
|
385
|
+
history.testPassRate +
|
|
386
|
+
'% (' +
|
|
387
|
+
history.testResults.totalTestsPassed +
|
|
388
|
+
'/' +
|
|
389
|
+
(history.testResults.totalTestsPassed + history.testResults.totalTestsFailed) +
|
|
390
|
+
')',
|
|
391
|
+
'- **Last Deploy**: ' +
|
|
392
|
+
(history.lastDeploy ? new Date(history.lastDeploy).toLocaleString() : 'Never') +
|
|
393
|
+
' ' +
|
|
394
|
+
(history.lastDeploySuccess ? '✅' : '❌'),
|
|
395
|
+
'- **Last Test Run**: ' +
|
|
396
|
+
(history.testResults.lastRun
|
|
397
|
+
? new Date(history.testResults.lastRun).toLocaleString()
|
|
398
|
+
: 'Never') +
|
|
399
|
+
' ' +
|
|
400
|
+
(history.testResults.lastRunSuccess ? '✅' : '❌'),
|
|
357
401
|
'- **Total Tests Executed**: ' + history.testResults.totalTestsRun,
|
|
358
|
-
'- **Avg Test Duration**: ' +
|
|
402
|
+
'- **Avg Test Duration**: ' +
|
|
403
|
+
(history.testResults.averageDuration
|
|
404
|
+
? Math.round(history.testResults.averageDuration) + 's'
|
|
405
|
+
: 'N/A'),
|
|
359
406
|
];
|
|
360
407
|
return lines.join('\n');
|
|
361
408
|
}
|
|
362
|
-
catch
|
|
409
|
+
catch {
|
|
363
410
|
return '- Error reading deployment history';
|
|
364
411
|
}
|
|
365
412
|
}
|
|
@@ -372,7 +419,7 @@ async function executePush(projectPath, branch, message) {
|
|
|
372
419
|
if (message) {
|
|
373
420
|
const commitOutput = execSync('git commit -m "' + message + '"', {
|
|
374
421
|
cwd: projectPath,
|
|
375
|
-
encoding: 'utf8'
|
|
422
|
+
encoding: 'utf8',
|
|
376
423
|
});
|
|
377
424
|
output += 'Commit:\n' + commitOutput + '\n\n';
|
|
378
425
|
}
|
|
@@ -380,7 +427,7 @@ async function executePush(projectPath, branch, message) {
|
|
|
380
427
|
const pushOutput = execSync(pushCommand, {
|
|
381
428
|
cwd: projectPath,
|
|
382
429
|
encoding: 'utf8',
|
|
383
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
430
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
384
431
|
});
|
|
385
432
|
output += 'Push:\n' + pushOutput;
|
|
386
433
|
return { output, success: true };
|
|
@@ -392,18 +439,47 @@ async function executePush(projectPath, branch, message) {
|
|
|
392
439
|
// Helper functions
|
|
393
440
|
function mapGitStatus(status) {
|
|
394
441
|
switch (status) {
|
|
395
|
-
case 'A':
|
|
396
|
-
|
|
397
|
-
case '
|
|
398
|
-
|
|
399
|
-
|
|
442
|
+
case 'A':
|
|
443
|
+
return 'added';
|
|
444
|
+
case 'M':
|
|
445
|
+
return 'modified';
|
|
446
|
+
case 'D':
|
|
447
|
+
return 'deleted';
|
|
448
|
+
case 'R':
|
|
449
|
+
return 'renamed';
|
|
450
|
+
default:
|
|
451
|
+
return 'modified';
|
|
400
452
|
}
|
|
401
453
|
}
|
|
402
454
|
function isTextFile(path) {
|
|
403
455
|
const textExtensions = [
|
|
404
|
-
'.js',
|
|
405
|
-
'.
|
|
406
|
-
'.
|
|
456
|
+
'.js',
|
|
457
|
+
'.ts',
|
|
458
|
+
'.jsx',
|
|
459
|
+
'.tsx',
|
|
460
|
+
'.json',
|
|
461
|
+
'.md',
|
|
462
|
+
'.txt',
|
|
463
|
+
'.yml',
|
|
464
|
+
'.yaml',
|
|
465
|
+
'.py',
|
|
466
|
+
'.rb',
|
|
467
|
+
'.java',
|
|
468
|
+
'.cs',
|
|
469
|
+
'.go',
|
|
470
|
+
'.rs',
|
|
471
|
+
'.cpp',
|
|
472
|
+
'.c',
|
|
473
|
+
'.h',
|
|
474
|
+
'.hpp',
|
|
475
|
+
'.php',
|
|
476
|
+
'.html',
|
|
477
|
+
'.css',
|
|
478
|
+
'.scss',
|
|
479
|
+
'.sass',
|
|
480
|
+
'.less',
|
|
481
|
+
'.vue',
|
|
482
|
+
'.svelte',
|
|
407
483
|
];
|
|
408
484
|
return textExtensions.includes(extname(path).toLowerCase());
|
|
409
485
|
}
|
|
@@ -431,12 +507,18 @@ function getSecurityRecommendation(pattern) {
|
|
|
431
507
|
}
|
|
432
508
|
function getIrrelevantFileRecommendation(reason) {
|
|
433
509
|
switch (reason) {
|
|
434
|
-
case 'temp-file':
|
|
435
|
-
|
|
436
|
-
case '
|
|
437
|
-
|
|
438
|
-
case '
|
|
439
|
-
|
|
510
|
+
case 'temp-file':
|
|
511
|
+
return 'Add to .gitignore - temporary files should not be committed';
|
|
512
|
+
case 'build-artifact':
|
|
513
|
+
return 'Add to .gitignore - build outputs should not be in source control';
|
|
514
|
+
case 'ide-config':
|
|
515
|
+
return 'Add to .gitignore - IDE configurations are user-specific';
|
|
516
|
+
case 'log-file':
|
|
517
|
+
return 'Add to .gitignore - log files should not be committed';
|
|
518
|
+
case 'cache-file':
|
|
519
|
+
return 'Add to .gitignore - cache files are generated';
|
|
520
|
+
default:
|
|
521
|
+
return 'Consider adding to .gitignore';
|
|
440
522
|
}
|
|
441
523
|
}
|
|
442
524
|
// Human Override Functions
|
|
@@ -458,7 +540,7 @@ async function applyHumanOverrides(securityIssues, irrelevantFiles, humanOverrid
|
|
|
458
540
|
detectedIssue: issue,
|
|
459
541
|
suggestedPurpose: analyzeFilePurpose(issue.file),
|
|
460
542
|
riskLevel: issue.severity,
|
|
461
|
-
alternatives: generateAlternatives(issue)
|
|
543
|
+
alternatives: generateAlternatives(issue),
|
|
462
544
|
});
|
|
463
545
|
}
|
|
464
546
|
return true; // Keep issue if no override
|
|
@@ -476,7 +558,7 @@ async function applyHumanOverrides(securityIssues, irrelevantFiles, humanOverrid
|
|
|
476
558
|
detectedIssue: file,
|
|
477
559
|
suggestedPurpose: analyzeFilePurpose(file.path),
|
|
478
560
|
riskLevel: 'medium',
|
|
479
|
-
alternatives: generateAlternatives(file)
|
|
561
|
+
alternatives: generateAlternatives(file),
|
|
480
562
|
});
|
|
481
563
|
}
|
|
482
564
|
return true; // Keep file if no override
|
|
@@ -484,7 +566,7 @@ async function applyHumanOverrides(securityIssues, irrelevantFiles, humanOverrid
|
|
|
484
566
|
return {
|
|
485
567
|
filteredSecurityIssues,
|
|
486
568
|
filteredIrrelevantFiles,
|
|
487
|
-
confirmationRequests
|
|
569
|
+
confirmationRequests,
|
|
488
570
|
};
|
|
489
571
|
}
|
|
490
572
|
/**
|
|
@@ -493,7 +575,9 @@ async function applyHumanOverrides(securityIssues, irrelevantFiles, humanOverrid
|
|
|
493
575
|
function analyzeFilePurpose(filePath) {
|
|
494
576
|
const fileName = filePath.toLowerCase();
|
|
495
577
|
// Configuration files
|
|
496
|
-
if (fileName.includes('config') ||
|
|
578
|
+
if (fileName.includes('config') ||
|
|
579
|
+
fileName.endsWith('.config.js') ||
|
|
580
|
+
fileName.endsWith('.config.ts')) {
|
|
497
581
|
return 'Configuration file - may contain environment-specific settings';
|
|
498
582
|
}
|
|
499
583
|
// Build/deployment files
|
|
@@ -505,7 +589,9 @@ function analyzeFilePurpose(filePath) {
|
|
|
505
589
|
return 'Development or debugging file - may be temporary';
|
|
506
590
|
}
|
|
507
591
|
// IDE/editor files
|
|
508
|
-
if (fileName.includes('.vscode') ||
|
|
592
|
+
if (fileName.includes('.vscode') ||
|
|
593
|
+
fileName.includes('.idea') ||
|
|
594
|
+
fileName.includes('.settings')) {
|
|
509
595
|
return 'IDE/editor configuration - user-specific preferences';
|
|
510
596
|
}
|
|
511
597
|
// Log files
|
|
@@ -517,7 +603,9 @@ function analyzeFilePurpose(filePath) {
|
|
|
517
603
|
return 'Security-sensitive file - may contain credentials or keys';
|
|
518
604
|
}
|
|
519
605
|
// Cache/temporary
|
|
520
|
-
if (fileName.includes('cache') ||
|
|
606
|
+
if (fileName.includes('cache') ||
|
|
607
|
+
fileName.includes('node_modules') ||
|
|
608
|
+
fileName.includes('.cache')) {
|
|
521
609
|
return 'Cache or temporary data - generated content';
|
|
522
610
|
}
|
|
523
611
|
return 'Unknown purpose - manual review recommended';
|
|
@@ -577,11 +665,12 @@ function generateAlternatives(issue) {
|
|
|
577
665
|
}
|
|
578
666
|
// Response generators
|
|
579
667
|
function createNoChangesResponse(metricsText) {
|
|
580
|
-
return '# Smart Git Push - No Changes\n\n' +
|
|
668
|
+
return ('# Smart Git Push - No Changes\n\n' +
|
|
581
669
|
'## Status\n' +
|
|
582
670
|
'No staged files found. Use git add to stage files before pushing.\n\n' +
|
|
583
671
|
'## Deployment Metrics\n' +
|
|
584
|
-
metricsText +
|
|
672
|
+
metricsText +
|
|
673
|
+
'\n\n' +
|
|
585
674
|
'## ⚠️ IMPORTANT: Selective File Staging\n' +
|
|
586
675
|
'**DO NOT USE:** `git add .` or `git add -A` (stages everything including unintended files)\n\n' +
|
|
587
676
|
'**RECOMMENDED APPROACH:**\n' +
|
|
@@ -599,7 +688,7 @@ function createNoChangesResponse(metricsText) {
|
|
|
599
688
|
'- [ ] Code reviewed and approved\n' +
|
|
600
689
|
'- [ ] No sensitive data in changes\n' +
|
|
601
690
|
'- [ ] Documentation updated if needed\n' +
|
|
602
|
-
'- [ ] Deployment strategy confirmed';
|
|
691
|
+
'- [ ] Deployment strategy confirmed');
|
|
603
692
|
}
|
|
604
693
|
/**
|
|
605
694
|
* Generate confirmation request response for human override
|
|
@@ -610,141 +699,198 @@ function generateConfirmationRequestResponse(confirmationRequests, stagedFiles)
|
|
|
610
699
|
`The LLM has detected ${confirmationRequests.length} files that need your confirmation before proceeding.\n\n`;
|
|
611
700
|
confirmationRequests.forEach((request, index) => {
|
|
612
701
|
const isSecurityIssue = 'severity' in request.detectedIssue;
|
|
613
|
-
const riskEmoji = request.riskLevel === 'critical'
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
702
|
+
const riskEmoji = request.riskLevel === 'critical'
|
|
703
|
+
? '🔴'
|
|
704
|
+
: request.riskLevel === 'high'
|
|
705
|
+
? '🟠'
|
|
706
|
+
: request.riskLevel === 'medium'
|
|
707
|
+
? '🟡'
|
|
708
|
+
: '🟢';
|
|
709
|
+
response +=
|
|
710
|
+
`### ${index + 1}. ${jsonSafeFilePath(request.path)} ${riskEmoji}\n\n` +
|
|
711
|
+
`**Detected Issue**: ${isSecurityIssue ? 'Security Risk' : 'Irrelevant File'}\n` +
|
|
712
|
+
`**Risk Level**: ${request.riskLevel.toUpperCase()}\n` +
|
|
713
|
+
`**LLM Analysis**: ${request.suggestedPurpose}\n\n` +
|
|
714
|
+
`**Recommended Alternatives**:\n${request.alternatives.map(alt => `- ${alt}`).join('\n')}\n\n` +
|
|
715
|
+
`**To Override**: Confirm this file's purpose and business justification.\n\n`;
|
|
622
716
|
});
|
|
623
|
-
response +=
|
|
624
|
-
'
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
717
|
+
response +=
|
|
718
|
+
'## Override Instructions\n\n' +
|
|
719
|
+
'To proceed with these files, rerun the command with human overrides:\n\n' +
|
|
720
|
+
'```json\n' +
|
|
721
|
+
'{\n' +
|
|
722
|
+
' "operation": "smart_git_push",\n' +
|
|
723
|
+
' "humanOverrides": [\n' +
|
|
724
|
+
confirmationRequests
|
|
725
|
+
.map(req => ' {\n' +
|
|
726
|
+
` "path": "${req.path}",\n` +
|
|
727
|
+
` "purpose": "YOUR_BUSINESS_JUSTIFICATION_HERE",\n` +
|
|
728
|
+
' "userConfirmed": true,\n' +
|
|
729
|
+
` "timestamp": "${new Date().toISOString()}",\n` +
|
|
730
|
+
' "overrideReason": "business-requirement", // or security-exception, deployment-necessity, etc.\n' +
|
|
731
|
+
' "additionalContext": "EXPLAIN_WHY_THIS_IS_NECESSARY"\n' +
|
|
732
|
+
' }')
|
|
733
|
+
.join(',\n') +
|
|
734
|
+
'\n' +
|
|
735
|
+
' ]\n' +
|
|
736
|
+
'}\n' +
|
|
737
|
+
'```\n\n' +
|
|
738
|
+
'## ⚠️ Important Reminders\n' +
|
|
739
|
+
'- **Only override if you understand the business need**\n' +
|
|
740
|
+
'- **Document the purpose clearly**\n' +
|
|
741
|
+
'- **Consider the security implications**\n' +
|
|
742
|
+
'- **Review alternatives before overriding**\n\n' +
|
|
743
|
+
`**Total staged files**: ${stagedFiles.length} | **Files needing confirmation**: ${confirmationRequests.length}`;
|
|
646
744
|
return response;
|
|
647
745
|
}
|
|
648
746
|
function generateBlockedResponse(securityIssues, _irrelevantFiles, testResults, humanOverrides) {
|
|
649
747
|
let response = '# Smart Git Push - Blocked 🚫\n\n## Push Blocked Due to Critical Issues\n\n';
|
|
650
748
|
if (securityIssues.some(i => i.severity === 'critical')) {
|
|
651
|
-
const criticalIssues = securityIssues
|
|
652
|
-
|
|
653
|
-
'
|
|
749
|
+
const criticalIssues = securityIssues
|
|
750
|
+
.filter(i => i.severity === 'critical')
|
|
751
|
+
.map(issue => '- **' +
|
|
752
|
+
issue.type +
|
|
753
|
+
'** in ' +
|
|
754
|
+
jsonSafeFilePath(issue.file) +
|
|
755
|
+
(issue.line ? ' (line ' + issue.line + ')' : '') +
|
|
756
|
+
'\n' +
|
|
757
|
+
' Pattern: ' +
|
|
758
|
+
issue.pattern +
|
|
759
|
+
'\n' +
|
|
760
|
+
' Fix: ' +
|
|
761
|
+
issue.recommendation)
|
|
762
|
+
.join('\n\n');
|
|
654
763
|
response += '### 🔐 Critical Security Issues Found\n' + criticalIssues + '\n\n';
|
|
655
764
|
}
|
|
656
765
|
if (testResults && !testResults.success) {
|
|
657
|
-
response +=
|
|
658
|
-
'
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
766
|
+
response +=
|
|
767
|
+
'### 🧪 Tests Failed\n' +
|
|
768
|
+
'- **Command**: ' +
|
|
769
|
+
testResults.command +
|
|
770
|
+
'\n' +
|
|
771
|
+
'- **Output**:\n' +
|
|
772
|
+
'-------\n' +
|
|
773
|
+
jsonSafeUserInput(testResults.output) +
|
|
774
|
+
'\n' +
|
|
775
|
+
'-------\n\n';
|
|
663
776
|
}
|
|
664
777
|
// Show human override status if provided
|
|
665
778
|
if (humanOverrides && humanOverrides.length > 0) {
|
|
666
779
|
response += '## Human Overrides Applied\n';
|
|
667
780
|
humanOverrides.forEach(override => {
|
|
668
|
-
response +=
|
|
669
|
-
|
|
781
|
+
response +=
|
|
782
|
+
`- **${jsonSafeFilePath(override.path)}**: ${override.purpose}\n` +
|
|
783
|
+
` Reason: ${override.overrideReason} | Confirmed: ${override.userConfirmed ? '✅' : '❌'}\n`;
|
|
670
784
|
});
|
|
671
785
|
response += '\n';
|
|
672
786
|
}
|
|
673
|
-
response +=
|
|
674
|
-
'
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
787
|
+
response +=
|
|
788
|
+
'## Required Actions\n' +
|
|
789
|
+
'1. Fix all critical security issues\n' +
|
|
790
|
+
'2. Ensure all tests pass\n' +
|
|
791
|
+
'3. Review and fix any warnings\n' +
|
|
792
|
+
'4. OR use human overrides with proper justification\n\n' +
|
|
793
|
+
'## ⚠️ IMPORTANT: File Staging Best Practices\n' +
|
|
794
|
+
'**NEVER USE:** `git add .` or `git add -A` when fixing issues\n' +
|
|
795
|
+
'**RECOMMENDED:**\n' +
|
|
796
|
+
'1. Fix specific issues in specific files\n' +
|
|
797
|
+
'2. Stage only the fixed files: `git add <fixed-file>`\n' +
|
|
798
|
+
'3. Verify changes: `git diff --cached`\n' +
|
|
799
|
+
'4. Re-run smart git push\n\n' +
|
|
800
|
+
'## Human Override Option\n' +
|
|
801
|
+
'If these issues are expected and have business justification:\n' +
|
|
802
|
+
'1. Use `requestHumanConfirmation: true` to get guided override instructions\n' +
|
|
803
|
+
'2. Provide detailed justification for each file\n' +
|
|
804
|
+
'3. Consider security implications carefully\n\n' +
|
|
805
|
+
'🚫 Use --forceUnsafe to override (NOT RECOMMENDED)';
|
|
691
806
|
return response;
|
|
692
807
|
}
|
|
693
808
|
function generateSuccessResponse(stagedFiles, securityIssues, irrelevantFiles, testResults, pushResult, branch, humanOverrides) {
|
|
694
809
|
let response = '# Smart Git Push - Success ✅\n\n' +
|
|
695
810
|
'## Push Summary\n' +
|
|
696
|
-
'- **Branch**: ' +
|
|
697
|
-
|
|
698
|
-
'
|
|
699
|
-
'- **
|
|
700
|
-
|
|
811
|
+
'- **Branch**: ' +
|
|
812
|
+
(branch || 'current') +
|
|
813
|
+
'\n' +
|
|
814
|
+
'- **Files**: ' +
|
|
815
|
+
stagedFiles.length +
|
|
816
|
+
' staged files\n' +
|
|
817
|
+
'- **Security Issues**: ' +
|
|
818
|
+
securityIssues.length +
|
|
819
|
+
' (' +
|
|
820
|
+
securityIssues.filter(i => i.severity === 'critical').length +
|
|
821
|
+
' critical)\n' +
|
|
822
|
+
'- **Irrelevant Files**: ' +
|
|
823
|
+
irrelevantFiles.length +
|
|
824
|
+
'\n' +
|
|
825
|
+
'- **Tests**: ' +
|
|
826
|
+
(testResults ? (testResults.success ? '✅ Passed' : '❌ Failed') : 'Skipped') +
|
|
827
|
+
'\n\n' +
|
|
701
828
|
'## Deployment Metrics Updated\n' +
|
|
702
|
-
getDeploymentMetricsUpdate() +
|
|
829
|
+
getDeploymentMetricsUpdate() +
|
|
830
|
+
'\n\n' +
|
|
703
831
|
'## Files Pushed\n' +
|
|
704
832
|
stagedFiles.map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.status + ')').join('\n');
|
|
705
833
|
if (securityIssues.length > 0) {
|
|
706
834
|
const nonCriticalIssues = securityIssues.filter(i => i.severity !== 'critical');
|
|
707
835
|
if (nonCriticalIssues.length > 0) {
|
|
708
|
-
response +=
|
|
709
|
-
|
|
836
|
+
response +=
|
|
837
|
+
'\n\n## Security Warnings (Non-Critical)\n' +
|
|
838
|
+
nonCriticalIssues
|
|
839
|
+
.map(issue => '- **' +
|
|
840
|
+
issue.type +
|
|
841
|
+
'** in ' +
|
|
842
|
+
jsonSafeFilePath(issue.file) +
|
|
843
|
+
': ' +
|
|
844
|
+
issue.recommendation)
|
|
845
|
+
.join('\n');
|
|
710
846
|
}
|
|
711
847
|
}
|
|
712
848
|
if (irrelevantFiles.length > 0) {
|
|
713
|
-
response +=
|
|
714
|
-
|
|
849
|
+
response +=
|
|
850
|
+
'\n\n## Irrelevant Files (Consider .gitignore)\n' +
|
|
851
|
+
irrelevantFiles
|
|
852
|
+
.map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.reason + '): ' + f.recommendation)
|
|
853
|
+
.join('\n');
|
|
715
854
|
}
|
|
716
855
|
// Show human overrides if any were applied
|
|
717
856
|
if (humanOverrides && humanOverrides.length > 0) {
|
|
718
|
-
response +=
|
|
719
|
-
'
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
'
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
857
|
+
response +=
|
|
858
|
+
'\n\n## ✅ Human Overrides Applied\n' +
|
|
859
|
+
'The following files were explicitly approved by human override:\n' +
|
|
860
|
+
humanOverrides
|
|
861
|
+
.filter(o => o.userConfirmed)
|
|
862
|
+
.map(override => `- **${jsonSafeFilePath(override.path)}**: ${override.purpose}\n` +
|
|
863
|
+
` Justification: ${override.additionalContext || 'No additional context'}\n` +
|
|
864
|
+
` Override Reason: ${override.overrideReason}\n` +
|
|
865
|
+
` Timestamp: ${new Date(override.timestamp).toLocaleString()}`)
|
|
866
|
+
.join('\n\n') +
|
|
867
|
+
'\n\n' +
|
|
868
|
+
'📝 **Note**: These overrides have been logged for audit purposes.';
|
|
869
|
+
}
|
|
870
|
+
response +=
|
|
871
|
+
'\n\n## Git Output\n' +
|
|
872
|
+
'-------\n' +
|
|
873
|
+
jsonSafeUserInput(pushResult.output) +
|
|
874
|
+
'\n' +
|
|
875
|
+
'-------\n\n' +
|
|
876
|
+
'## 🚀 Post-Push Deployment Checklist\n' +
|
|
877
|
+
'### Immediate Actions (Next 5 minutes)\n' +
|
|
878
|
+
'- [ ] Monitor CI/CD pipeline status\n' +
|
|
879
|
+
'- [ ] Check automated test results\n' +
|
|
880
|
+
'- [ ] Verify build completion\n' +
|
|
881
|
+
'- [ ] Review any deployment warnings\n\n' +
|
|
882
|
+
'### Deployment Completion (Next 15 minutes)\n' +
|
|
883
|
+
'- [ ] Confirm deployment to staging/production\n' +
|
|
884
|
+
'- [ ] Verify application health checks\n' +
|
|
885
|
+
'- [ ] Test key functionality post-deployment\n' +
|
|
886
|
+
'- [ ] Monitor error rates and performance metrics\n' +
|
|
887
|
+
'- [ ] Update TODO list with deployment status\n\n' +
|
|
888
|
+
'### Documentation & Communication\n' +
|
|
889
|
+
'- [ ] Update deployment notes\n' +
|
|
890
|
+
'- [ ] Notify team of successful deployment\n' +
|
|
891
|
+
'- [ ] Close related tickets/issues\n' +
|
|
892
|
+
'- [ ] Schedule post-deployment review if needed\n\n' +
|
|
893
|
+
'💡 **Tip**: Use the TODO management tool to track deployment completion tasks!';
|
|
748
894
|
return response;
|
|
749
895
|
}
|
|
750
896
|
function generateDryRunResponse(stagedFiles, securityIssues, irrelevantFiles, testResults, branch) {
|
|
@@ -752,53 +898,82 @@ function generateDryRunResponse(stagedFiles, securityIssues, irrelevantFiles, te
|
|
|
752
898
|
const wouldBlock = hasCritical || (testResults && !testResults.success);
|
|
753
899
|
let response = '# Smart Git Push - Dry Run 🔍\n\n' +
|
|
754
900
|
'## Analysis Results\n' +
|
|
755
|
-
'- **Files to Push**: ' +
|
|
756
|
-
|
|
757
|
-
'
|
|
758
|
-
'- **
|
|
901
|
+
'- **Files to Push**: ' +
|
|
902
|
+
stagedFiles.length +
|
|
903
|
+
'\n' +
|
|
904
|
+
'- **Security Issues**: ' +
|
|
905
|
+
securityIssues.length +
|
|
906
|
+
' (' +
|
|
907
|
+
securityIssues.filter(i => i.severity === 'critical').length +
|
|
908
|
+
' critical)\n' +
|
|
909
|
+
'- **Irrelevant Files**: ' +
|
|
910
|
+
irrelevantFiles.length +
|
|
911
|
+
'\n' +
|
|
912
|
+
'- **Would Block**: ' +
|
|
913
|
+
(wouldBlock ? '❌ Yes' : '✅ No') +
|
|
914
|
+
'\n\n' +
|
|
759
915
|
'## Staged Files\n' +
|
|
760
|
-
stagedFiles
|
|
916
|
+
stagedFiles
|
|
917
|
+
.map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.status + ') - ' + f.size + ' bytes')
|
|
918
|
+
.join('\n');
|
|
761
919
|
if (securityIssues.length > 0) {
|
|
762
|
-
response +=
|
|
763
|
-
|
|
764
|
-
|
|
920
|
+
response +=
|
|
921
|
+
'\n\n## Security Issues Found\n' +
|
|
922
|
+
securityIssues
|
|
923
|
+
.map(issue => '- **' +
|
|
924
|
+
issue.severity.toUpperCase() +
|
|
925
|
+
'** ' +
|
|
926
|
+
issue.type +
|
|
927
|
+
' in ' +
|
|
928
|
+
jsonSafeFilePath(issue.file) +
|
|
929
|
+
(issue.line ? ' (line ' + issue.line + ')' : '') +
|
|
930
|
+
'\n' +
|
|
931
|
+
' Fix: ' +
|
|
932
|
+
issue.recommendation)
|
|
933
|
+
.join('\n');
|
|
765
934
|
}
|
|
766
935
|
else {
|
|
767
936
|
response += '\n\n## ✅ No Security Issues Found';
|
|
768
937
|
}
|
|
769
938
|
if (irrelevantFiles.length > 0) {
|
|
770
|
-
response +=
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
'
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
'
|
|
790
|
-
'
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
'-
|
|
939
|
+
response +=
|
|
940
|
+
'\n\n## Irrelevant Files Detected\n' +
|
|
941
|
+
irrelevantFiles
|
|
942
|
+
.map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.reason + ')\n' + ' ' + f.recommendation)
|
|
943
|
+
.join('\n');
|
|
944
|
+
}
|
|
945
|
+
response +=
|
|
946
|
+
'\n\n## ⚠️ IMPORTANT: Pre-Push Staging Review\n' +
|
|
947
|
+
'**AVOID:** `git add .` or `git add -A` before this tool\n' +
|
|
948
|
+
'**RECOMMENDED:**\n' +
|
|
949
|
+
'1. Review each staged file individually\n' +
|
|
950
|
+
'2. Verify changes: `git diff --cached`\n' +
|
|
951
|
+
'3. Ensure only intended files are staged\n\n' +
|
|
952
|
+
'## Command to Execute\n' +
|
|
953
|
+
'-------\n' +
|
|
954
|
+
'# Run without dry run to actually push\n' +
|
|
955
|
+
'git push' +
|
|
956
|
+
(branch ? ' origin ' + branch : '') +
|
|
957
|
+
'\n' +
|
|
958
|
+
'-------\n\n' +
|
|
959
|
+
'**Note:** This was a dry run. No files were pushed.' +
|
|
960
|
+
(wouldBlock ? '\n⚠️ **Warning**: This push would be BLOCKED due to critical issues.' : '') +
|
|
961
|
+
'\n\n' +
|
|
962
|
+
'## 🚀 Deployment Readiness Assessment\n' +
|
|
963
|
+
(wouldBlock
|
|
964
|
+
? '❌ **NOT READY** - Fix issues above before deployment'
|
|
965
|
+
: '✅ **READY** - This push appears safe for deployment\n\n' +
|
|
966
|
+
'### Post-Push Checklist\n' +
|
|
967
|
+
'- [ ] Monitor CI/CD pipeline\n' +
|
|
968
|
+
'- [ ] Verify deployment health\n' +
|
|
969
|
+
'- [ ] Update TODO tasks\n' +
|
|
970
|
+
'- [ ] Document deployment notes');
|
|
796
971
|
return response;
|
|
797
972
|
}
|
|
798
973
|
function getDeploymentMetricsUpdate() {
|
|
799
|
-
return '- Deploy success rate updated\n' +
|
|
974
|
+
return ('- Deploy success rate updated\n' +
|
|
800
975
|
'- Test results recorded\n' +
|
|
801
|
-
'- Metrics available in .mcp-adr-cache/deploy-history.json';
|
|
976
|
+
'- Metrics available in .mcp-adr-cache/deploy-history.json');
|
|
802
977
|
}
|
|
803
978
|
/**
|
|
804
979
|
* Generate deployment readiness block response
|
|
@@ -813,33 +988,46 @@ function generateDeploymentReadinessBlockResponse(readinessResult, stagedFiles,
|
|
|
813
988
|
- **Confidence Level**: ${readinessResult.confidence || 0}%
|
|
814
989
|
|
|
815
990
|
## 🧪 Test Validation Issues
|
|
816
|
-
${readinessResult.testFailureBlockers?.length > 0
|
|
991
|
+
${readinessResult.testFailureBlockers?.length > 0
|
|
992
|
+
? `
|
|
817
993
|
**Test Failures**: ${readinessResult.testValidationResult?.failureCount || 0} failures detected
|
|
818
994
|
**Test Coverage**: ${readinessResult.testValidationResult?.coveragePercentage || 0}% (Required: 80%)
|
|
819
995
|
|
|
820
996
|
### Critical Test Failures:
|
|
821
|
-
${readinessResult.testValidationResult?.criticalTestFailures
|
|
822
|
-
|
|
997
|
+
${readinessResult.testValidationResult?.criticalTestFailures
|
|
998
|
+
?.map((f) => `- ❌ ${f.testSuite}: ${f.testName}`)
|
|
999
|
+
.join('\n') || 'No critical test failures'}
|
|
1000
|
+
`
|
|
1001
|
+
: '✅ All tests passing'}
|
|
823
1002
|
|
|
824
1003
|
## 📊 Deployment History Issues
|
|
825
|
-
${readinessResult.deploymentHistoryBlockers?.length > 0
|
|
1004
|
+
${readinessResult.deploymentHistoryBlockers?.length > 0
|
|
1005
|
+
? `
|
|
826
1006
|
**Success Rate**: ${readinessResult.deploymentHistoryAnalysis?.successRate || 0}% (Required: 80%)
|
|
827
1007
|
**Rollback Rate**: ${readinessResult.deploymentHistoryAnalysis?.rollbackRate || 0}% (Threshold: 20%)
|
|
828
1008
|
|
|
829
1009
|
### Recent Failure Patterns:
|
|
830
|
-
${readinessResult.deploymentHistoryAnalysis?.failurePatterns
|
|
831
|
-
|
|
1010
|
+
${readinessResult.deploymentHistoryAnalysis?.failurePatterns
|
|
1011
|
+
?.map((p) => `- **${p.pattern}**: ${p.frequency} occurrences`)
|
|
1012
|
+
.join('\n') || 'No failure patterns detected'}
|
|
1013
|
+
`
|
|
1014
|
+
: '✅ Deployment history stable'}
|
|
832
1015
|
|
|
833
1016
|
## 🚨 Critical Blockers (Must Fix Before Push)
|
|
834
|
-
${readinessResult.criticalBlockers
|
|
1017
|
+
${readinessResult.criticalBlockers
|
|
1018
|
+
?.map((blocker) => `
|
|
835
1019
|
### ${blocker.category.toUpperCase()}: ${blocker.title}
|
|
836
1020
|
- **Impact**: ${blocker.impact}
|
|
837
1021
|
- **Resolution Steps**: ${blocker.resolutionSteps?.join(' → ') || 'See deployment readiness tool for details'}
|
|
838
1022
|
- **Estimated Time**: ${blocker.estimatedResolutionTime || 'Unknown'}
|
|
839
|
-
`)
|
|
1023
|
+
`)
|
|
1024
|
+
.join('\n') || 'No critical blockers found'}
|
|
840
1025
|
|
|
841
1026
|
## 📁 Staged Files (${stagedFiles.length} files ready to push)
|
|
842
|
-
${stagedFiles
|
|
1027
|
+
${stagedFiles
|
|
1028
|
+
.slice(0, 10)
|
|
1029
|
+
.map(file => `- ${file.status}: ${file.path}`)
|
|
1030
|
+
.join('\n')}
|
|
843
1031
|
${stagedFiles.length > 10 ? `\n... and ${stagedFiles.length - 10} more files` : ''}
|
|
844
1032
|
|
|
845
1033
|
## 🛠️ Required Actions Before Git Push
|
|
@@ -885,10 +1073,12 @@ smart_git_push --force-unsafe
|
|
|
885
1073
|
\`\`\`
|
|
886
1074
|
|
|
887
1075
|
## 📋 Deployment Checklist Integration
|
|
888
|
-
${readinessResult.todoTasksCreated?.length > 0
|
|
1076
|
+
${readinessResult.todoTasksCreated?.length > 0
|
|
1077
|
+
? `
|
|
889
1078
|
**Auto-Generated Tasks**: ${readinessResult.todoTasksCreated.length} tasks created
|
|
890
1079
|
Use \`manage_todo_v2 --operation get_tasks\` to view blocking tasks.
|
|
891
|
-
`
|
|
1080
|
+
`
|
|
1081
|
+
: 'No automatic tasks created'}
|
|
892
1082
|
|
|
893
1083
|
**❌ GIT PUSH BLOCKED UNTIL ALL CRITICAL ISSUES ARE RESOLVED**
|
|
894
1084
|
|
|
@@ -910,11 +1100,15 @@ export async function smartGitPushMcpSafe(args) {
|
|
|
910
1100
|
}
|
|
911
1101
|
catch (error) {
|
|
912
1102
|
const errorResponse = {
|
|
913
|
-
content: [
|
|
1103
|
+
content: [
|
|
1104
|
+
{
|
|
914
1105
|
type: 'text',
|
|
915
|
-
text: '# Smart Git Push - Error\n\n**Error**: ' +
|
|
916
|
-
|
|
917
|
-
|
|
1106
|
+
text: '# Smart Git Push - Error\n\n**Error**: ' +
|
|
1107
|
+
jsonSafeError(error) +
|
|
1108
|
+
'\n\nPlease check your git configuration and try again.',
|
|
1109
|
+
},
|
|
1110
|
+
],
|
|
1111
|
+
isError: true,
|
|
918
1112
|
};
|
|
919
1113
|
return validateMcpResponse(errorResponse);
|
|
920
1114
|
}
|