pumuki-ast-hooks 5.5.0 → 5.5.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki-ast-hooks",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.1",
|
|
4
4
|
"description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -967,166 +967,172 @@ async function handleMcpMessage(message) {
|
|
|
967
967
|
// Start protocol handler
|
|
968
968
|
protocolHandler.start(handleMcpMessage);
|
|
969
969
|
|
|
970
|
+
// Log MCP ready
|
|
971
|
+
process.stderr.write(`[MCP] Server ready for ${REPO_ROOT}\n`);
|
|
972
|
+
|
|
970
973
|
/**
|
|
971
974
|
* Polling loop for background notifications and automations
|
|
975
|
+
* IMPORTANT: Delayed start to avoid blocking MCP initialization handshake
|
|
972
976
|
*/
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
if (
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
// 2. Evidence Freshness Guard
|
|
1002
|
-
if (evidenceMonitor.isStale() && (now - lastEvidenceNotification > NOTIFICATION_COOLDOWN)) {
|
|
1003
|
-
try {
|
|
1004
|
-
await evidenceMonitor.refresh();
|
|
1005
|
-
sendNotification('🔄 Evidence Auto-Updated', 'AI Evidence has been refreshed automatically', 'Purr');
|
|
1006
|
-
} catch (err) {
|
|
1007
|
-
sendNotification('⚠️ Evidence Stale', `Failed to auto-refresh evidence: ${err.message}`, 'Basso');
|
|
977
|
+
setTimeout(() => {
|
|
978
|
+
setInterval(async () => {
|
|
979
|
+
try {
|
|
980
|
+
const now = Date.now();
|
|
981
|
+
const gitFlowService = getCompositionRoot().getGitFlowService();
|
|
982
|
+
const gitQuery = getCompositionRoot().getGitQueryAdapter();
|
|
983
|
+
const evidenceMonitor = getCompositionRoot().getEvidenceMonitor();
|
|
984
|
+
const orchestrator = getCompositionRoot().getOrchestrator();
|
|
985
|
+
|
|
986
|
+
const currentBranch = gitFlowService.getCurrentBranch();
|
|
987
|
+
const baseBranch = process.env.AST_BASE_BRANCH || 'develop';
|
|
988
|
+
const isProtectedBranch = ['main', 'master', baseBranch].includes(currentBranch);
|
|
989
|
+
|
|
990
|
+
const uncommittedChanges = gitQuery.getUncommittedChanges();
|
|
991
|
+
const hasUncommittedChanges = uncommittedChanges && uncommittedChanges.length > 0;
|
|
992
|
+
|
|
993
|
+
// 1. Protected Branch Guard
|
|
994
|
+
if (isProtectedBranch && hasUncommittedChanges) {
|
|
995
|
+
if (now - lastGitFlowNotification > NOTIFICATION_COOLDOWN) {
|
|
996
|
+
const state = gitQuery.getBranchState(currentBranch);
|
|
997
|
+
sendNotification(
|
|
998
|
+
'⚠️ Git Flow Violation',
|
|
999
|
+
`branch=${currentBranch} changes detected on protected branch. Create a feature branch.`,
|
|
1000
|
+
'Basso'
|
|
1001
|
+
);
|
|
1002
|
+
lastGitFlowNotification = now;
|
|
1003
|
+
}
|
|
1008
1004
|
}
|
|
1009
|
-
lastEvidenceNotification = now;
|
|
1010
|
-
}
|
|
1011
1005
|
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
const decision = await orchestrator.analyzeContext();
|
|
1015
|
-
if (decision.action === 'auto-execute' && decision.platforms.length > 0) {
|
|
1006
|
+
// 2. Evidence Freshness Guard
|
|
1007
|
+
if (evidenceMonitor.isStale() && (now - lastEvidenceNotification > NOTIFICATION_COOLDOWN)) {
|
|
1016
1008
|
try {
|
|
1017
1009
|
await evidenceMonitor.refresh();
|
|
1018
|
-
sendNotification('
|
|
1019
|
-
} catch (
|
|
1020
|
-
sendNotification('
|
|
1010
|
+
sendNotification('🔄 Evidence Auto-Updated', 'AI Evidence has been refreshed automatically', 'Purr');
|
|
1011
|
+
} catch (err) {
|
|
1012
|
+
sendNotification('⚠️ Evidence Stale', `Failed to auto-refresh evidence: ${err.message}`, 'Basso');
|
|
1021
1013
|
}
|
|
1014
|
+
lastEvidenceNotification = now;
|
|
1022
1015
|
}
|
|
1023
|
-
}
|
|
1024
1016
|
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1017
|
+
// 3. Autonomous Orchestration
|
|
1018
|
+
if (orchestrator.shouldReanalyze()) {
|
|
1019
|
+
const decision = await orchestrator.analyzeContext();
|
|
1020
|
+
if (decision.action === 'auto-execute' && decision.platforms.length > 0) {
|
|
1021
|
+
try {
|
|
1022
|
+
await evidenceMonitor.refresh();
|
|
1023
|
+
sendNotification('✅ AI Start Executed', `Platforms: ${decision.platforms.map(p => p.platform.toUpperCase()).join(', ')}`, 'Glass');
|
|
1024
|
+
} catch (e) {
|
|
1025
|
+
sendNotification('❌ AI Start Error', `Failed to execute: ${e.message}`, 'Basso');
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
1029
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
}
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
if (process.env.DEBUG) console.error('[MCP] Polling loop error:', error);
|
|
1032
|
+
}
|
|
1033
|
+
}, 30000);
|
|
1035
1034
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1035
|
+
// AUTO-COMMIT: Only for project code changes (no node_modules, no library)
|
|
1036
|
+
setInterval(async () => {
|
|
1037
|
+
if (!AUTO_COMMIT_ENABLED) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1038
1040
|
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
const gitQuery = getCompositionRoot().getGitQueryAdapter();
|
|
1042
|
-
const gitCommand = getCompositionRoot().getGitCommandAdapter();
|
|
1041
|
+
const now = Date.now();
|
|
1042
|
+
if (now - lastAutoCommitTime < AUTO_COMMIT_INTERVAL) return;
|
|
1043
1043
|
|
|
1044
|
-
|
|
1045
|
-
|
|
1044
|
+
try {
|
|
1045
|
+
const gitFlowService = getCompositionRoot().getGitFlowService();
|
|
1046
|
+
const gitQuery = getCompositionRoot().getGitQueryAdapter();
|
|
1047
|
+
const gitCommand = getCompositionRoot().getGitCommandAdapter();
|
|
1046
1048
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
1049
|
+
const currentBranch = gitFlowService.getCurrentBranch();
|
|
1050
|
+
const isFeatureBranch = currentBranch.match(/^(feature|fix|hotfix)\//);
|
|
1050
1051
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1052
|
+
if (!isFeatureBranch) {
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1054
1055
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
// Detect library installation path
|
|
1059
|
-
const libraryPath = getLibraryInstallPath();
|
|
1060
|
-
|
|
1061
|
-
// Filter changes: project code only
|
|
1062
|
-
const filesToCommit = uncommittedChanges.filter(file => {
|
|
1063
|
-
// Exclude noise
|
|
1064
|
-
if (file.startsWith('node_modules/') ||
|
|
1065
|
-
file.includes('package-lock.json') ||
|
|
1066
|
-
file.startsWith('.git/') ||
|
|
1067
|
-
file.startsWith('.cursor/') ||
|
|
1068
|
-
file.startsWith('.ast-intelligence/') ||
|
|
1069
|
-
file.startsWith('.vscode/') ||
|
|
1070
|
-
file.startsWith('.idea/')) {
|
|
1071
|
-
return false;
|
|
1056
|
+
if (gitFlowService.isClean()) {
|
|
1057
|
+
return;
|
|
1072
1058
|
}
|
|
1073
1059
|
|
|
1074
|
-
//
|
|
1075
|
-
|
|
1076
|
-
|
|
1060
|
+
// Get uncommitted changes
|
|
1061
|
+
const uncommittedChanges = gitQuery.getUncommittedChanges();
|
|
1062
|
+
|
|
1063
|
+
// Detect library installation path
|
|
1064
|
+
const libraryPath = getLibraryInstallPath();
|
|
1065
|
+
|
|
1066
|
+
// Filter changes: project code only
|
|
1067
|
+
const filesToCommit = uncommittedChanges.filter(file => {
|
|
1068
|
+
// Exclude noise
|
|
1069
|
+
if (file.startsWith('node_modules/') ||
|
|
1070
|
+
file.includes('package-lock.json') ||
|
|
1071
|
+
file.startsWith('.git/') ||
|
|
1072
|
+
file.startsWith('.cursor/') ||
|
|
1073
|
+
file.startsWith('.ast-intelligence/') ||
|
|
1074
|
+
file.startsWith('.vscode/') ||
|
|
1075
|
+
file.startsWith('.idea/')) {
|
|
1076
|
+
return false;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// Exclude library itself
|
|
1080
|
+
if (libraryPath && file.startsWith(libraryPath + '/')) {
|
|
1081
|
+
return false;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// Code/Doc files only
|
|
1085
|
+
const codeExtensions = ['.ts', '.tsx', '.js', '.jsx', '.swift', '.kt', '.py', '.java', '.go', '.rs', '.md', '.json', '.yaml', '.yml'];
|
|
1086
|
+
return codeExtensions.some(ext => file.endsWith(ext));
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
if (filesToCommit.length === 0) {
|
|
1090
|
+
return;
|
|
1077
1091
|
}
|
|
1078
1092
|
|
|
1079
|
-
//
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1093
|
+
// Stage files
|
|
1094
|
+
filesToCommit.forEach(file => {
|
|
1095
|
+
gitCommand.add(file);
|
|
1096
|
+
});
|
|
1083
1097
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1098
|
+
const branchType = currentBranch.split('/')[0];
|
|
1099
|
+
const branchName = currentBranch.split('/').slice(1).join('/');
|
|
1100
|
+
const commitMessage = `${branchType}(auto): ${branchName} - ${filesToCommit.length} files`;
|
|
1087
1101
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
gitCommand.add(file);
|
|
1091
|
-
});
|
|
1102
|
+
// Commit
|
|
1103
|
+
gitCommand.commit(commitMessage);
|
|
1092
1104
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
const commitMessage = `${branchType}(auto): ${branchName} - ${filesToCommit.length} files`;
|
|
1105
|
+
sendNotification('✅ Auto-Commit', `${filesToCommit.length} files in ${currentBranch}`, 'Purr');
|
|
1106
|
+
lastAutoCommitTime = now;
|
|
1096
1107
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1108
|
+
if (AUTO_PUSH_ENABLED) {
|
|
1109
|
+
if (gitFlowService.isGitHubAvailable()) {
|
|
1110
|
+
try {
|
|
1111
|
+
gitCommand.push('origin', currentBranch);
|
|
1112
|
+
sendNotification('✅ Auto-Push', `Pushed to origin/${currentBranch}`, 'Glass');
|
|
1099
1113
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1114
|
+
if (AUTO_PR_ENABLED) {
|
|
1115
|
+
const baseBranch = process.env.AST_BASE_BRANCH || 'develop';
|
|
1116
|
+
const branchState = gitQuery.getBranchState(currentBranch);
|
|
1102
1117
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
if (AUTO_PR_ENABLED) {
|
|
1110
|
-
const baseBranch = process.env.AST_BASE_BRANCH || 'develop';
|
|
1111
|
-
const branchState = gitQuery.getBranchState(currentBranch);
|
|
1112
|
-
|
|
1113
|
-
if (branchState.ahead >= 3) {
|
|
1114
|
-
const prTitle = `Auto-PR: ${branchName}`;
|
|
1115
|
-
const prUrl = gitFlowService.createPullRequest(currentBranch, baseBranch, prTitle, 'Automated PR by Pumuki Git Flow');
|
|
1116
|
-
if (prUrl) {
|
|
1117
|
-
sendNotification('✅ Auto-PR Created', prTitle, 'Hero');
|
|
1118
|
+
if (branchState.ahead >= 3) {
|
|
1119
|
+
const prTitle = `Auto-PR: ${branchName}`;
|
|
1120
|
+
const prUrl = gitFlowService.createPullRequest(currentBranch, baseBranch, prTitle, 'Automated PR by Pumuki Git Flow');
|
|
1121
|
+
if (prUrl) {
|
|
1122
|
+
sendNotification('✅ Auto-PR Created', prTitle, 'Hero');
|
|
1123
|
+
}
|
|
1118
1124
|
}
|
|
1119
1125
|
}
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1126
|
+
} catch (e) {
|
|
1127
|
+
if (!e.message.includes('No remote')) {
|
|
1128
|
+
sendNotification('⚠️ Auto-Push Failed', 'Push manual required', 'Basso');
|
|
1129
|
+
}
|
|
1124
1130
|
}
|
|
1125
1131
|
}
|
|
1126
1132
|
}
|
|
1127
|
-
}
|
|
1128
1133
|
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
}, AUTO_COMMIT_INTERVAL);
|
|
1134
|
+
} catch (error) {
|
|
1135
|
+
if (process.env.DEBUG) console.error('[MCP] Auto-commit error:', error);
|
|
1136
|
+
}
|
|
1137
|
+
}, AUTO_COMMIT_INTERVAL);
|
|
1138
|
+
}, 2000); // Delay 2 seconds to allow MCP handshake to complete first
|