pumuki-ast-hooks 5.5.50 → 5.5.52

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 (30) hide show
  1. package/docs/MCP_SERVERS.md +16 -2
  2. package/docs/RELEASE_NOTES.md +34 -0
  3. package/hooks/git-status-monitor.ts +0 -5
  4. package/hooks/notify-macos.ts +0 -1
  5. package/hooks/pre-tool-use-evidence-validator.ts +0 -1
  6. package/package.json +2 -2
  7. package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +96 -0
  8. package/scripts/hooks-system/application/services/guard/GuardConfig.js +2 -4
  9. package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +2 -20
  10. package/scripts/hooks-system/application/services/installation/McpConfigurator.js +9 -139
  11. package/scripts/hooks-system/application/services/installation/mcp/McpGlobalConfigCleaner.js +49 -0
  12. package/scripts/hooks-system/application/services/installation/mcp/McpProjectConfigWriter.js +59 -0
  13. package/scripts/hooks-system/application/services/installation/mcp/McpServerConfigBuilder.js +103 -0
  14. package/scripts/hooks-system/infrastructure/ast/ast-core.js +1 -13
  15. package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +3 -2
  16. package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +17 -9
  17. package/scripts/hooks-system/infrastructure/ast/backend/detectors/god-class-detector.js +2 -1
  18. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDChecks.js +385 -0
  19. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDRules.js +38 -408
  20. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSEnterpriseAnalyzer.js +397 -34
  21. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMChecks.js +408 -0
  22. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMRules.js +36 -442
  23. package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenExtractor.js +146 -0
  24. package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenParser.js +22 -190
  25. package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenRunner.js +62 -0
  26. package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +398 -1
  27. package/scripts/hooks-system/infrastructure/orchestration/__tests__/intelligent-audit.spec.js +0 -16
  28. package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +14 -25
  29. package/scripts/hooks-system/infrastructure/shell/gitflow/gitflow-enforcer.sh +20 -76
  30. package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSEnterpriseChecks.js +0 -350
@@ -426,12 +426,26 @@ Checks if there are violations blocking work and returns `BLOCKED` or `ALLOWED`.
426
426
  ```json
427
427
  {
428
428
  "status": "ALLOWED|BLOCKED",
429
- "message": "All checks passed",
429
+ "timestamp": "2026-01-07T22:19:30.363Z",
430
+ "branch": "feature/my-task",
430
431
  "violations": [],
431
- "blockingReason": null
432
+ "warnings": [],
433
+ "autoFixes": [],
434
+ "mandatory_rules": {
435
+ "platforms": ["backend", "frontend", "ios", "android"],
436
+ "criticalRules": [],
437
+ "rulesLoaded": ["gold"],
438
+ "warning": "⚠️ AI MUST read and follow these rules before ANY code generation or modification"
439
+ },
440
+ "summary": "🚦 ALLOWED: Gate passed.",
441
+ "instructions": "You may proceed with user task. CRITICAL: Review mandatory_rules.criticalRules BEFORE generating ANY code."
432
442
  }
433
443
  ```
434
444
 
445
+ **Guarantee:** `mandatory_rules` is always returned (never `null`).
446
+ - If context/platform detection fails, it falls back to `['backend','frontend','ios','android']`.
447
+ - If rules loading fails, it returns an object with `criticalRules: []` and an `error` field instead of `null`.
448
+
435
449
  **When it returns `BLOCKED`:**
436
450
  - There are CRITICAL or HIGH violations
437
451
  - Evidence is stale and must be updated first
@@ -52,6 +52,40 @@ npm run ast:guard:restart
52
52
 
53
53
  ---
54
54
 
