pumuki-ast-hooks 5.5.24 → 5.5.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1065,6 +1065,24 @@ For coding standards, see [CODE_STANDARDS.md](./docs/CODE_STANDARDS.md).
1065
1065
 
1066
1066
  ## 📝 Recent Changes
1067
1067
 
1068
+ ### Version 5.5.25 (2026-01-04)
1069
+
1070
+ **⚡ Performance Fix:**
1071
+ - Removed slow full AST analysis (35 minutes) from evidence guard refresh loop
1072
+ - Evidence guard now uses fast `update-evidence.sh` (seconds) instead of `intelligent-audit.js`
1073
+ - Evidence refreshes every 3 minutes as intended, notifications work correctly
1074
+
1075
+ ---
1076
+
1077
+ ### Version 5.5.24 (2026-01-04)
1078
+
1079
+ **🔔 Notifications Fix:**
1080
+ - Replaced empty catch blocks with proper error handling via `MacNotificationSender`
1081
+ - macOS notifications now sent on every evidence update with proper error management
1082
+ - Notifications show "AI Evidence has been refreshed automatically" or "AI Gate BLOCKED"
1083
+
1084
+ ---
1085
+
1068
1086
  ### Version 5.5.22 (2026-01-04)
1069
1087
 
1070
1088
  **🔴 CRITICAL Fix:**
@@ -1,3 +1,104 @@
1
+ # Release Notes - v5.5.25
2
+
3
+ **Release Date**: January 4, 2026
4
+ **Type**: Performance Patch Release
5
+ **Compatibility**: Fully backward compatible with 5.5.x
6
+
7
+ ---
8
+
9
+ ## ⚡ Performance Fix
10
+
11
+ ### Problem
12
+
13
+ The evidence guard daemon was running full AST analysis on every refresh (every 3 minutes), causing:
14
+
15
+ - **35-minute delays** between evidence updates
16
+ - **Notifications not appearing** until analysis completed
17
+ - **High CPU usage** during full repository scans
18
+
19
+ ### Root Cause
20
+
21
+ Evidence guard was calling `intelligent-audit.js` directly:
22
+
23
+ ```javascript
24
+ const astScript = 'node_modules/pumuki-ast-hooks/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js';
25
+ spawn('node', [astScript], { stdio: 'ignore' });
26
+ ```
27
+
28
+ This script performs a full repository scan (1687 files, 11356 violations) which takes 35 minutes.
29
+
30
+ ### Solution
31
+
32
+ Use `update-evidence.sh` which performs incremental analysis on staged files only:
33
+
34
+ ```javascript
35
+ spawn('bash', [this.updateScript, '--auto'], { stdio: 'ignore' });
36
+ ```
37
+
38
+ ### Impact
39
+
40
+ - **Before**: Evidence refresh takes 35 minutes, notifications delayed
41
+ - **After**: Evidence refresh takes seconds, notifications appear immediately
42
+ - Refresh interval remains 180 seconds but now completes in seconds instead of minutes
43
+
44
+ ---
45
+
46
+ ## 📦 Installation / Upgrade
47
+ ```bash
48
+ npm install --save-dev pumuki-ast-hooks@5.5.25
49
+ npm run install-hooks
50
+ npm run ast:guard:restart
51
+ ```
52
+
53
+ ---
54
+
55
+ # Release Notes - v5.5.24
56
+
57
+ **Release Date**: January 4, 2026
58
+ **Type**: Patch Release
59
+ **Compatibility**: Fully backward compatible with 5.5.x
60
+
61
+ ---
62
+
63
+ ## 🔔 Notifications Fix
64
+
65
+ ### Problem
66
+
67
+ macOS notifications had empty catch blocks that silently failed:
68
+
69
+ ```javascript
70
+ try {
71
+ execSync('osascript ...');
72
+ } catch (e) {
73
+ }
74
+ ```
75
+
76
+ ### Solution
77
+
78
+ Use `MacNotificationSender` service with proper error handling:
79
+
80
+ ```javascript
81
+ const MacNotificationSender = require('../../application/services/notification/MacNotificationSender');
82
+ const notificationSender = new MacNotificationSender(null);
83
+ notificationSender.send({ message: notifMsg, level });
84
+ ```
85
+
86
+ ### Impact
87
+
88
+ - Notifications now appear on every evidence update
89
+ - Proper error logging when notifications fail
90
+ - Consistent behavior across all notification types
91
+
92
+ ---
93
+
94
+ ## 📦 Installation / Upgrade
95
+ ```bash
96
+ npm install --save-dev pumuki-ast-hooks@5.5.24
97
+ npm run install-hooks
98
+ ```
99
+
100
+ ---
101
+
1
102
  # Release Notes - v5.5.22
