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.
- package/docs/MCP_SERVERS.md +16 -2
- package/docs/RELEASE_NOTES.md +34 -0
- package/hooks/git-status-monitor.ts +0 -5
- package/hooks/notify-macos.ts +0 -1
- package/hooks/pre-tool-use-evidence-validator.ts +0 -1
- package/package.json +2 -2
- package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +96 -0
- package/scripts/hooks-system/application/services/guard/GuardConfig.js +2 -4
- package/scripts/hooks-system/application/services/installation/GitEnvironmentService.js +2 -20
- package/scripts/hooks-system/application/services/installation/McpConfigurator.js +9 -139
- package/scripts/hooks-system/application/services/installation/mcp/McpGlobalConfigCleaner.js +49 -0
- package/scripts/hooks-system/application/services/installation/mcp/McpProjectConfigWriter.js +59 -0
- package/scripts/hooks-system/application/services/installation/mcp/McpServerConfigBuilder.js +103 -0
- package/scripts/hooks-system/infrastructure/ast/ast-core.js +1 -13
- package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +3 -2
- package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +17 -9
- package/scripts/hooks-system/infrastructure/ast/backend/detectors/god-class-detector.js +2 -1
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDChecks.js +385 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSCICDRules.js +38 -408
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSEnterpriseAnalyzer.js +397 -34
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMChecks.js +408 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSSPMRules.js +36 -442
- package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenExtractor.js +146 -0
- package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenParser.js +22 -190
- package/scripts/hooks-system/infrastructure/ast/ios/parsers/SourceKittenRunner.js +62 -0
- package/scripts/hooks-system/infrastructure/mcp/ast-intelligence-automation.js +398 -1
- package/scripts/hooks-system/infrastructure/orchestration/__tests__/intelligent-audit.spec.js +0 -16
- package/scripts/hooks-system/infrastructure/orchestration/intelligent-audit.js +14 -25
- package/scripts/hooks-system/infrastructure/shell/gitflow/gitflow-enforcer.sh +20 -76
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSEnterpriseChecks.js +0 -350
package/docs/MCP_SERVERS.md
CHANGED
|
@@ -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
|
-
"
|
|
429
|
+
"timestamp": "2026-01-07T22:19:30.363Z",
|
|
430
|
+
"branch": "feature/my-task",
|
|
430
431
|
"violations": [],
|
|
431
|
-
"
|
|
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
|
package/docs/RELEASE_NOTES.md
CHANGED
|
@@ -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
|
}
|
package/hooks/notify-macos.ts
CHANGED
|
@@ -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.
|
|
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
|
-
|
|
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
|
-
|
|
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 "
|
|
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
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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;
|