rules-enforcer 1.0.0

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 (33) hide show
  1. package/README.md +58 -0
  2. package/detector/README.md +212 -0
  3. package/detector/decision-engine/README.md +203 -0
  4. package/detector/decision-engine/conflict-resolver.js +336 -0
  5. package/detector/decision-engine/de-verify.js +461 -0
  6. package/detector/decision-engine/index.js +204 -0
  7. package/detector/decision-engine/optimizer.js +325 -0
  8. package/detector/decision-engine/scorer.js +359 -0
  9. package/detector/knowledge-base/README.md +140 -0
  10. package/detector/knowledge-base/agent-knowledge.json +62 -0
  11. package/detector/knowledge-base/index.js +332 -0
  12. package/detector/knowledge-base/kb-verify.js +287 -0
  13. package/detector/knowledge-base/mcp-knowledge.json +135 -0
  14. package/detector/knowledge-base/rules-knowledge.json +184 -0
  15. package/detector/mcp-server.js +157 -0
  16. package/detector/mcp-service.js +118 -0
  17. package/detector/package.json +13 -0
  18. package/detector/plugin.json +122 -0
  19. package/detector/project-detector.js +710 -0
  20. package/detector/render-engine/ag-config-render.js +195 -0
  21. package/detector/render-engine/index.js +124 -0
  22. package/detector/render-engine/render-core.js +200 -0
  23. package/detector/render-engine/render-verify.js +282 -0
  24. package/detector/render-engine/rule-render.js +231 -0
  25. package/detector/test-exceptions.js +366 -0
  26. package/detector/verify-plugin.js +233 -0
  27. package/hooks/chain-invoker.js +98 -0
  28. package/hooks/custom-hook-server.js +312 -0
  29. package/hooks/mcp-hooks.js +153 -0
  30. package/hooks/validate-chain.js +147 -0
  31. package/package.json +35 -0
  32. package/rules-server.js +350 -0
  33. package/test/test-mcp-full.js +193 -0
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Conflict Resolver - 冲突解决器
3
+ * 检测规则优先级冲突、MCP依赖冲突、资源冲突
4
+ * 优先级规则:L1 > L2 > L3 > custom
5
+ */
6
+
7
+ class ConflictResolver {
8
+ constructor() {
9
+ // 规则优先级定义
10
+ this.rulePriority = {
11
+ 'L1': 1, // 最高优先级
12
+ 'L2': 2,
13
+ 'L3': 3,
14
+ 'custom': 4 // 最低优先级
15
+ };
16
+ }
17
+
18
+ /**
19
+ * 检测规则层级冲突
20
+ */
21
+ detectRuleConflicts(rules) {
22
+ const conflicts = [];
23
+
24
+ if (!rules || rules.length === 0) {
25
+ return conflicts;
26
+ }
27
+
28
+ // 按模块分组
29
+ const moduleGroups = {};
30
+ for (const rule of rules) {
31
+ const module = rule.module || 'default';
32
+ if (!moduleGroups[module]) {
33
+ moduleGroups[module] = [];
34
+ }
35
+ moduleGroups[module].push(rule);
36
+ }
37
+
38
+ // 检查同一模块内的规则冲突
39
+ for (const [module, moduleRules] of Object.entries(moduleGroups)) {
40
+ // 检查是否有重复功能的规则
41
+ const typeMap = {};
42
+ for (const rule of moduleRules) {
43
+ const type = rule.type || 'unknown';
44
+ if (typeMap[type]) {
45
+ // 同类型规则,检查优先级
46
+ const existing = typeMap[type];
47
+ const existingPriority = this.rulePriority[existing.level] || 5;
48
+ const currentPriority = this.rulePriority[rule.level] || 5;
49
+
50
+ if (existingPriority === currentPriority) {
51
+ conflicts.push({
52
+ type: 'rule-duplicate',
53
+ severity: 'warning',
54
+ message: `模块 ${module} 中存在同类型同优先级规则`,
55
+ components: [existing.id, rule.id],
56
+ suggestion: '建议保留其中一个规则'
57
+ });
58
+ }
59
+ } else {
60
+ typeMap[type] = rule;
61
+ }
62
+ }
63
+ }
64
+
65
+ // 检查L1/L2/L3层级覆盖
66
+ const levels = {};
67
+ for (const rule of rules) {
68
+ const level = rule.level;
69
+ if (!levels[level]) {
70
+ levels[level] = [];
71
+ }
72
+ levels[level].push(rule);
73
+ }
74
+
75
+ // 检查是否缺少必要层级
76
+ if (!levels['L1'] && (levels['L2'] || levels['L3'])) {
77
+ conflicts.push({
78
+ type: 'rule-missing-level',
79
+ severity: 'info',
80
+ message: '缺少L1全局规则,建议添加用户全局行为约束',
81
+ suggestion: '添加 user_rules.md (L1)'
82
+ });
83
+ }
84
+
85
+ if (!levels['L2'] && levels['L3']) {
86
+ conflicts.push({
87
+ type: 'rule-missing-level',
88
+ severity: 'info',
89
+ message: '缺少L2项目规则,建议添加项目特定约束',
90
+ suggestion: '添加 project_rules.md (L2)'
91
+ });
92
+ }
93
+
94
+ return conflicts;
95
+ }
96
+
97
+ /**
98
+ * 检测MCP依赖冲突
99
+ */
100
+ detectMcpConflicts(mcpServices, existingMcp) {
101
+ const conflicts = [];
102
+
103
+ if (!mcpServices || mcpServices.length === 0) {
104
+ return conflicts;
105
+ }
106
+
107
+ // 构建依赖图
108
+ const dependencyGraph = {};
109
+ for (const service of mcpServices) {
110
+ dependencyGraph[service.id] = service.dependencies || [];
111
+ }
112
+
113
+ // 检查循环依赖
114
+ const visited = new Set();
115
+ const recursionStack = new Set();
116
+
117
+ const hasCycle = (node, path) => {
118
+ visited.add(node);
119
+ recursionStack.add(node);
120
+
121
+ const deps = dependencyGraph[node] || [];
122
+ for (const dep of deps) {
123
+ if (!visited.has(dep)) {
124
+ if (hasCycle(dep, [...path, dep])) {
125
+ return true;
126
+ }
127
+ } else if (recursionStack.has(dep)) {
128
+ conflicts.push({
129
+ type: 'mcp-circular-dependency',
130
+ severity: 'error',
131
+ message: `检测到MCP循环依赖: ${[...path, dep].join(' -> ')}`,
132
+ components: [...path, dep],
133
+ suggestion: '请移除循环依赖'
134
+ });
135
+ return true;
136
+ }
137
+ }
138
+
139
+ recursionStack.delete(node);
140
+ return false;
141
+ };
142
+
143
+ for (const serviceId of Object.keys(dependencyGraph)) {
144
+ if (!visited.has(serviceId)) {
145
+ hasCycle(serviceId, [serviceId]);
146
+ }
147
+ }
148
+
149
+ // 检查缺失依赖
150
+ for (const service of mcpServices) {
151
+ const deps = service.dependencies || [];
152
+ for (const dep of deps) {
153
+ const depExists = existingMcp.includes(dep) ||
154
+ mcpServices.some(s => s.id === dep);
155
+
156
+ if (!depExists) {
157
+ conflicts.push({
158
+ type: 'mcp-missing-dependency',
159
+ severity: 'warning',
160
+ message: `MCP服务 ${service.id} 依赖 ${dep},但该依赖不存在`,
161
+ components: [service.id, dep],
162
+ suggestion: `请先安装或启用 ${dep} 服务`
163
+ });
164
+ }
165
+ }
166
+
167
+ // 检查不兼容依赖
168
+ const incompatible = service.incompatible || [];
169
+ for (const inc of incompatible) {
170
+ const incExists = existingMcp.includes(inc) ||
171
+ mcpServices.some(s => s.id === inc);
172
+
173
+ if (incExists) {
174
+ conflicts.push({
175
+ type: 'mcp-incompatible-dependency',
176
+ severity: 'error',
177
+ message: `MCP服务 ${service.id} 与 ${inc} 存在功能冲突`,
178
+ components: [service.id, inc],
179
+ suggestion: `请勿同时启用 ${service.id} 和 ${inc}`
180
+ });
181
+ }
182
+ }
183
+ }
184
+
185
+ return conflicts;
186
+ }
187
+
188
+ /**
189
+ * 检测资源冲突
190
+ */
191
+ detectResourceConflicts(components, projectInfo) {
192
+ const conflicts = [];
193
+
194
+ // 检查内存/CPU限制(简化版)
195
+ const mcpCount = components.mcp?.length || 0;
196
+ const ruleCount = components.rules?.length || 0;
197
+ const complexity = projectInfo.complexity || 'medium';
198
+
199
+ // 根据项目复杂度检查组件数量
200
+ const limits = {
201
+ simple: { mcp: 3, rules: 5 },
202
+ medium: { mcp: 5, rules: 10 },
203
+ complex: { mcp: 10, rules: 20 }
204
+ };
205
+
206
+ const limit = limits[complexity] || limits.medium;
207
+
208
+ if (mcpCount > limit.mcp) {
209
+ conflicts.push({
210
+ type: 'resource-mcp-overload',
211
+ severity: 'warning',
212
+ message: `MCP服务数量(${mcpCount})超过${complexity}项目建议上限(${limit.mcp})`,
213
+ suggestion: '考虑禁用部分非必要MCP服务'
214
+ });
215
+ }
216
+
217
+ if (ruleCount > limit.rules) {
218
+ conflicts.push({
219
+ type: 'resource-rules-overload',
220
+ severity: 'warning',
221
+ message: `规则数量(${ruleCount})超过${complexity}项目建议上限(${limit.rules})`,
222
+ suggestion: '考虑合并或移除部分规则'
223
+ });
224
+ }
225
+
226
+ return conflicts;
227
+ }
228
+
229
+ /**
230
+ * 检测Agent配置冲突
231
+ */
232
+ detectAgentConflicts(agentProfile, existingAgents) {
233
+ const conflicts = [];
234
+
235
+ if (!agentProfile) {
236
+ return conflicts;
237
+ }
238
+
239
+ // 检查Agent推荐的MCP是否存在
240
+ const recommendedMcp = agentProfile.recommendedMcp || [];
241
+ const existingMcp = existingAgents.mcp || [];
242
+
243
+ for (const mcp of recommendedMcp) {
244
+ if (!existingMcp.includes(mcp)) {
245
+ conflicts.push({
246
+ type: 'agent-mcp-missing',
247
+ severity: 'info',
248
+ message: `Agent配置 ${agentProfile.name} 推荐的MCP服务 ${mcp} 未安装`,
249
+ suggestion: `考虑安装 ${mcp} 服务以获得最佳体验`
250
+ });
251
+ }
252
+ }
253
+
254
+ return conflicts;
255
+ }
256
+
257
+ /**
258
+ * 解决规则冲突(按优先级保留)
259
+ */
260
+ resolveRuleConflicts(rules) {
261
+ if (!rules || rules.length === 0) {
262
+ return { resolved: [], removed: [] };
263
+ }
264
+
265
+ // 按优先级排序
266
+ const sorted = [...rules].sort((a, b) => {
267
+ const priorityA = this.rulePriority[a.level] || 5;
268
+ const priorityB = this.rulePriority[b.level] || 5;
269
+ return priorityA - priorityB; // 低数字优先
270
+ });
271
+
272
+ // 去重(保留高优先级)
273
+ const seen = new Set();
274
+ const resolved = [];
275
+ const removed = [];
276
+
277
+ for (const rule of sorted) {
278
+ const key = `${rule.module || 'default'}-${rule.type || 'unknown'}`;
279
+ if (!seen.has(key)) {
280
+ seen.add(key);
281
+ resolved.push(rule);
282
+ } else {
283
+ removed.push(rule);
284
+ }
285
+ }
286
+
287
+ return { resolved, removed };
288
+ }
289
+
290
+ /**
291
+ * 执行完整冲突检测
292
+ */
293
+ detectAll(optimizationResult, projectInfo) {
294
+ const allConflicts = [];
295
+
296
+ // 规则冲突检测
297
+ const rules = optimizationResult.rulesResult?.all || [];
298
+ const ruleConflicts = this.detectRuleConflicts(rules);
299
+ allConflicts.push(...ruleConflicts);
300
+
301
+ // MCP依赖冲突检测
302
+ const mcpServices = optimizationResult.mcpResult?.all || [];
303
+ const existingMcp = projectInfo.existingComponents?.mcp || [];
304
+ const mcpConflicts = this.detectMcpConflicts(mcpServices, existingMcp);
305
+ allConflicts.push(...mcpConflicts);
306
+
307
+ // 资源冲突检测
308
+ const components = {
309
+ mcp: mcpServices,
310
+ rules: rules
311
+ };
312
+ const resourceConflicts = this.detectResourceConflicts(components, projectInfo);
313
+ allConflicts.push(...resourceConflicts);
314
+
315
+ // Agent冲突检测
316
+ const agentProfile = optimizationResult.agentResult?.recommended;
317
+ const agentConflicts = this.detectAgentConflicts(agentProfile, projectInfo.existingComponents || {});
318
+ allConflicts.push(...agentConflicts);
319
+
320
+ // 统计冲突严重程度
321
+ const summary = {
322
+ error: allConflicts.filter(c => c.severity === 'error').length,
323
+ warning: allConflicts.filter(c => c.severity === 'warning').length,
324
+ info: allConflicts.filter(c => c.severity === 'info').length
325
+ };
326
+
327
+ return {
328
+ conflicts: allConflicts,
329
+ summary,
330
+ hasErrors: summary.error > 0,
331
+ hasWarnings: summary.warning > 0
332
+ };
333
+ }
334
+ }
335
+
336
+ module.exports = { ConflictResolver };