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.
Files changed (263) hide show
  1. package/README.md +94 -839
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/config/ai-config.d.ts.map +1 -1
  4. package/dist/src/config/ai-config.js +9 -9
  5. package/dist/src/config/ai-config.js.map +1 -1
  6. package/dist/src/index.d.ts +15 -0
  7. package/dist/src/index.d.ts.map +1 -1
  8. package/dist/src/index.js +1594 -837
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/prompts/analysis-prompts.d.ts +4 -1
  11. package/dist/src/prompts/analysis-prompts.d.ts.map +1 -1
  12. package/dist/src/prompts/analysis-prompts.js +61 -30
  13. package/dist/src/prompts/analysis-prompts.js.map +1 -1
  14. package/dist/src/prompts/index.d.ts +17 -1
  15. package/dist/src/prompts/index.d.ts.map +1 -1
  16. package/dist/src/prompts/index.js +325 -1
  17. package/dist/src/prompts/index.js.map +1 -1
  18. package/dist/src/prompts/rule-generation-prompts.d.ts +5 -1
  19. package/dist/src/prompts/rule-generation-prompts.d.ts.map +1 -1
  20. package/dist/src/prompts/rule-generation-prompts.js +5 -1
  21. package/dist/src/prompts/rule-generation-prompts.js.map +1 -1
  22. package/dist/src/prompts/security-prompts.d.ts +6 -1
  23. package/dist/src/prompts/security-prompts.d.ts.map +1 -1
  24. package/dist/src/prompts/security-prompts.js +6 -1
  25. package/dist/src/prompts/security-prompts.js.map +1 -1
  26. package/dist/src/prompts/todo-prompts.d.ts +49 -0
  27. package/dist/src/prompts/todo-prompts.d.ts.map +1 -0
  28. package/dist/src/prompts/todo-prompts.js +824 -0
  29. package/dist/src/prompts/todo-prompts.js.map +1 -0
  30. package/dist/src/resources/index.d.ts.map +1 -1
  31. package/dist/src/resources/index.js +9 -7
  32. package/dist/src/resources/index.js.map +1 -1
  33. package/dist/src/tools/adr-bootstrap-validation-tool.d.ts +47 -0
  34. package/dist/src/tools/adr-bootstrap-validation-tool.d.ts.map +1 -0
  35. package/dist/src/tools/adr-bootstrap-validation-tool.js +979 -0
  36. package/dist/src/tools/adr-bootstrap-validation-tool.js.map +1 -0
  37. package/dist/src/tools/adr-suggestion-tool.d.ts +1 -0
  38. package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -1
  39. package/dist/src/tools/adr-suggestion-tool.js +330 -32
  40. package/dist/src/tools/adr-suggestion-tool.js.map +1 -1
  41. package/dist/src/tools/content-masking-tool.d.ts +5 -0
  42. package/dist/src/tools/content-masking-tool.d.ts.map +1 -1
  43. package/dist/src/tools/content-masking-tool.js +631 -28
  44. package/dist/src/tools/content-masking-tool.js.map +1 -1
  45. package/dist/src/tools/deployment-readiness-tool.d.ts +8 -5
  46. package/dist/src/tools/deployment-readiness-tool.d.ts.map +1 -1
  47. package/dist/src/tools/deployment-readiness-tool.js +1017 -93
  48. package/dist/src/tools/deployment-readiness-tool.js.map +1 -1
  49. package/dist/src/tools/environment-analysis-tool.d.ts +4 -0
  50. package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -1
  51. package/dist/src/tools/environment-analysis-tool.js +568 -24
  52. package/dist/src/tools/environment-analysis-tool.js.map +1 -1
  53. package/dist/src/tools/interactive-adr-planning-tool.d.ts.map +1 -1
  54. package/dist/src/tools/interactive-adr-planning-tool.js +270 -108
  55. package/dist/src/tools/interactive-adr-planning-tool.js.map +1 -1
  56. package/dist/src/tools/mcp-planning-tool.d.ts.map +1 -1
  57. package/dist/src/tools/mcp-planning-tool.js +316 -183
  58. package/dist/src/tools/mcp-planning-tool.js.map +1 -1
  59. package/dist/src/tools/memory-loading-tool.d.ts +60 -0
  60. package/dist/src/tools/memory-loading-tool.d.ts.map +1 -0
  61. package/dist/src/tools/memory-loading-tool.js +457 -0
  62. package/dist/src/tools/memory-loading-tool.js.map +1 -0
  63. package/dist/src/tools/research-integration-tool.d.ts +4 -1
  64. package/dist/src/tools/research-integration-tool.d.ts.map +1 -1
  65. package/dist/src/tools/research-integration-tool.js +5 -1
  66. package/dist/src/tools/research-integration-tool.js.map +1 -1
  67. package/dist/src/tools/review-existing-adrs-tool.d.ts +19 -0
  68. package/dist/src/tools/review-existing-adrs-tool.d.ts.map +1 -0
  69. package/dist/src/tools/review-existing-adrs-tool.js +1204 -0
  70. package/dist/src/tools/review-existing-adrs-tool.js.map +1 -0
  71. package/dist/src/tools/rule-generation-tool.d.ts +2 -0
  72. package/dist/src/tools/rule-generation-tool.d.ts.map +1 -1
  73. package/dist/src/tools/rule-generation-tool.js +274 -33
  74. package/dist/src/tools/rule-generation-tool.js.map +1 -1
  75. package/dist/src/tools/smart-git-push-tool-v2.d.ts +4 -0
  76. package/dist/src/tools/smart-git-push-tool-v2.d.ts.map +1 -1
  77. package/dist/src/tools/smart-git-push-tool-v2.js +423 -229
  78. package/dist/src/tools/smart-git-push-tool-v2.js.map +1 -1
  79. package/dist/src/tools/smart-git-push-tool.d.ts +3 -0
  80. package/dist/src/tools/smart-git-push-tool.d.ts.map +1 -1
  81. package/dist/src/tools/smart-git-push-tool.js +241 -235
  82. package/dist/src/tools/smart-git-push-tool.js.map +1 -1
  83. package/dist/src/tools/tool-chain-orchestrator.d.ts +2 -2
  84. package/dist/src/tools/tool-chain-orchestrator.d.ts.map +1 -1
  85. package/dist/src/tools/tool-chain-orchestrator.js +152 -93
  86. package/dist/src/tools/tool-chain-orchestrator.js.map +1 -1
  87. package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts +22 -13
  88. package/dist/src/tools/troubleshoot-guided-workflow-tool.d.ts.map +1 -1
  89. package/dist/src/tools/troubleshoot-guided-workflow-tool.js +660 -28
  90. package/dist/src/tools/troubleshoot-guided-workflow-tool.js.map +1 -1
  91. package/dist/src/types/ape-framework.d.ts +93 -0
  92. package/dist/src/types/ape-framework.d.ts.map +1 -1
  93. package/dist/src/types/ape-framework.js +10 -10
  94. package/dist/src/types/ape-framework.js.map +1 -1
  95. package/dist/src/types/enhanced-errors.d.ts +173 -0
  96. package/dist/src/types/enhanced-errors.d.ts.map +1 -0
  97. package/dist/src/types/enhanced-errors.js +668 -0
  98. package/dist/src/types/enhanced-errors.js.map +1 -0
  99. package/dist/src/types/index.d.ts +129 -3
  100. package/dist/src/types/index.d.ts.map +1 -1
  101. package/dist/src/types/index.js +15 -0
  102. package/dist/src/types/index.js.map +1 -1
  103. package/dist/src/types/knowledge-generation.d.ts +78 -0
  104. package/dist/src/types/knowledge-generation.d.ts.map +1 -1
  105. package/dist/src/types/knowledge-generation.js +10 -6
  106. package/dist/src/types/knowledge-generation.js.map +1 -1
  107. package/dist/src/types/knowledge-graph-schemas.d.ts +92 -0
  108. package/dist/src/types/knowledge-graph-schemas.d.ts.map +1 -1
  109. package/dist/src/types/knowledge-graph-schemas.js +45 -17
  110. package/dist/src/types/knowledge-graph-schemas.js.map +1 -1
  111. package/dist/src/types/memory-entities.d.ts +7209 -0
  112. package/dist/src/types/memory-entities.d.ts.map +1 -0
  113. package/dist/src/types/memory-entities.js +395 -0
  114. package/dist/src/types/memory-entities.js.map +1 -0
  115. package/dist/src/types/reflexion-framework.d.ts +44 -0
  116. package/dist/src/types/reflexion-framework.d.ts.map +1 -1
  117. package/dist/src/types/reflexion-framework.js +7 -7
  118. package/dist/src/types/reflexion-framework.js.map +1 -1
  119. package/dist/src/types/todo-json-schemas.d.ts +7 -653
  120. package/dist/src/types/todo-json-schemas.d.ts.map +1 -1
  121. package/dist/src/types/todo-json-schemas.js +6 -110
  122. package/dist/src/types/todo-json-schemas.js.map +1 -1
  123. package/dist/src/types/tool-arguments.d.ts +224 -0
  124. package/dist/src/types/tool-arguments.d.ts.map +1 -0
  125. package/dist/src/types/tool-arguments.js +6 -0
  126. package/dist/src/types/tool-arguments.js.map +1 -0
  127. package/dist/src/utils/actual-file-operations.d.ts.map +1 -1
  128. package/dist/src/utils/actual-file-operations.js +25 -9
  129. package/dist/src/utils/actual-file-operations.js.map +1 -1
  130. package/dist/src/utils/adr-discovery.d.ts +33 -1
  131. package/dist/src/utils/adr-discovery.d.ts.map +1 -1
  132. package/dist/src/utils/adr-discovery.js +14 -9
  133. package/dist/src/utils/adr-discovery.js.map +1 -1
  134. package/dist/src/utils/adr-suggestions.d.ts +72 -0
  135. package/dist/src/utils/adr-suggestions.d.ts.map +1 -1
  136. package/dist/src/utils/adr-suggestions.js +6 -0
  137. package/dist/src/utils/adr-suggestions.js.map +1 -1
  138. package/dist/src/utils/cache.d.ts.map +1 -1
  139. package/dist/src/utils/cache.js +22 -19
  140. package/dist/src/utils/cache.js.map +1 -1
  141. package/dist/src/utils/chain-of-thought-template.d.ts +13 -1
  142. package/dist/src/utils/chain-of-thought-template.d.ts.map +1 -1
  143. package/dist/src/utils/chain-of-thought-template.js +31 -22
  144. package/dist/src/utils/chain-of-thought-template.js.map +1 -1
  145. package/dist/src/utils/config.d.ts.map +1 -1
  146. package/dist/src/utils/config.js +1 -0
  147. package/dist/src/utils/config.js.map +1 -1
  148. package/dist/src/utils/directory-compat.js +1 -1
  149. package/dist/src/utils/directory-compat.js.map +1 -1
  150. package/dist/src/utils/enhanced-logging.d.ts +195 -0
  151. package/dist/src/utils/enhanced-logging.d.ts.map +1 -0
  152. package/dist/src/utils/enhanced-logging.js +449 -0
  153. package/dist/src/utils/enhanced-logging.js.map +1 -0
  154. package/dist/src/utils/file-system.d.ts +182 -34
  155. package/dist/src/utils/file-system.d.ts.map +1 -1
  156. package/dist/src/utils/file-system.js +648 -774
  157. package/dist/src/utils/file-system.js.map +1 -1
  158. package/dist/src/utils/gitleaks-detector.d.ts +50 -0
  159. package/dist/src/utils/gitleaks-detector.d.ts.map +1 -0
  160. package/dist/src/utils/gitleaks-detector.js +334 -0
  161. package/dist/src/utils/gitleaks-detector.js.map +1 -0
  162. package/dist/src/utils/interactive-approval.d.ts +1 -1
  163. package/dist/src/utils/interactive-approval.d.ts.map +1 -1
  164. package/dist/src/utils/interactive-approval.js +22 -17
  165. package/dist/src/utils/interactive-approval.js.map +1 -1
  166. package/dist/src/utils/json-safe.d.ts.map +1 -1
  167. package/dist/src/utils/json-safe.js +9 -6
  168. package/dist/src/utils/json-safe.js.map +1 -1
  169. package/dist/src/utils/knowledge-graph-manager.d.ts +37 -1
  170. package/dist/src/utils/knowledge-graph-manager.d.ts.map +1 -1
  171. package/dist/src/utils/knowledge-graph-manager.js +315 -70
  172. package/dist/src/utils/knowledge-graph-manager.js.map +1 -1
  173. package/dist/src/utils/location-filter.d.ts +35 -10
  174. package/dist/src/utils/location-filter.d.ts.map +1 -1
  175. package/dist/src/utils/location-filter.js +360 -94
  176. package/dist/src/utils/location-filter.js.map +1 -1
  177. package/dist/src/utils/mcp-response-validator.d.ts.map +1 -1
  178. package/dist/src/utils/mcp-response-validator.js +34 -19
  179. package/dist/src/utils/mcp-response-validator.js.map +1 -1
  180. package/dist/src/utils/memory-entity-manager.d.ts +134 -0
  181. package/dist/src/utils/memory-entity-manager.d.ts.map +1 -0
  182. package/dist/src/utils/memory-entity-manager.js +851 -0
  183. package/dist/src/utils/memory-entity-manager.js.map +1 -0
  184. package/dist/src/utils/memory-health-scoring.d.ts +125 -0
  185. package/dist/src/utils/memory-health-scoring.d.ts.map +1 -0
  186. package/dist/src/utils/memory-health-scoring.js +277 -0
  187. package/dist/src/utils/memory-health-scoring.js.map +1 -0
  188. package/dist/src/utils/memory-migration-manager.d.ts +93 -0
  189. package/dist/src/utils/memory-migration-manager.d.ts.map +1 -0
  190. package/dist/src/utils/memory-migration-manager.js +842 -0
  191. package/dist/src/utils/memory-migration-manager.js.map +1 -0
  192. package/dist/src/utils/memory-relationship-mapper.d.ts +87 -0
  193. package/dist/src/utils/memory-relationship-mapper.d.ts.map +1 -0
  194. package/dist/src/utils/memory-relationship-mapper.js +482 -0
  195. package/dist/src/utils/memory-relationship-mapper.js.map +1 -0
  196. package/dist/src/utils/memory-rollback-manager.d.ts +105 -0
  197. package/dist/src/utils/memory-rollback-manager.d.ts.map +1 -0
  198. package/dist/src/utils/memory-rollback-manager.js +575 -0
  199. package/dist/src/utils/memory-rollback-manager.js.map +1 -0
  200. package/dist/src/utils/memory-transformation.d.ts +59 -0
  201. package/dist/src/utils/memory-transformation.d.ts.map +1 -0
  202. package/dist/src/utils/memory-transformation.js +742 -0
  203. package/dist/src/utils/memory-transformation.js.map +1 -0
  204. package/dist/src/utils/output-masking.d.ts +12 -0
  205. package/dist/src/utils/output-masking.d.ts.map +1 -1
  206. package/dist/src/utils/output-masking.js +5 -0
  207. package/dist/src/utils/output-masking.js.map +1 -1
  208. package/dist/src/utils/prompt-execution.d.ts.map +1 -1
  209. package/dist/src/utils/prompt-execution.js +72 -51
  210. package/dist/src/utils/prompt-execution.js.map +1 -1
  211. package/dist/src/utils/release-readiness-detector.d.ts.map +1 -1
  212. package/dist/src/utils/release-readiness-detector.js +43 -42
  213. package/dist/src/utils/release-readiness-detector.js.map +1 -1
  214. package/dist/src/utils/research-integration.d.ts.map +1 -1
  215. package/dist/src/utils/research-integration.js +73 -44
  216. package/dist/src/utils/research-integration.js.map +1 -1
  217. package/dist/src/utils/research-questions.d.ts.map +1 -1
  218. package/dist/src/utils/research-questions.js +40 -14
  219. package/dist/src/utils/research-questions.js.map +1 -1
  220. package/dist/src/utils/ripgrep-wrapper.d.ts +84 -0
  221. package/dist/src/utils/ripgrep-wrapper.d.ts.map +1 -0
  222. package/dist/src/utils/ripgrep-wrapper.js +255 -0
  223. package/dist/src/utils/ripgrep-wrapper.js.map +1 -0
  224. package/dist/src/utils/rule-generation.d.ts.map +1 -1
  225. package/dist/src/utils/rule-generation.js +26 -15
  226. package/dist/src/utils/rule-generation.js.map +1 -1
  227. package/dist/src/utils/todo-file-watcher.d.ts +11 -23
  228. package/dist/src/utils/todo-file-watcher.d.ts.map +1 -1
  229. package/dist/src/utils/todo-file-watcher.js +18 -156
  230. package/dist/src/utils/todo-file-watcher.js.map +1 -1
  231. package/dist/src/utils/tree-sitter-analyzer.d.ts +185 -0
  232. package/dist/src/utils/tree-sitter-analyzer.d.ts.map +1 -0
  233. package/dist/src/utils/tree-sitter-analyzer.js +885 -0
  234. package/dist/src/utils/tree-sitter-analyzer.js.map +1 -0
  235. package/package.json +51 -10
  236. package/dist/src/tools/smart-score-tool.d.ts +0 -173
  237. package/dist/src/tools/smart-score-tool.d.ts.map +0 -1
  238. package/dist/src/tools/smart-score-tool.js +0 -681
  239. package/dist/src/tools/smart-score-tool.js.map +0 -1
  240. package/dist/src/tools/todo-management-tool-v2.d.ts +0 -368
  241. package/dist/src/tools/todo-management-tool-v2.d.ts.map +0 -1
  242. package/dist/src/tools/todo-management-tool-v2.js +0 -922
  243. package/dist/src/tools/todo-management-tool-v2.js.map +0 -1
  244. package/dist/src/utils/enhanced-sensitive-detector.d.ts +0 -61
  245. package/dist/src/utils/enhanced-sensitive-detector.d.ts.map +0 -1
  246. package/dist/src/utils/enhanced-sensitive-detector.js +0 -437
  247. package/dist/src/utils/enhanced-sensitive-detector.js.map +0 -1
  248. package/dist/src/utils/project-health-scoring.d.ts +0 -177
  249. package/dist/src/utils/project-health-scoring.d.ts.map +0 -1
  250. package/dist/src/utils/project-health-scoring.js +0 -370
  251. package/dist/src/utils/project-health-scoring.js.map +0 -1
  252. package/dist/src/utils/todo-json-manager.d.ts +0 -71
  253. package/dist/src/utils/todo-json-manager.d.ts.map +0 -1
  254. package/dist/src/utils/todo-json-manager.js +0 -396
  255. package/dist/src/utils/todo-json-manager.js.map +0 -1
  256. package/dist/src/utils/todo-markdown-converter.d.ts +0 -16
  257. package/dist/src/utils/todo-markdown-converter.d.ts.map +0 -1
  258. package/dist/src/utils/todo-markdown-converter.js +0 -362
  259. package/dist/src/utils/todo-markdown-converter.js.map +0 -1
  260. package/dist/src/utils/todo-migration.d.ts +0 -47
  261. package/dist/src/utils/todo-migration.d.ts.map +0 -1
  262. package/dist/src/utils/todo-migration.js +0 -261
  263. 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 && (enforceDeploymentReadiness || strictDeploymentMode)) {
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 && checkDeploymentReadiness && !enforceDeploymentReadiness) {
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 (err) {
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/enhanced-sensitive-detector.js');
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' ? 'critical' :
207
- match.pattern.severity === 'high' ? 'high' : 'medium';
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 cacheDir = join(projectPath, '.mcp-adr-cache');
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 (error) {
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 ? (currentAvg * (totalRuns - 1) + result.testResults.duration) / totalRuns : result.testResults.duration;
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 = totalDeploys > 0 ?
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 = totalTests > 0 ?
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 historyFile = join(projectPath, '.mcp-adr-cache', 'deploy-history.json');
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**: ' + history.successRate + '% (' + history.successful + '/' + (history.successful + history.failed) + ')',
354
- '- **Test Pass Rate**: ' + history.testPassRate + '% (' + history.testResults.totalTestsPassed + '/' + (history.testResults.totalTestsPassed + history.testResults.totalTestsFailed) + ')',
355
- '- **Last Deploy**: ' + (history.lastDeploy ? new Date(history.lastDeploy).toLocaleString() : 'Never') + ' ' + (history.lastDeploySuccess ? '✅' : '❌'),
356
- '- **Last Test Run**: ' + (history.testResults.lastRun ? new Date(history.testResults.lastRun).toLocaleString() : 'Never') + ' ' + (history.testResults.lastRunSuccess ? '✅' : '❌'),
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**: ' + (history.testResults.averageDuration ? Math.round(history.testResults.averageDuration) + 's' : 'N/A')
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 (error) {
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': return 'added';
396
- case 'M': return 'modified';
397
- case 'D': return 'deleted';
398
- case 'R': return 'renamed';
399
- default: return 'modified';
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', '.ts', '.jsx', '.tsx', '.json', '.md', '.txt', '.yml', '.yaml',
405
- '.py', '.rb', '.java', '.cs', '.go', '.rs', '.cpp', '.c', '.h', '.hpp',
406
- '.php', '.html', '.css', '.scss', '.sass', '.less', '.vue', '.svelte'
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': return 'Add to .gitignore - temporary files should not be committed';
435
- case 'build-artifact': return 'Add to .gitignore - build outputs should not be in source control';
436
- case 'ide-config': return 'Add to .gitignore - IDE configurations are user-specific';
437
- case 'log-file': return 'Add to .gitignore - log files should not be committed';
438
- case 'cache-file': return 'Add to .gitignore - cache files are generated';
439
- default: return 'Consider adding to .gitignore';
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') || fileName.endsWith('.config.js') || fileName.endsWith('.config.ts')) {
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') || fileName.includes('.idea') || fileName.includes('.settings')) {
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') || fileName.includes('node_modules') || 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 + '\n\n' +
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
- request.riskLevel === 'high' ? '🟠' :
615
- request.riskLevel === 'medium' ? '🟡' : '🟢';
616
- response += `### ${index + 1}. ${jsonSafeFilePath(request.path)} ${riskEmoji}\n\n` +
617
- `**Detected Issue**: ${isSecurityIssue ? 'Security Risk' : 'Irrelevant File'}\n` +
618
- `**Risk Level**: ${request.riskLevel.toUpperCase()}\n` +
619
- `**LLM Analysis**: ${request.suggestedPurpose}\n\n` +
620
- `**Recommended Alternatives**:\n${request.alternatives.map(alt => `- ${alt}`).join('\n')}\n\n` +
621
- `**To Override**: Confirm this file's purpose and business justification.\n\n`;
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 += '## Override Instructions\n\n' +
624
- 'To proceed with these files, rerun the command with human overrides:\n\n' +
625
- '```json\n' +
626
- '{\n' +
627
- ' "operation": "smart_git_push",\n' +
628
- ' "humanOverrides": [\n' +
629
- confirmationRequests.map(req => ' {\n' +
630
- ` "path": "${req.path}",\n` +
631
- ` "purpose": "YOUR_BUSINESS_JUSTIFICATION_HERE",\n` +
632
- ' "userConfirmed": true,\n' +
633
- ` "timestamp": "${new Date().toISOString()}",\n` +
634
- ' "overrideReason": "business-requirement", // or security-exception, deployment-necessity, etc.\n' +
635
- ' "additionalContext": "EXPLAIN_WHY_THIS_IS_NECESSARY"\n' +
636
- ' }').join(',\n') + '\n' +
637
- ' ]\n' +
638
- '}\n' +
639
- '```\n\n' +
640
- '## ⚠️ Important Reminders\n' +
641
- '- **Only override if you understand the business need**\n' +
642
- '- **Document the purpose clearly**\n' +
643
- '- **Consider the security implications**\n' +
644
- '- **Review alternatives before overriding**\n\n' +
645
- `**Total staged files**: ${stagedFiles.length} | **Files needing confirmation**: ${confirmationRequests.length}`;
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.filter(i => i.severity === 'critical').map(issue => '- **' + issue.type + '** in ' + jsonSafeFilePath(issue.file) + (issue.line ? ' (line ' + issue.line + ')' : '') + '\n' +
652
- ' Pattern: ' + issue.pattern + '\n' +
653
- ' Fix: ' + issue.recommendation).join('\n\n');
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 += '### 🧪 Tests Failed\n' +
658
- '- **Command**: ' + testResults.command + '\n' +
659
- '- **Output**:\n' +
660
- '-------\n' +
661
- jsonSafeUserInput(testResults.output) + '\n' +
662
- '-------\n\n';
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 += `- **${jsonSafeFilePath(override.path)}**: ${override.purpose}\n` +
669
- ` Reason: ${override.overrideReason} | Confirmed: ${override.userConfirmed ? '✅' : '❌'}\n`;
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 += '## Required Actions\n' +
674
- '1. Fix all critical security issues\n' +
675
- '2. Ensure all tests pass\n' +
676
- '3. Review and fix any warnings\n' +
677
- '4. OR use human overrides with proper justification\n\n' +
678
- '## ⚠️ IMPORTANT: File Staging Best Practices\n' +
679
- '**NEVER USE:** `git add .` or `git add -A` when fixing issues\n' +
680
- '**RECOMMENDED:**\n' +
681
- '1. Fix specific issues in specific files\n' +
682
- '2. Stage only the fixed files: `git add <fixed-file>`\n' +
683
- '3. Verify changes: `git diff --cached`\n' +
684
- '4. Re-run smart git push\n\n' +
685
- '## Human Override Option\n' +
686
- 'If these issues are expected and have business justification:\n' +
687
- '1. Use `requestHumanConfirmation: true` to get guided override instructions\n' +
688
- '2. Provide detailed justification for each file\n' +
689
- '3. Consider security implications carefully\n\n' +
690
- '🚫 Use --forceUnsafe to override (NOT RECOMMENDED)';
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**: ' + (branch || 'current') + '\n' +
697
- '- **Files**: ' + stagedFiles.length + ' staged files\n' +
698
- '- **Security Issues**: ' + securityIssues.length + ' (' + securityIssues.filter(i => i.severity === 'critical').length + ' critical)\n' +
699
- '- **Irrelevant Files**: ' + irrelevantFiles.length + '\n' +
700
- '- **Tests**: ' + (testResults ? (testResults.success ? '✅ Passed' : '❌ Failed') : 'Skipped') + '\n\n' +
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() + '\n\n' +
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 += '\n\n## Security Warnings (Non-Critical)\n' +
709
- nonCriticalIssues.map(issue => '- **' + issue.type + '** in ' + jsonSafeFilePath(issue.file) + ': ' + issue.recommendation).join('\n');
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 += '\n\n## Irrelevant Files (Consider .gitignore)\n' +
714
- irrelevantFiles.map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.reason + '): ' + f.recommendation).join('\n');
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 += '\n\n## ✅ Human Overrides Applied\n' +
719
- 'The following files were explicitly approved by human override:\n' +
720
- humanOverrides.filter(o => o.userConfirmed).map(override => `- **${jsonSafeFilePath(override.path)}**: ${override.purpose}\n` +
721
- ` Justification: ${override.additionalContext || 'No additional context'}\n` +
722
- ` Override Reason: ${override.overrideReason}\n` +
723
- ` Timestamp: ${new Date(override.timestamp).toLocaleString()}`).join('\n\n') + '\n\n' +
724
- '📝 **Note**: These overrides have been logged for audit purposes.';
725
- }
726
- response += '\n\n## Git Output\n' +
727
- '-------\n' +
728
- jsonSafeUserInput(pushResult.output) + '\n' +
729
- '-------\n\n' +
730
- '## 🚀 Post-Push Deployment Checklist\n' +
731
- '### Immediate Actions (Next 5 minutes)\n' +
732
- '- [ ] Monitor CI/CD pipeline status\n' +
733
- '- [ ] Check automated test results\n' +
734
- '- [ ] Verify build completion\n' +
735
- '- [ ] Review any deployment warnings\n\n' +
736
- '### Deployment Completion (Next 15 minutes)\n' +
737
- '- [ ] Confirm deployment to staging/production\n' +
738
- '- [ ] Verify application health checks\n' +
739
- '- [ ] Test key functionality post-deployment\n' +
740
- '- [ ] Monitor error rates and performance metrics\n' +
741
- '- [ ] Update TODO list with deployment status\n\n' +
742
- '### Documentation & Communication\n' +
743
- '- [ ] Update deployment notes\n' +
744
- '- [ ] Notify team of successful deployment\n' +
745
- '- [ ] Close related tickets/issues\n' +
746
- '- [ ] Schedule post-deployment review if needed\n\n' +
747
- '💡 **Tip**: Use the TODO management tool to track deployment completion tasks!';
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**: ' + stagedFiles.length + '\n' +
756
- '- **Security Issues**: ' + securityIssues.length + ' (' + securityIssues.filter(i => i.severity === 'critical').length + ' critical)\n' +
757
- '- **Irrelevant Files**: ' + irrelevantFiles.length + '\n' +
758
- '- **Would Block**: ' + (wouldBlock ? '❌ Yes' : '✅ No') + '\n\n' +
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.map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.status + ') - ' + f.size + ' bytes').join('\n');
916
+ stagedFiles
917
+ .map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.status + ') - ' + f.size + ' bytes')
918
+ .join('\n');
761
919
  if (securityIssues.length > 0) {
762
- response += '\n\n## Security Issues Found\n' +
763
- securityIssues.map(issue => '- **' + issue.severity.toUpperCase() + '** ' + issue.type + ' in ' + jsonSafeFilePath(issue.file) + (issue.line ? ' (line ' + issue.line + ')' : '') + '\n' +
764
- ' Fix: ' + issue.recommendation).join('\n');
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 += '\n\n## Irrelevant Files Detected\n' +
771
- irrelevantFiles.map(f => '- ' + jsonSafeFilePath(f.path) + ' (' + f.reason + ')\n' +
772
- ' ' + f.recommendation).join('\n');
773
- }
774
- response += '\n\n## ⚠️ IMPORTANT: Pre-Push Staging Review\n' +
775
- '**AVOID:** `git add .` or `git add -A` before this tool\n' +
776
- '**RECOMMENDED:**\n' +
777
- '1. Review each staged file individually\n' +
778
- '2. Verify changes: `git diff --cached`\n' +
779
- '3. Ensure only intended files are staged\n\n' +
780
- '## Command to Execute\n' +
781
- '-------\n' +
782
- '# Run without dry run to actually push\n' +
783
- 'git push' + (branch ? ' origin ' + branch : '') + '\n' +
784
- '-------\n\n' +
785
- '**Note:** This was a dry run. No files were pushed.' +
786
- (wouldBlock ? '\n⚠️ **Warning**: This push would be BLOCKED due to critical issues.' : '') + '\n\n' +
787
- '## 🚀 Deployment Readiness Assessment\n' +
788
- (wouldBlock ?
789
- '❌ **NOT READY** - Fix issues above before deployment' :
790
- '✅ **READY** - This push appears safe for deployment\n\n' +
791
- '### Post-Push Checklist\n' +
792
- '- [ ] Monitor CI/CD pipeline\n' +
793
- '- [ ] Verify deployment health\n' +
794
- '- [ ] Update TODO tasks\n' +
795
- '- [ ] Document deployment notes');
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?.map((f) => `- ❌ ${f.testSuite}: ${f.testName}`).join('\n') || 'No critical test failures'}
822
- ` : '✅ All tests passing'}
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?.map((p) => `- **${p.pattern}**: ${p.frequency} occurrences`).join('\n') || 'No failure patterns detected'}
831
- ` : '✅ Deployment history stable'}
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?.map((blocker) => `
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
- `).join('\n') || 'No critical blockers found'}
1023
+ `)
1024
+ .join('\n') || 'No critical blockers found'}
840
1025
 
841
1026
  ## 📁 Staged Files (${stagedFiles.length} files ready to push)
842
- ${stagedFiles.slice(0, 10).map(file => `- ${file.status}: ${file.path}`).join('\n')}
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
- ` : 'No automatic tasks created'}
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**: ' + jsonSafeError(error) + '\n\nPlease check your git configuration and try again.'
916
- }],
917
- isError: true
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
  }