smart_git_push
Automate secure git pushes with AI-driven credential detection, file filtering, and deployment tracking. Execute AI-run tests to validate changes and ensure compliance before deployment.
Instructions
AI-driven security-focused git push with credential detection, file filtering, and deployment metrics tracking. Tests should be run by calling AI and results provided.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| branch | No | Target branch for push (optional, uses current branch if not specified) | |
| dryRun | No | Show what would be pushed without actually pushing | |
| forceUnsafe | No | Override security blocks and test failures (DANGEROUS) | |
| message | No | Commit message (optional, commits staged files if provided) | |
| projectPath | No | Path to project directory (defaults to current working directory) | |
| skipSecurity | No | Skip security scanning (NOT RECOMMENDED) | |
| testResults | No | Test results from AI-executed tests (required for proper deployment tracking) |
Input Schema (JSON Schema)
{
"properties": {
"branch": {
"description": "Target branch for push (optional, uses current branch if not specified)",
"type": "string"
},
"dryRun": {
"default": false,
"description": "Show what would be pushed without actually pushing",
"type": "boolean"
},
"forceUnsafe": {
"default": false,
"description": "Override security blocks and test failures (DANGEROUS)",
"type": "boolean"
},
"message": {
"description": "Commit message (optional, commits staged files if provided)",
"type": "string"
},
"projectPath": {
"description": "Path to project directory (defaults to current working directory)",
"type": "string"
},
"skipSecurity": {
"default": false,
"description": "Skip security scanning (NOT RECOMMENDED)",
"type": "boolean"
},
"testResults": {
"description": "Test results from AI-executed tests (required for proper deployment tracking)",
"properties": {
"command": {
"description": "Test command that was executed by AI",
"type": "string"
},
"duration": {
"description": "Test execution duration in seconds",
"type": "number"
},
"failureDetails": {
"description": "Details of test failures",
"items": {
"type": "string"
},
"type": "array"
},
"output": {
"description": "Test execution output",
"type": "string"
},
"success": {
"description": "Whether all tests passed",
"type": "boolean"
},
"testTypes": {
"additionalProperties": {
"properties": {
"failed": {
"type": "number"
},
"passed": {
"type": "number"
}
},
"type": "object"
},
"description": "Results broken down by test type (unit, integration, etc.)",
"type": "object"
},
"testsFailed": {
"description": "Number of tests that failed",
"type": "number"
},
"testsPassed": {
"description": "Number of tests that passed",
"type": "number"
},
"testsRun": {
"description": "Total number of tests executed",
"type": "number"
}
},
"required": [
"success",
"testsRun",
"testsPassed",
"testsFailed"
],
"type": "object"
}
},
"type": "object"
}
Implementation Reference
- Input schema defining parameters for the smart_git_push tool, including branch, message, security options, deployment readiness checks, and human overrides.interface SmartGitPushArgs { branch?: string; message?: string; testResults?: TestResults; skipSecurity?: boolean; dryRun?: boolean; projectPath?: string; forceUnsafe?: boolean; humanOverrides?: HumanOverride[]; requestHumanConfirmation?: boolean; // Deployment Readiness Integration checkDeploymentReadiness?: boolean; targetEnvironment?: 'staging' | 'production' | 'integration'; enforceDeploymentReadiness?: boolean; strictDeploymentMode?: boolean; }
- Core handler function implementing the smart_git_push tool logic: scans staged files for security issues, checks deployment readiness, applies human overrides, executes git push if safe.export async function smartGitPushV2(args: SmartGitPushArgs): Promise<any> { 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; try { // Step 1: Get staged files const stagedFiles = await getStagedFiles(projectPath); if (stagedFiles.length === 0) { const metricsText = await getDeploymentMetricsSummary(projectPath); return { content: [ { type: 'text', text: createNoChangesResponse(metricsText), }, ], }; } // Step 2: Security scan (unless skipped) let securityIssues: SecurityIssue[] = []; if (!skipSecurity) { securityIssues = await scanForSecurityIssues(stagedFiles, projectPath); } // Step 3: Check for irrelevant files const irrelevantFiles = await checkIrrelevantFiles(stagedFiles); // Step 4: Apply human overrides to security issues and irrelevant files const { filteredSecurityIssues, filteredIrrelevantFiles, confirmationRequests } = await applyHumanOverrides( securityIssues, irrelevantFiles, humanOverrides, requestHumanConfirmation ); // Step 5: Check for confirmation requests if (confirmationRequests.length > 0 && requestHumanConfirmation) { return { content: [ { type: 'text', text: generateConfirmationRequestResponse(confirmationRequests, stagedFiles), }, ], }; } // Step 5.5: Deployment Readiness Check (NEW) if (checkDeploymentReadiness || enforceDeploymentReadiness) { const { deploymentReadiness } = await import('./deployment-readiness-tool.js'); const readinessCheck = await deploymentReadiness({ operation: 'full_audit', projectPath, targetEnvironment, strictMode: strictDeploymentMode, // Test Gates - Zero tolerance for failures maxTestFailures: 0, requireTestCoverage: 80, blockOnFailingTests: true, // Deployment History Gates maxRecentFailures: 2, deploymentSuccessThreshold: 80, blockOnRecentFailures: true, rollbackFrequencyThreshold: 20, // Integration with existing systems integrateTodoTasks: true, updateHealthScoring: true, }); // Hard block if deployment is not ready and enforcement is enabled if ( !readinessCheck.isDeploymentReady && (enforceDeploymentReadiness || strictDeploymentMode) ) { return { content: [ { type: 'text', text: generateDeploymentReadinessBlockResponse( readinessCheck, stagedFiles, targetEnvironment ), }, ], }; } // Soft warning if just checking but not enforcing if ( !readinessCheck.isDeploymentReady && checkDeploymentReadiness && !enforceDeploymentReadiness ) { // Continue with push but include warning in success response } } // Step 6: Check blocking conditions (after overrides) const hasCriticalSecurity = filteredSecurityIssues.some(issue => issue.severity === 'critical'); const hasFailedTests = testResults && !testResults.success; const shouldBlock = (hasCriticalSecurity || hasFailedTests) && !forceUnsafe; if (shouldBlock) { return { content: [ { type: 'text', text: generateBlockedResponse( filteredSecurityIssues, filteredIrrelevantFiles, testResults, humanOverrides ), }, ], }; } // Step 5: Execute push if not dry run if (!dryRun) { const pushResult = await executePush(projectPath, branch, message); // Update deployment history await updateDeploymentHistory(projectPath, { success: true, ...(testResults && { testResults }), filesChanged: stagedFiles.length, }); return { content: [ { type: 'text', text: generateSuccessResponse( stagedFiles, filteredSecurityIssues, filteredIrrelevantFiles, testResults, pushResult, branch, humanOverrides ), }, ], }; } else { // Dry run response return { content: [ { type: 'text', text: generateDryRunResponse( stagedFiles, filteredSecurityIssues, filteredIrrelevantFiles, testResults, branch ), }, ], }; } } catch (error) { // Update deployment history with failure await updateDeploymentHistory(projectPath, { success: false, testResults: testResults || { success: false, testsRun: 0, testsPassed: 0, testsFailed: 0 }, filesChanged: 0, }); throw new McpAdrError('Smart git push failed: ' + jsonSafeError(error), 'GIT_PUSH_ERROR'); } }
- Exported handler wrapper for smart_git_push that calls the v2 implementation and validates MCP response.export async function smartGitPush(args: SmartGitPushArgs): Promise<any> { const result = await smartGitPushV2(args); return validateMcpResponse(result); }
- src/tools/smart-git-push-tool.ts:126-614 (handler)Alternative handler in original smart-git-push-tool.ts with knowledge graph integration (likely legacy version).async function _smartGitPushInternal(args: SmartGitPushArgs): Promise<any> { const { branch, message, skipValidation = false, allowedArtifacts = [], sensitivityLevel = 'moderate', dryRun = false, projectPath = process.cwd(), checkReleaseReadiness = false, releaseType = 'minor', skipKnowledgeGraphAnalysis = false, } = args; try { // Step 1: Get staged files using git CLI const stagedFiles = await getStagedFiles(projectPath); // Step 2: Perform Knowledge Graph Analysis (NEW - this is the smart part!) let kgAnalysis: KnowledgeGraphAnalysis | null = null; if (!skipKnowledgeGraphAnalysis) { try { kgAnalysis = await analyzeKnowledgeGraphContext(projectPath, stagedFiles); } catch (kgError) { // Knowledge graph analysis failed, continue with warning console.error('Knowledge graph analysis failed:', kgError); } } // Step 3: Check release readiness if requested (enhanced with KG data) let releaseReadinessResult = null; if (checkReleaseReadiness) { try { const { analyzeReleaseReadiness } = await import('../utils/release-readiness-detector.js'); releaseReadinessResult = await analyzeReleaseReadiness({ projectPath, releaseType, includeAnalysis: true, }); // Update deployment readiness score in health scoring system try { // ProjectHealthScoring removed - skip health scoring console.warn( '⚠️ ProjectHealthScoring is deprecated and was removed in memory-centric transformation' ); // Skip health scoring update - ProjectHealthScoring removed } catch { // Silently handle health scoring errors } } catch { // Silently handle release readiness analysis errors } } if (stagedFiles.length === 0) { let responseText = `# Smart Git Push - No Changes ## Status No staged files found. Use \`git add\` to stage files before pushing. ## Available Commands - \`git add .\` - Stage all changes - \`git add <file>\` - Stage specific file - \`git status\` - Check current status `; // Add knowledge graph context even when no files are staged if (kgAnalysis) { responseText += ` ## Knowledge Graph Context ### Current Project Status - **Active Intents**: ${kgAnalysis.activeIntents.length} - **Goal Progress**: ${kgAnalysis.projectGoalProgress.overallProgress}% - **Task Dependencies**: ${kgAnalysis.taskDependencies.completed.length} completed, ${kgAnalysis.taskDependencies.pending.length} pending ${ kgAnalysis.activeIntents.length > 0 ? ` ### Active Intents ${kgAnalysis.activeIntents.map(intent => `- **${intent.currentStatus}**: ${jsonSafeUserInput(intent.humanRequest.substring(0, 80))}...`).join('\n')} ` : '' } ${ kgAnalysis.taskDependencies.pending.length > 0 ? ` ### Pending Tasks Consider working on these tasks before your next push: ${kgAnalysis.taskDependencies.pending .slice(0, 5) .map(task => `- ${jsonSafeUserInput(task)}`) .join('\n')} ` : '' } `; } // Add release readiness info if checked if (releaseReadinessResult) { responseText += ` ## Release Readiness Analysis ${jsonSafeUserInput(releaseReadinessResult.summary)} ### Recommendations ${jsonSafeMarkdownList(releaseReadinessResult.recommendations)} ${ releaseReadinessResult.isReady ? '✅ **Project is ready for release!** Consider creating a release after staging files.' : '❌ **Project is not ready for release.** Address blockers before proceeding.' } `; } return { content: [ { type: 'text', text: responseText, }, ], }; } // Step 3: Analyze staged files if validation is enabled let validationResults: ValidationResult[] = []; if (!skipValidation) { validationResults = await validateStagedFiles(stagedFiles, { sensitivityLevel, allowedArtifacts, projectPath, }); } // Step 4: Check for blocking conditions (Enhanced with Knowledge Graph) const issues = validationResults.filter(r => r.issues.length > 0); // Check if release readiness should block push let releaseReadinessBlocked = false; if (releaseReadinessResult && !releaseReadinessResult.isReady) { const criticalBlockers = releaseReadinessResult.blockers.filter(b => b.severity === 'error'); if (criticalBlockers.length > 0) { releaseReadinessBlocked = true; } } // Check Knowledge Graph for blocking conditions (NEW!) let knowledgeGraphBlocked = false; const kgBlockingConditions = kgAnalysis?.blockingConditions?.filter(bc => bc.severity === 'error') || []; if (kgBlockingConditions.length > 0) { knowledgeGraphBlocked = true; } // Check for blocking conditions const hasBlockingErrors = issues.some(issue => issue.issues.some(i => i.severity === 'error')); const shouldBlock = hasBlockingErrors || releaseReadinessBlocked || knowledgeGraphBlocked; if (shouldBlock && !dryRun) { let cancelText = `# Smart Git Push - Blocked ## Validation Issues Push blocked due to critical issues that must be resolved. ## Issues Found ${issues .map( issue => ` ### ${jsonSafeFilePath(issue.file)} ${issue.issues.map(i => `- **${i.severity.toUpperCase()}**: ${jsonSafeUserInput(i.message)}`).join('\n')} **Suggestions:** ${jsonSafeMarkdownList(issue.suggestions)} ` ) .join('\n')} `; // Add release readiness info if checked and blocked if (releaseReadinessResult && releaseReadinessBlocked) { cancelText += ` ## Release Readiness Issues ${jsonSafeUserInput(releaseReadinessResult.summary)} ### Critical Blockers ${releaseReadinessResult.blockers .filter(b => b.severity === 'error') .map(b => `- **${b.type}**: ${jsonSafeUserInput(b.message)}`) .join('\n')} ### Recommendations ${jsonSafeMarkdownList(releaseReadinessResult.recommendations)} `; } // Add knowledge graph blocking information (NEW!) if (kgAnalysis && knowledgeGraphBlocked) { cancelText += ` ## Knowledge Graph Analysis - Blocking Conditions The following architectural and project context issues prevent this push: ### Critical Issues ${kgBlockingConditions.map(bc => `- **${bc.type}**: ${jsonSafeUserInput(bc.message)}`).join('\n')} ### Recommendations ${kgBlockingConditions.map(bc => `- ${jsonSafeUserInput(bc.recommendation)}`).join('\n')} ### Project Context - **Active Intents**: ${kgAnalysis.activeIntents.length} - **Architectural Alignment**: ${kgAnalysis.architecturalAlignment.score}% - **Goal Progress**: ${kgAnalysis.projectGoalProgress.overallProgress}% - **Pending Critical Tasks**: ${kgAnalysis.taskDependencies.blocking.length} `; } // Add general knowledge graph insights if available if (kgAnalysis && !knowledgeGraphBlocked) { cancelText += ` ## Knowledge Graph Insights ### Project Status - **Active Intents**: ${kgAnalysis.activeIntents.length} - **Architectural Alignment**: ${kgAnalysis.architecturalAlignment.score}% - **Goal Progress**: ${kgAnalysis.projectGoalProgress.overallProgress}% ### Warnings ${kgAnalysis.blockingConditions .filter(bc => bc.severity === 'warning') .map(bc => `- **${bc.type}**: ${jsonSafeUserInput(bc.message)}`) .join('\n')} `; } return { content: [ { type: 'text', text: cancelText, }, ], }; } // Step 5: Execute git push if not dry run if (!dryRun) { const pushResult = await executePush(projectPath, branch, message); // Update TODO tasks with KG integration if (kgAnalysis) { try { // TodoJsonManager removed - skipping todo validation console.warn( '⚠️ TodoJsonManager is deprecated and was removed in memory-centric transformation' ); // Skip todo task update - TodoJsonManager removed } catch (todoError) { console.error('Error updating TODO tasks with KG:', todoError); } } const successText = `# Smart Git Push - Success ✅ ## Push Details - **Branch**: ${branch || 'current'} - **Files**: ${stagedFiles.length} staged files - **Validation**: ${skipValidation ? 'Skipped' : 'Completed'} - **Issues Found**: ${issues.length} - **Sensitivity Level**: ${sensitivityLevel} ${checkReleaseReadiness ? `- **Release Readiness**: ${releaseReadinessResult?.isReady ? '✅ Ready' : '❌ Not Ready'}` : ''} ${kgAnalysis ? `- **Knowledge Graph Analysis**: ✅ Completed` : ''} ## Files Pushed ${stagedFiles.map(f => `- ${jsonSafeFilePath(f.path)} (${f.status})`).join('\n')} ${ kgAnalysis ? ` ## Knowledge Graph Analysis ### Project Context - **Active Intents**: ${kgAnalysis.activeIntents.length} - **Architectural Alignment**: ${kgAnalysis.architecturalAlignment.score}% - **Goal Progress**: ${kgAnalysis.projectGoalProgress.overallProgress}% - **Task Dependencies**: ${kgAnalysis.taskDependencies.completed.length} completed, ${kgAnalysis.taskDependencies.pending.length} pending ### Architectural Insights ${kgAnalysis.architecturalAlignment.details.map(detail => `- ${jsonSafeUserInput(detail)}`).join('\n')} ${ kgAnalysis.blockingConditions.length > 0 ? ` ### Warnings & Recommendations ${kgAnalysis.blockingConditions .filter(bc => bc.severity === 'warning') .map(bc => `- **${bc.type}**: ${jsonSafeUserInput(bc.message)}`) .join('\n')} ` : '' } ${ kgAnalysis.projectGoalProgress.intentProgress.length > 0 ? ` ### Intent Progress ${kgAnalysis.projectGoalProgress.intentProgress.map(intent => `- **${intent.status}**: ${jsonSafeUserInput(intent.humanRequest.substring(0, 60))}... (${intent.progress}%)`).join('\n')} ` : '' } ` : '' } ${ issues.length > 0 ? ` ## Validation Issues (Auto-Approved) ${issues .map( issue => ` ### ${jsonSafeFilePath(issue.file)} ${issue.issues.map(i => `- **${i.severity.toUpperCase()}**: ${jsonSafeUserInput(i.message)}`).join('\n')} ` ) .join('\n')} ` : '' } ${ releaseReadinessResult ? ` ## Release Readiness Analysis ${jsonSafeUserInput(releaseReadinessResult.summary)} ### Post-Push Recommendations ${jsonSafeMarkdownList(releaseReadinessResult.recommendations)} ${ releaseReadinessResult.isReady ? '🎉 **Congratulations!** This push completed a release-ready state. Consider creating a release tag.' : '📋 **Next Steps**: Address remaining blockers to achieve release readiness.' } ` : '' } ## Git Output \`\`\` ${jsonSafeUserInput(pushResult.output)} \`\`\` ## Next Steps - Monitor CI/CD pipeline for build status - Review any deployment processes - Check for any post-push hooks or workflows ${releaseReadinessResult?.isReady ? '- Consider creating a release tag or publishing' : ''} ${kgAnalysis ? '- Review knowledge graph insights for follow-up tasks' : ''} `; return { content: [ { type: 'text', text: successText, }, ], }; } else { // Dry run - show what would happen const dryRunText = `# Smart Git Push - Dry Run 🔍 ## Analysis Complete - **Files to Push**: ${stagedFiles.length} - **Validation Issues**: ${issues.length} - **Sensitivity Level**: ${sensitivityLevel} - **Would Push to**: ${branch || 'current branch'} ${checkReleaseReadiness ? `- **Release Readiness**: ${releaseReadinessResult?.isReady ? '✅ Ready' : '❌ Not Ready'}` : ''} ${kgAnalysis ? `- **Knowledge Graph Analysis**: ✅ Completed` : ''} ## Staged Files ${stagedFiles.map(f => `- ${jsonSafeFilePath(f.path)} (${f.status}) - ${f.size} bytes`).join('\n')} ${ kgAnalysis ? ` ## Knowledge Graph Analysis Preview ### Project Context - **Active Intents**: ${kgAnalysis.activeIntents.length} - **Architectural Alignment**: ${kgAnalysis.architecturalAlignment.score}% - **Goal Progress**: ${kgAnalysis.projectGoalProgress.overallProgress}% - **Task Dependencies**: ${kgAnalysis.taskDependencies.completed.length} completed, ${kgAnalysis.taskDependencies.pending.length} pending ### Architectural Assessment ${kgAnalysis.architecturalAlignment.details.map(detail => `- ${jsonSafeUserInput(detail)}`).join('\n')} ${ kgAnalysis.blockingConditions.length > 0 ? ` ### Potential Issues ${kgAnalysis.blockingConditions.map(bc => `- **${bc.type}** (${bc.severity}): ${jsonSafeUserInput(bc.message)}`).join('\n')} ` : '' } ${ kgAnalysis.projectGoalProgress.intentProgress.length > 0 ? ` ### Intent Progress Impact ${kgAnalysis.projectGoalProgress.intentProgress.map(intent => `- **${intent.status}**: ${jsonSafeUserInput(intent.humanRequest.substring(0, 60))}... (${intent.progress}%)`).join('\n')} ` : '' } ` : '' } ${ issues.length > 0 ? ` ## Validation Issues Found ${issues .map( issue => ` ### ${jsonSafeFilePath(issue.file)} ${issue.issues.map(i => `- **${i.severity.toUpperCase()}**: ${jsonSafeUserInput(i.message)}`).join('\n')} **Suggestions:** ${jsonSafeMarkdownList(issue.suggestions)} ` ) .join('\n')} ` : '## ✅ No Validation Issues Found' } ${ releaseReadinessResult ? ` ## Release Readiness Analysis ${jsonSafeUserInput(releaseReadinessResult.summary)} ### Pre-Push Recommendations ${jsonSafeMarkdownList(releaseReadinessResult.recommendations)} ${ releaseReadinessResult.isReady ? '🎉 **Ready for Release!** This push would complete all release requirements.' : '📋 **Release Blockers**: Address these issues before considering this a release.' } ` : '' } ## Command to Execute \`\`\`bash # Run without dry run to actually push git push${branch ? ` origin ${branch}` : ''} \`\`\` **Note:** This was a dry run. No files were actually pushed. `; return { content: [ { type: 'text', text: dryRunText, }, ], }; } } catch (error) { throw new McpAdrError(`Smart git push failed: ${jsonSafeError(error)}`, 'GIT_PUSH_ERROR'); } }
- src/tools/tool-chain-orchestrator.ts:55-69 (registration)Tool name 'smart_git_push' registered in AVAILABLE_TOOLS array for orchestration and planning.'smart_git_push', 'generate_research_questions', 'validate_rules', 'analyze_code_patterns', 'suggest_improvements', 'generate_test_scenarios', 'create_documentation', 'security_audit', 'performance_analysis', 'dependency_analysis', 'refactoring_suggestions', 'api_documentation', 'deployment_checklist', 'release_notes', ] as const;