55
+ # Release Notes - v5.5.52
56
+
57
+ **Release Date**: January 8, 2026
58
+ **Type**: Patch Release
59
+ **Compatibility**: Fully backward compatible with 5.5.x
60
+
61
+ ---
62
+
63
+ ## 🚦 MCP AI Gate: mandatory_rules always present
64
+
65
+ ### Problem
66
+ `ai_gate_check` could return `mandatory_rules: null` when context/platform detection failed, forcing manual rule loading.
67
+
68
+ ### Solution
69
+ `ai_gate_check` now guarantees `mandatory_rules` is always returned:
70
+ - Fallback to `PlatformDetectionService` when `analyzeContext()` fails or returns no platforms.
71
+ - Deterministic fallback to `backend`, `frontend`, `ios`, `android` when detection is inconclusive.
72
+ - If rule loading fails, returns a non-null object with `criticalRules: []` and an `error` field.
73
+
74
+ ### Impact
75
+ - The AI can reliably read and apply rules on every iteration.
76
+ - Removes a class of regressions caused by missing rule payload in MCP responses.
77
+
78
+ ---
79
+
80
+ ## 📦 Installation / Upgrade
81
+
82
+ ```bash
83
+ npm install --save-dev pumuki-ast-hooks@5.5.52
84
+ npm run install-hooks
85
+ ```
86
+
87
+ ---
88
+
55
89
  # Release Notes - v5.5.24
56
90
 
57
91
  **Release Date**: January 4, 2026
@@ -42,7 +42,6 @@ function getGitStatus(projectDir: string): GitStatus | null {
42
42
  hasUncommittedChanges: lines.length > 0
43
43
  };
44
44
  } catch (err) {
45
- console.error(`[git-status-monitor] Failed to read git status: ${(err as Error).message}`);
46
45
  return null;
47
46
  }
48
47
  }
@@ -80,7 +79,6 @@ function detectPlatformFromFiles(projectDir: string): string[] {
80
79
  }
81
80
  }
82
81
  } catch (err) {
83
- console.error(`[git-status-monitor] Failed to detect platforms from files: ${(err as Error).message}`);
84
82
  }
85
83
 
86
84
  return platforms.length > 0 ? platforms : ['frontend', 'backend', 'ios', 'android'];
@@ -136,7 +134,6 @@ async function main() {
136
134
  sound: 'Ping'
137
135
  });
138
136
  } catch (err) {
139
- console.error(`[git-status-monitor] Notification failed (staged): ${(err as Error).message}`);
140
137
  }
141
138
  } else if (totalChanges > 10) {
142
139
  try {
@@ -147,13 +144,11 @@ async function main() {
147
144
  sound: 'Glass'
148
145
  });
149
146
  } catch (err) {
150
- console.error(`[git-status-monitor] Notification failed (unstaged): ${(err as Error).message}`);
151
147
  }
152
148
  }
153
149
 
154
150
  process.exit(0);
155
151
  } catch (err) {
156
- console.error(`[git-status-monitor] Unexpected error: ${(err as Error).message}`);
157
152
  process.exit(0);
158
153
  }
159
154
  }
@@ -24,7 +24,6 @@ export function sendMacOSNotification(options: NotificationOptions): void {
24
24
  try {
25
25
  execSync(`osascript -e '${script}'`, { stdio: 'ignore' });
26
26
  } catch (err) {
27
- console.error(`[notify-macos] Failed to send notification: ${(err as Error).message}`);
28
27
  }
29
28
  }
30
29
 
@@ -235,7 +235,6 @@ async function main() {
235
235
  sound: 'Basso'
236
236
  });
237
237
  } catch (err) {
238
- process.stderr.write(`Notification failed: ${err instanceof Error ? err.message : String(err)}\n`);
239
238
  }
240
239
  process.stderr.write(`${validation.error || ''}\n`);
241
240
  process.exit(2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki-ast-hooks",
3
- "version": "5.5.50",
3
+ "version": "5.5.52",
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": {
@@ -134,4 +134,4 @@
134
134
  "./skills": "./skills/skill-rules.json",
135
135
  "./hooks": "./hooks/index.js"
136
136
  }