2
103
 
3
104
  **Release Date**: January 4, 2026
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki-ast-hooks",
3
- "version": "5.5.24",
3
+ "version": "5.5.26",
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": {
@@ -80,61 +80,26 @@ class EvidenceGuard {
80
80
 
81
81
  async refreshEvidence() {
82
82
  return new Promise((resolve) => {
83
- const astScript = path.join(
84
- this.projectRoot,
85
- 'node_modules/pumuki-ast-hooks/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js'
86
- );
87
-
88
- if (fs.existsSync(astScript)) {
89
- console.log('[EvidenceGuard] Running full AST analysis...');
90
- const child = spawn('node', [astScript], {
91
- cwd: this.projectRoot,
92
- stdio: 'ignore',
93
- detached: false,
94
- env: {
95
- ...process.env,
96
- REPO_ROOT: this.projectRoot,
97
- AUTO_EVIDENCE_TRIGGER: 'auto',
98
- AUTO_EVIDENCE_REASON: 'evidence_guard_refresh',
99
- AUTO_EVIDENCE_SUMMARY: 'Automatic refresh by evidence guard'
100
- }
101
- });
102
-
103
- child.on('close', (code) => {
104
- if (code === 0) {
105
- console.log(`[EvidenceGuard] Full AST analysis completed at ${new Date().toISOString()}`);
106
- } else {
107
- console.error(`[EvidenceGuard] AST analysis failed with code ${code}`);
108
- }
109
- resolve();
110
- });
111
-
112
- child.on('error', (error) => {
113
- console.error('[EvidenceGuard] Failed to spawn AST analysis:', error.message);
114
- resolve();
115
- });
116
- } else {
117
- console.warn('[EvidenceGuard] intelligent-audit.js not found, falling back to update-evidence.sh');
118
- const child = spawn('bash', [this.updateScript, '--auto'], {
119
- cwd: this.projectRoot,
120
- stdio: 'ignore',
121
- detached: false
122
- });
123
-
124
- child.on('close', (code) => {
125
- if (code === 0) {
126
- console.log(`[EvidenceGuard] Evidence refreshed (fallback) at ${new Date().toISOString()}`);
127
- } else {
128
- console.error(`[EvidenceGuard] Refresh failed with code ${code}`);
129
- }
130
- resolve();
131
- });
132
-
133
- child.on('error', (error) => {
134
- console.error('[EvidenceGuard] Refresh error:', error.message);
135
- resolve();
136
- });
137
- }
83
+ console.log('[EvidenceGuard] Running evidence update...');
84
+ const child = spawn('bash', [this.updateScript, '--auto'], {
85
+ cwd: this.projectRoot,
86
+ stdio: 'ignore',
87
+ detached: false
88
+ });
89
+
90
+ child.on('close', (code) => {
91
+ if (code === 0) {
92
+ console.log(`[EvidenceGuard] Evidence refreshed at ${new Date().toISOString()}`);
93
+ } else {
94
+ console.error(`[EvidenceGuard] Refresh failed with code ${code}`);
95
+ }
96
+ resolve();
97
+ });
98
+
99
+ child.on('error', (error) => {
100
+ console.error('[EvidenceGuard] Refresh error:', error.message);
101
+ resolve();
102
+ });
138
103
  });
139
104
  }
140
105
 
@@ -10,6 +10,20 @@ const { toErrorMessage } = require('../utils/error-utils');
10
10
  const fs = require('fs');
11
11
  const path = require('path');
12
12
 
13
+ function deriveCategoryFromRuleId(ruleId) {
14
+ if (!ruleId || typeof ruleId !== 'string') return 'unknown';
15
+ const parts = ruleId.split('.');
16
+ if (parts.length >= 2) {
17
+ const platform = parts[0].toLowerCase();
18
+ const domain = parts[1].toLowerCase();
19
+ if (['ios', 'android', 'backend', 'frontend'].includes(platform)) {
20
+ return `${platform}.${domain}`;
21
+ }
22
+ return domain;
23
+ }
24
+ return parts[0] || 'unknown';
25
+ }
26
+
13
27
  function formatLocalTimestamp(date = new Date()) {
14
28
  const year = date.getFullYear();
15
29
  const month = String(date.getMonth() + 1).padStart(2, '0');
@@ -272,16 +286,19 @@ function updateAIEvidence(violations, gateResult, tokenUsage) {
272
286
  status: gateResult.passed ? 'ALLOWED' : 'BLOCKED',
273
287
  scope: gateScope === 'repo' || gateScope === 'repository' ? 'repo' : 'staging',
274
288
  last_check: formatLocalTimestamp(),
275
- violations: blockingViolations.map(v => ({
276
- file: v.filePath || v.file || 'unknown',
277
- line: v.line || null,
278
- severity: v.severity,
279
- rule: v.ruleId || v.rule || 'unknown',
280
- message: v.message || v.description || '',
281
- category: v.category || 'unknown',
282
- intelligent_evaluation: v.intelligentEvaluation || false,
283
- severity_score: v.severityScore || 0
284
- })),
289
+ violations: blockingViolations.map(v => {
290
+ const ruleId = v.ruleId || v.rule || 'unknown';
291
+ return {
292
+ file: v.filePath || v.file || 'unknown',
293
+ line: v.line || null,
294
+ severity: v.severity,
295
+ rule: ruleId,
296
+ message: v.message || v.description || '',
297
+ category: v.category || deriveCategoryFromRuleId(ruleId),
298
+ intelligent_evaluation: v.intelligentEvaluation || false,
299
+ severity_score: v.severityScore || 0
300
+ };
301
+ }),
285
302
  instruction: '🚨 AI MUST call mcp_ast-intelligence-automation_ai_gate_check BEFORE any action. If BLOCKED, fix violations first!',
286
303
  mandatory: true
287
304
  };
@@ -114,6 +114,52 @@ print_header() {
114
114
  printf "%b%s%b\n\n" "$BLUE" "$MSG_TITLE" "$NC"
115
115
  }
116
116
 
117
+ print_blocking_violations() {
118
+ if [[ ! -f "$TMP_DIR/ast-summary.json" ]]; then
119
+ return
120
+ fi
121
+ if ! command -v jq >/dev/null 2>&1; then
122
+ return
123
+ fi
124
+
125
+ local max_show=${1:-20}
126
+
127
+ local critical_violations
128
+ critical_violations=$(jq -r '
129
+ [.findings[] | select(.severity == "CRITICAL" or .severity == "critical" or .severity == "error")]
130
+ | .[0:'"$max_show"']
131
+ | .[] | "🔴 CRITICAL: \(.ruleId) - File: \(.filePath):\(.line // 1)"
132
+ ' "$TMP_DIR/ast-summary.json" 2>/dev/null || echo "")
133
+
134
+ local high_violations
135
+ high_violations=$(jq -r '
136
+ [.findings[] | select(.severity == "HIGH" or .severity == "high")]
137
+ | .[0:'"$max_show"']
138
+ | .[] | "🟠 HIGH: \(.ruleId) - File: \(.filePath):\(.line // 1)"
139
+ ' "$TMP_DIR/ast-summary.json" 2>/dev/null || echo "")
140
+
141
+ if [[ -n "$critical_violations" || -n "$high_violations" ]]; then
142
+ printf "\n%b📋 BLOCKING VIOLATIONS DETAIL:%b\n" "$YELLOW" "$NC"
143
+ printf "─────────────────────────────────────────────────────────────\n"
144
+ fi
145
+
146
+ if [[ -n "$critical_violations" ]]; then
147
+ printf "%b%s%b\n" "$RED" "$critical_violations" "$NC"
148
+ fi
149
+
150
+ if [[ -n "$high_violations" ]]; then
151
+ printf "%b%s%b\n" "$YELLOW" "$high_violations" "$NC"
152
+ fi
153
+
154
+ local total_crit total_high
155
+ total_crit=$(jq '[.findings[] | select(.severity == "CRITICAL" or .severity == "critical" or .severity == "error")] | length' "$TMP_DIR/ast-summary.json" 2>/dev/null || echo "0")
156
+ total_high=$(jq '[.findings[] | select(.severity == "HIGH" or .severity == "high")] | length' "$TMP_DIR/ast-summary.json" 2>/dev/null || echo "0")
157
+
158
+ if (( total_crit > max_show )) || (( total_high > max_show )); then
159
+ printf "\n %b(Showing first %d of each severity. Run full audit for complete list)%b\n" "$BLUE" "$max_show" "$NC"
160
+ fi
161
+ }
162
+
117
163
  ignored_globs() {
118
164
  cat <<'EOF'
119
165
  node_modules
@@ -268,6 +314,7 @@ full_audit_strict_staging_only() {
268
314
  printf " 🟠 HIGH: %s\n" "$gate_high"
269
315
  printf " 🟡 MEDIUM: %s\n" "$gate_med"
270
316
  printf " 🔵 LOW: %s\n" "$gate_low"
317
+ print_blocking_violations
271
318
  printf "\n Action: Fix ALL violations in staged files.\n"
272
319
  printf "\n"
273
320
  print_final_signature
@@ -324,6 +371,7 @@ full_audit_standard() {
324
371
  printf " 🟠 HIGH: %s\n" "$gate_high"
325
372
  printf " 🟡 MEDIUM: %s (allowed)\n" "$gate_med"
326
373
  printf " 🔵 LOW: %s (allowed)\n" "$gate_low"
374
+ print_blocking_violations
327
375
  printf "\n Action: Fix CRITICAL/HIGH violations in staged files.\n"
328
376
  printf "\n"
329
377
  print_final_signature
@@ -802,6 +850,7 @@ summarize_all() {
802
850
  printf " MEDIUM violations (repository): %s\n" "$gate_med"
803
851
  printf " LOW violations (repository): %s\n" "$gate_low"
804
852
  printf " ESLint errors (repository): %s\n" "$gate_es"
853
+ print_blocking_violations
805
854
  printf " Action: Clean entire repository before committing.\n"
806
855
  else
807
856
  printf "%b[COMMIT BLOCKED - STRICT STAGING]%b\n" "$RED" "$NC"
@@ -809,6 +858,7 @@ summarize_all() {
809
858
  printf " HIGH violations in staging: %s\n" "$gate_high"
810
859
  printf " MEDIUM violations in staging: %s\n" "$gate_med"
811
860
  printf " LOW violations in staging: %s\n" "$gate_low"
861
+ print_blocking_violations
812
862
  printf " Action: Fix violations in staged files before committing.\n"
813
863
  fi
814
864
  printf "\n"
@@ -822,6 +872,7 @@ summarize_all() {
822
872
  printf "%b[COMMIT BLOCKED - CRITICAL/HIGH]%b\n" "$RED" "$NC"
823
873
  printf " CRITICAL violations in staging: %s\n" "$gate_crit"
824
874
  printf " HIGH violations in staging: %s\n" "$gate_high"
875
+ print_blocking_violations
825
876
  printf " Action: Fix critical/high violations in staged files before committing.\n"
826
877
  printf "\n"
827
878
  print_final_signature