137
- }
137
+ }
@@ -110,3 +110,99 @@
110
110
  {"timestamp":1767772971939,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
111
111
  {"timestamp":1767772971939,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
112
112
  {"timestamp":1767772971939,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
113
+ {"timestamp":1767775802167,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
114
+ {"timestamp":1767775802167,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
115
+ {"timestamp":1767775802167,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
116
+ {"timestamp":1767775802167,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
117
+ {"timestamp":1767775833943,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
118
+ {"timestamp":1767775833943,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
119
+ {"timestamp":1767775833943,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
120
+ {"timestamp":1767775833943,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
121
+ {"timestamp":1767776135844,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
122
+ {"timestamp":1767776135844,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
123
+ {"timestamp":1767776135844,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
124
+ {"timestamp":1767776135844,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
125
+ {"timestamp":1767776384649,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
126
+ {"timestamp":1767776384649,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
127
+ {"timestamp":1767776384649,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
128
+ {"timestamp":1767776384649,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
129
+ {"timestamp":1767777653343,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
130
+ {"timestamp":1767777653343,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
131
+ {"timestamp":1767777653343,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
132
+ {"timestamp":1767777653344,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
133
+ {"timestamp":1767778142566,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
134
+ {"timestamp":1767778142567,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
135
+ {"timestamp":1767778142567,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
136
+ {"timestamp":1767778142567,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
137
+ {"timestamp":1767778800954,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
138
+ {"timestamp":1767778800955,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
139
+ {"timestamp":1767778800955,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
140
+ {"timestamp":1767778800955,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
141
+ {"timestamp":1767779528552,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
142
+ {"timestamp":1767779528552,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
143
+ {"timestamp":1767779528552,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
144
+ {"timestamp":1767779528552,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
145
+ {"timestamp":1767779903813,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
146
+ {"timestamp":1767779903813,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
147
+ {"timestamp":1767779903813,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
148
+ {"timestamp":1767779903813,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
149
+ {"timestamp":1767780497468,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
150
+ {"timestamp":1767780497468,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
151
+ {"timestamp":1767780497468,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
152
+ {"timestamp":1767780497468,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
153
+ {"timestamp":1767780655724,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
154
+ {"timestamp":1767780655725,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
155
+ {"timestamp":1767780655725,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
156
+ {"timestamp":1767780655725,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
157
+ {"timestamp":1767782291627,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
158
+ {"timestamp":1767782291627,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
159
+ {"timestamp":1767782291627,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
160
+ {"timestamp":1767782291627,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
161
+ {"timestamp":1767784424360,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
162
+ {"timestamp":1767784424360,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
163
+ {"timestamp":1767784424360,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
164
+ {"timestamp":1767784424360,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
165
+ {"timestamp":1767784524038,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
166
+ {"timestamp":1767784524038,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
167
+ {"timestamp":1767784524038,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
168
+ {"timestamp":1767784524038,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
169
+ {"timestamp":1767795854402,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
170
+ {"timestamp":1767795854402,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
171
+ {"timestamp":1767795854402,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
172
+ {"timestamp":1767795854402,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
173
+ {"timestamp":1767796412339,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
174
+ {"timestamp":1767796412339,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
175
+ {"timestamp":1767796412339,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
176
+ {"timestamp":1767796412339,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
177
+ {"timestamp":1767814882292,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
178
+ {"timestamp":1767814882292,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
179
+ {"timestamp":1767814882292,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
180
+ {"timestamp":1767814882292,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
181
+ {"timestamp":1767815229484,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
182
+ {"timestamp":1767815229484,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
183
+ {"timestamp":1767815229484,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
184
+ {"timestamp":1767815229484,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
185
+ {"timestamp":1767815730534,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
186
+ {"timestamp":1767815730534,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
187
+ {"timestamp":1767815730534,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
188
+ {"timestamp":1767815730534,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
189
+ {"timestamp":1767815803186,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
190
+ {"timestamp":1767815803186,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
191
+ {"timestamp":1767815803186,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
192
+ {"timestamp":1767815803186,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
193
+ {"timestamp":1767815859028,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
194
+ {"timestamp":1767815859028,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
195
+ {"timestamp":1767815859028,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
196
+ {"timestamp":1767815859028,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
197
+ {"timestamp":1767818741021,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
198
+ {"timestamp":1767818741022,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
199
+ {"timestamp":1767818741022,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
200
+ {"timestamp":1767818741022,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
201
+ {"timestamp":1767818773283,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
202
+ {"timestamp":1767818773283,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
203
+ {"timestamp":1767818773283,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
204
+ {"timestamp":1767818773283,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
205
+ {"timestamp":1767819338043,"hook":"audit_logger","operation":"constructor","status":"started","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
206
+ {"timestamp":1767819338043,"hook":"audit_logger","operation":"ensure_dir","status":"started"}
207
+ {"timestamp":1767819338043,"hook":"audit_logger","operation":"ensure_dir","status":"success"}
208
+ {"timestamp":1767819338043,"hook":"audit_logger","operation":"constructor","status":"success","repoRoot":"/Users/juancarlosmerlosalbarracin/Developer/Projects/ast-intelligence-hooks/scripts/hooks-system"}
@@ -3,11 +3,9 @@ const AuditLogger = require('../logging/AuditLogger');
3
3
 
4
4
  class GuardConfig {
5
5
  constructor(env = envHelper) {
6
- this.auditLogger = new AuditLogger({ repoRoot: process.cwd() });
7
-
8
- const getNumber = (name, def) =>
6
+
7
+ this.auditLogger = new AuditLogger({ repoRoot: process.cwd() });const getNumber = (name, def) =>
9
8
  typeof env.getNumber === 'function' ? env.getNumber(name, def) : Number(env[name] || def);
10
-
11
9
  const getBool = (name, def) =>
12
10
  typeof env.getBool === 'function' ? env.getBool(name, def) : (env[name] !== 'false');
13
11
 
@@ -128,20 +128,6 @@ if [[ "$CURRENT_BRANCH" == "main" ]] || [[ "$CURRENT_BRANCH" == "master" ]] || [
128
128
  exit 1
129
129
  fi
130
130
 
131
- # Enforce Git Flow checks (strict) before allowing commit
132
- ENFORCER_SCRIPT="scripts/hooks-system/infrastructure/shell/gitflow/gitflow-enforcer.sh"
133
- if [[ -f "$ENFORCER_SCRIPT" ]]; then
134
- echo ""
135
- echo "🔍 Running Git Flow checks (strict)..."
136
- echo ""
137
- if ! GITFLOW_STRICT_CHECK=true bash "$ENFORCER_SCRIPT" check; then
138
- echo ""
139
- echo "🚨 COMMIT BLOCKED: Git Flow checks failed"
140
- echo ""
141
- exit 1
142
- fi
143
- fi
144
-
145
131
  # Check if there are staged files
146
132
  STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM 2>/dev/null | grep -E '\\.(ts|tsx|js|jsx|swift|kt)$' || true)
147
133
  if [ -z "$STAGED_FILES" ]; then
@@ -277,14 +263,10 @@ fi
277
263
  # Run gitflow-enforcer if available (optional validation)
278
264
  ENFORCER_SCRIPT="scripts/hooks-system/infrastructure/shell/gitflow/gitflow-enforcer.sh"
279
265
  if [[ -f "$ENFORCER_SCRIPT" ]]; then
280
- echo ""
281
- echo "🔍 Running Git Flow checks (strict)..."
282
- echo ""
283
- if ! GITFLOW_STRICT_CHECK=true bash "$ENFORCER_SCRIPT" check; then
266
+ if ! bash "$ENFORCER_SCRIPT" check 2>/dev/null; then
284
267
  echo ""
285
- echo "🚨 PUSH BLOCKED: Git Flow checks failed"
268
+ echo "⚠️ Git Flow check completed with warnings (non-blocking)"
286
269
  echo ""
287
- exit 1
288
270
  fi
289
271
  fi
290
272
 
@@ -1,10 +1,9 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { execSync } = require('child_process');
4
- const crypto = require('crypto');
5
- const os = require('os');
6
- const env = require('../../../config/env.js');
7
3
  const AuditLogger = require('../logging/AuditLogger');
4
+ const McpServerConfigBuilder = require('./mcp/McpServerConfigBuilder');
5
+ const McpProjectConfigWriter = require('./mcp/McpProjectConfigWriter');
6
+ const McpGlobalConfigCleaner = require('./mcp/McpGlobalConfigCleaner');
8
7
 
9
8
  const COLORS = {
10
9
  reset: '\x1b[0m',
@@ -13,151 +12,22 @@ const COLORS = {
13
12
  cyan: '\x1b[36m'
14
13
  };
15
14
 
16
- function slugifyId(input) {
17
- return String(input || '')
18
- .trim()
19
- .toLowerCase()
20
- .replace(/[^a-z0-9]+/g, '-')
21
- .replace(/^-+|-+$/g, '')
22
- .slice(0, 48);
23
- }
24
-
25
- function computeRepoFingerprint(repoRoot) {
26
- try {
27
- const real = fs.realpathSync(repoRoot);
28
- return crypto.createHash('sha1').update(real).digest('hex').slice(0, 8);
29
- } catch (error) {
30
- if (process.env.DEBUG) {
31
- process.stderr.write(`[MCP] computeRepoFingerprint fallback: ${error && error.message ? error.message : String(error)}\n`);
32
- }
33
- return crypto.createHash('sha1').update(String(repoRoot || '')).digest('hex').slice(0, 8);
34
- }
35
- }
36
-
37
- function computeServerIdForRepo(repoRoot) {
38
- const legacyServerId = 'ast-intelligence-automation';
39
- const forced = (env.get('MCP_SERVER_ID', '') || '').trim();
40
- if (forced.length > 0) return forced;
41
-
42
- const repoName = path.basename(repoRoot || process.cwd());
43
- const slug = slugifyId(repoName) || 'repo';
44
- const fp = computeRepoFingerprint(repoRoot);
45
- return `${legacyServerId}-${slug}-${fp}`;
46
- }
47
-
48
15
  class McpConfigurator {
49
16
  constructor(targetRoot, hookSystemRoot, logger = null) {
50
17
  this.targetRoot = targetRoot;
51
18
  this.hookSystemRoot = hookSystemRoot;
52
19
  this.logger = logger;
53
- }
54
-
55
- resolveAutomationEntrypoint() {
56
- // Prefer dependency-installed hook system (node_modules) to avoid requiring scripts/hooks-system in consumer repos
57
- // Fallback to repo-local hook system if it exists.
58
- const candidates = [
59
- this.hookSystemRoot
60
- ? path.join(this.hookSystemRoot, 'infrastructure', 'mcp', 'ast-intelligence-automation.js')
61
- : null,
62
- path.join(this.targetRoot, 'scripts', 'hooks-system', 'infrastructure', 'mcp', 'ast-intelligence-automation.js')
63
- ].filter(Boolean);
64
-
65
- for (const c of candidates) {
66
- try {
67
- if (fs.existsSync(c)) return c;
68
- } catch (error) {
69
- // Log error but continue checking other candidates
70
- console.warn(`Failed to check path ${c}:`, error.message);
71
- }
72
- }
73
-
74
- // Last resort: keep previous behaviour
75
- return path.join(this.targetRoot, 'scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js');
76
- }
77
-
78
- disableDuplicateServersForRepo(existing, currentServerId) {
79
- if (!existing || !existing.mcpServers) return;
80
-
81
- Object.entries(existing.mcpServers).forEach(([id, server]) => {
82
- if (!server || id === currentServerId) return;
83
- const envObj = server.env || {};
84
- const repoRoot = envObj.REPO_ROOT;
85
- if (repoRoot !== this.targetRoot) return;
86
-
87
- const args0 = Array.isArray(server.args) ? String(server.args[0] || '') : '';
88
- // Disable legacy server pointing to repo-local scripts/hooks-system when we already configure the canonical one
89
- if (args0.includes('/scripts/hooks-system/') || args0.includes('\\scripts\\hooks-system\\')) {
90
- server.disabled = true;
91
- }
92
- });
93
- }
94
-
95
- getGlobalWindsurfConfigPath() {
96
- return path.join(os.homedir(), '.codeium', 'windsurf', 'mcp_config.json');
20
+ this.serverConfigBuilder = new McpServerConfigBuilder(targetRoot, hookSystemRoot, logger);
21
+ this.projectWriter = new McpProjectConfigWriter(targetRoot, logger, this.logSuccess.bind(this), this.logWarning.bind(this), this.logInfo.bind(this));
22
+ this.globalCleaner = new McpGlobalConfigCleaner(targetRoot, logger, this.logInfo.bind(this));
97
23
  }
98
24
 
99
25
  configure() {
100
26
  if (this.logger) this.logger.info('MCP_CONFIGURATION_STARTED');
101
27
 
102
- let nodePath = process.execPath;
103
- if (!nodePath || !fs.existsSync(nodePath)) {
104
- try {
105
- nodePath = execSync('which node', { encoding: 'utf-8' }).trim();
106
- } catch (error) {
107
- if (process.env.DEBUG) {
108
- process.stderr.write(`[MCP] which node failed: ${error && error.message ? error.message : String(error)}\n`);
109
- }
110
- nodePath = 'node';
111
- }
112
- }
113
-
114
- const serverId = computeServerIdForRepo(this.targetRoot);
115
- const entrypoint = this.resolveAutomationEntrypoint();
116
- const mcpConfig = {
117
- mcpServers: {
118
- [serverId]: {
119
- command: nodePath,
120
- args: [
121
- entrypoint
122
- ],
123
- env: {
124
- REPO_ROOT: this.targetRoot,
125
- AUTO_COMMIT_ENABLED: 'false',
126
- AUTO_PUSH_ENABLED: 'false',
127
- AUTO_PR_ENABLED: 'false'
128
- }
129
- }
130
- }
131
- };
132
-
133
- const globalConfigPath = this.getGlobalWindsurfConfigPath();
134
- const globalConfigDir = path.dirname(globalConfigPath);
135
- if (!fs.existsSync(globalConfigDir)) {
136
- fs.mkdirSync(globalConfigDir, { recursive: true });
137
- }
138
-
139
- try {
140
- if (!fs.existsSync(globalConfigPath)) {
141
- fs.writeFileSync(globalConfigPath, JSON.stringify(mcpConfig, null, 2));
142
- this.logSuccess(`Configured global Windsurf MCP at ${globalConfigPath}`);
143
- if (this.logger) this.logger.info('MCP_GLOBAL_CONFIGURED', { path: globalConfigPath });
144
- } else {
145
- const existing = JSON.parse(fs.readFileSync(globalConfigPath, 'utf8'));
146
- if (!existing.mcpServers) existing.mcpServers = {};
147
-
148
- // Prevent duplicate MCP servers for the same repoRoot by disabling legacy entries.
149
- this.disableDuplicateServersForRepo(existing, serverId);
150
-
151
- existing.mcpServers[serverId] = mcpConfig.mcpServers[serverId];
152
-
153
- fs.writeFileSync(globalConfigPath, JSON.stringify(existing, null, 2));
154
- this.logSuccess(`Updated global Windsurf MCP at ${globalConfigPath}`);
155
- if (this.logger) this.logger.info('MCP_GLOBAL_UPDATED', { path: globalConfigPath });
156
- }
157
- } catch (mergeError) {
158
- this.logWarning(`${globalConfigPath} exists but couldn't be merged, skipping`);
159
- if (this.logger) this.logger.warn('MCP_GLOBAL_MERGE_FAILED', { error: mergeError.message });
160
- }
28
+ const { serverId, mcpConfig } = this.serverConfigBuilder.build();
29
+ this.projectWriter.configureProjectScoped(mcpConfig, serverId);
30
+ this.globalCleaner.cleanupGlobalConfig(serverId);
161
31
  }
162
32
 
163
33
  detectIDEs() {
@@ -0,0 +1,49 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class McpGlobalConfigCleaner {
5
+ constructor(targetRoot, logger, logInfo) {
6
+ this.targetRoot = targetRoot;
7
+ this.logger = logger;
8
+ this.logInfo = logInfo;
9
+ }
10
+
11
+ cleanupGlobalConfig(currentServerId) {
12
+ const globalConfigPath = this.getGlobalWindsurfConfigPath();
13
+
14
+ try {
15
+ if (!fs.existsSync(globalConfigPath)) return;
16
+
17
+ const existing = JSON.parse(fs.readFileSync(globalConfigPath, 'utf8'));
18
+ if (!existing.mcpServers) return;
19
+
20
+ let modified = false;
21
+ Object.keys(existing.mcpServers).forEach(id => {
22
+ const server = existing.mcpServers[id];
23
+ if (!server || !server.env) return;
24
+
25
+ if (server.env.REPO_ROOT === this.targetRoot) {
26
+ delete existing.mcpServers[id];
27
+ modified = true;
28
+ this.logInfo?.(`Removed ${id} from global config (now project-scoped)`);
29
+ }
30
+ });
31
+
32
+ if (modified) {
33
+ fs.writeFileSync(globalConfigPath, JSON.stringify(existing, null, 2));
34
+ this.logger?.info?.('MCP_GLOBAL_CLEANUP', { removedForRepo: this.targetRoot });
35
+ }
36
+ } catch (error) {
37
+ if (process.env.DEBUG) {
38
+ process.stderr.write(`[MCP] cleanupGlobalConfig failed: ${error.message}\n`);
39
+ }
40
+ }
41
+ }
42
+
43
+ getGlobalWindsurfConfigPath() {
44
+ const os = require('os');
45
+ return path.join(os.homedir(), '.codeium', 'windsurf', 'mcp_config.json');
46
+ }
47
+ }
48
+
49
+ module.exports = McpGlobalConfigCleaner;
@@ -0,0 +1,59 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ class McpProjectConfigWriter {
5
+ constructor(targetRoot, logger, logSuccess, logWarning, logInfo) {
6
+ this.targetRoot = targetRoot;
7
+ this.logger = logger;
8
+ this.logSuccess = logSuccess;
9
+ this.logWarning = logWarning;
10
+ this.logInfo = logInfo;
11
+ }
12
+
13
+ configureProjectScoped(mcpConfig, serverId) {
14
+ this.writeWindsurfConfig(mcpConfig, serverId);
15
+ this.writeCursorConfig(mcpConfig, serverId);
16
+ }
17
+
18
+ writeWindsurfConfig(mcpConfig, serverId) {
19
+ const windsurfProjectDir = path.join(this.targetRoot, '.windsurf');
20
+ const windsurfProjectPath = path.join(windsurfProjectDir, 'mcp.json');
21
+ this.writeProjectConfig(windsurfProjectDir, windsurfProjectPath, mcpConfig, serverId, 'Windsurf', 'MCP_PROJECT_CONFIGURED', 'MCP_PROJECT_CONFIGURE_FAILED');
22
+ }
23
+
24
+ writeCursorConfig(mcpConfig, serverId) {
25
+ const cursorProjectDir = path.join(this.targetRoot, '.cursor');
26
+ const cursorProjectPath = path.join(cursorProjectDir, 'mcp.json');
27
+ this.writeProjectConfig(cursorProjectDir, cursorProjectPath, mcpConfig, serverId, 'Cursor', 'MCP_CURSOR_CONFIGURED', 'MCP_CURSOR_CONFIGURE_FAILED');
28
+ }
29
+
30
+ writeProjectConfig(dir, filePath, mcpConfig, serverId, label, successEvent, errorEvent) {
31
+ try {
32
+ if (!fs.existsSync(dir)) {
33
+ fs.mkdirSync(dir, { recursive: true });
34
+ }
35
+
36
+ let finalConfig = mcpConfig;
37
+ if (fs.existsSync(filePath)) {
38
+ const existing = JSON.parse(fs.readFileSync(filePath, 'utf8'));
39
+ if (!existing.mcpServers) existing.mcpServers = {};
40
+ Object.keys(existing.mcpServers).forEach(id => {
41
+ if (id.startsWith('ast-intelligence-automation-') && id !== serverId) {
42
+ delete existing.mcpServers[id];
43
+ }
44
+ });
45
+ existing.mcpServers[serverId] = mcpConfig.mcpServers[serverId];
46
+ finalConfig = existing;
47
+ }
48
+
49
+ fs.writeFileSync(filePath, JSON.stringify(finalConfig, null, 2));
50
+ this.logSuccess?.(`Configured project-scoped ${label} MCP at ${filePath}`);
51
+ this.logger?.info?.(successEvent, { path: filePath, serverId });
52
+ } catch (error) {
53
+ this.logWarning?.(`Failed to configure ${label} MCP: ${error.message}`);
54
+ this.logger?.warn?.(errorEvent, { error: error.message });
55
+ }
56
+ }
57
+ }
58
+
59
+ module.exports = McpProjectConfigWriter;