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,195 @@
1
+ /**
2
+ * Agent Config Render - Agent配置渲染器
3
+ * 生成AGENTS.md和CLAUDE.md标准配置
4
+ */
5
+
6
+ class AgentConfigRender {
7
+ constructor() {
8
+ this.template = {
9
+ agents: this.getAgentsTemplate(),
10
+ claude: this.getClaudeTemplate()
11
+ };
12
+ }
13
+
14
+ /**
15
+ * 渲染AGENTS.md
16
+ */
17
+ renderAgentsMd(decisionResult) {
18
+ const recommendedAgent = decisionResult.decision?.recommendedAgent;
19
+ const recommendedMcp = decisionResult.decision?.recommendedMcp || [];
20
+
21
+ let content = `# AGENTS.md - Agent Configuration
22
+
23
+ ## Agent Identity
24
+
25
+ `;
26
+
27
+ if (recommendedAgent) {
28
+ content += `### ${recommendedAgent.name}
29
+
30
+ `;
31
+ content += `**Type**: ${recommendedAgent.type || 'general-purpose'}\n\n`;
32
+ content += `**Version**: 1.0.0\n\n`;
33
+ content += `**Description**: ${recommendedAgent.description || `AI agent configured for optimal project support`}\n\n`;
34
+
35
+ if (recommendedAgent.recommendedMcp) {
36
+ content += `### MCP Services\n\n`;
37
+ content += `Recommended MCP services for this agent:\n\n`;
38
+ for (const mcp of recommendedAgent.recommendedMcp) {
39
+ content += `- \`${mcp}\`\n`;
40
+ }
41
+ content += `\n`;
42
+ }
43
+
44
+ if (recommendedAgent.recommendedRules) {
45
+ content += `### Rule Levels\n\n`;
46
+ content += `Applicable rule levels:\n\n`;
47
+ for (const ruleLevel of recommendedAgent.recommendedRules) {
48
+ content += `- **${ruleLevel}**: `;
49
+ switch (ruleLevel) {
50
+ case 'L1': content += `Global behavior constraints\n`; break;
51
+ case 'L2': content += `Project-specific rules\n`; break;
52
+ case 'L3': content += `Module-level rules\n`; break;
53
+ default: content += `Custom rules\n`;
54
+ }
55
+ }
56
+ content += `\n`;
57
+ }
58
+ }
59
+
60
+ content += `## Agent Capabilities
61
+
62
+ ### Core Capabilities
63
+
64
+ - **Code Generation**: Generate TypeScript, JavaScript, React components
65
+ - **Code Refactoring**: Improve code quality and structure
66
+ - **Bug Detection**: Identify and fix common bugs
67
+ - **Debugging**: Analyze and resolve issues
68
+ - **Documentation**: Generate API docs, README, code comments
69
+ - **Testing**: Write unit tests, integration tests
70
+ - **Requirements Analysis**: Parse and understand user requirements
71
+
72
+ ### Behavior Constraints
73
+
74
+ 1. Follow AGENTS.md > CLAUDE.md > .trae/rules priority
75
+ 2. Use TypeScript strict mode
76
+ 3. Follow ESLint rules
77
+ 4. Use Prettier for formatting
78
+ 5. No hardcoded credentials
79
+ 6. No console.log statements in production code
80
+
81
+ ### MCP Integration
82
+
83
+ `;
84
+ if (recommendedMcp.length > 0) {
85
+ content += `Configured MCP services:\n\n`;
86
+ for (const mcp of recommendedMcp) {
87
+ content += `- **${mcp.name}** (${mcp.type}): ${mcp.id}\n`;
88
+ }
89
+ } else {
90
+ content += `No additional MCP services required.\n`;
91
+ }
92
+
93
+ content += `
94
+ ---
95
+
96
+ *Generated by TRAIDE Project Configuration System*
97
+ `;
98
+
99
+ return content;
100
+ }
101
+
102
+ /**
103
+ * 渲染CLAUDE.md
104
+ */
105
+ renderClaudeMd(decisionResult) {
106
+ const recommendedAgent = decisionResult.decision?.recommendedAgent;
107
+ const recommendedRules = decisionResult.decision?.recommendedRules || [];
108
+ const scoreBreakdown = decisionResult.scoreBreakdown || {};
109
+
110
+ let content = `# CLAUDE.md - Project Configuration
111
+
112
+ ## Project Overview
113
+
114
+ `;
115
+ if (recommendedAgent) {
116
+ content += `**Agent**: ${recommendedAgent.name}\n`;
117
+ }
118
+ content += `**Generated**: ${new Date().toISOString()}\n`;
119
+ content += `**Confidence**: ${(decisionResult.decision?.confidence * 100 || 0).toFixed(1)}%\n\n`;
120
+
121
+ content += `## Score Breakdown\n\n`;
122
+ content += `| Metric | Score |\n`;
123
+ content += `|--------|-------|\n`;
124
+ content += `| Tech Stack Match | ${scoreBreakdown.techStackMatch || 0}/100 |\n`;
125
+ content += `| Complexity Fit | ${scoreBreakdown.complexityFit || 0}/100 |\n`;
126
+ content += `| Dependency Score | ${scoreBreakdown.dependencyScore || 0}/100 |\n`;
127
+ content += `| Reuse Score | ${scoreBreakdown.reuseScore || 0}/100 |\n\n`;
128
+
129
+ content += `## Configuration Priority\n\n`;
130
+ content += `**IMPORTANT**: Configuration files are loaded in the following order:\n\n`;
131
+ content += `1. **AGENTS.md** (highest priority) - Agent-specific configuration\n`;
132
+ content += `2. **CLAUDE.md** (project level) - Project-specific settings\n`;
133
+ content += `3. **.trae/rules/** (lowest priority) - Rule files\n\n`;
134
+
135
+ content += `## Rule Levels\n\n`;
136
+ content += `### L1 - Global Rules\n`;
137
+ content += `Global behavior constraints that apply to all operations.\n\n`;
138
+ content += `### L2 - Project Rules\n`;
139
+ content += `Project-specific rules for this workspace.\n\n`;
140
+ content += `### L3 - Module Rules\n`;
141
+ content += `Module-level rules organized by functionality.\n\n`;
142
+
143
+ if (recommendedRules.length > 0) {
144
+ content += `## Recommended Rules\n\n`;
145
+ for (const rule of recommendedRules) {
146
+ content += `- **${rule.name}** [${rule.level}]: ${rule.description || 'No description'}\n`;
147
+ }
148
+ content += `\n`;
149
+ }
150
+
151
+ content += `## Conflicts & Warnings\n\n`;
152
+ if (decisionResult.conflicts && decisionResult.conflicts.length > 0) {
153
+ for (const conflict of decisionResult.conflicts) {
154
+ const icon = conflict.severity === 'error' ? '❌' :
155
+ conflict.severity === 'warning' ? '⚠️' : 'ℹ️';
156
+ content += `${icon} ${conflict.message}\n`;
157
+ if (conflict.suggestion) {
158
+ content += ` → ${conflict.suggestion}\n`;
159
+ }
160
+ }
161
+ } else {
162
+ content += `No conflicts detected.\n`;
163
+ }
164
+
165
+ content += `
166
+ ---
167
+
168
+ *Generated by TRAIDE Decision Engine*
169
+ `;
170
+
171
+ return content;
172
+ }
173
+
174
+ /**
175
+ * 获取AGENTS.md模板
176
+ */
177
+ getAgentsTemplate() {
178
+ return {
179
+ header: '# AGENTS.md - Agent Configuration',
180
+ sections: ['identity', 'capabilities', 'constraints', 'mcp', 'rules']
181
+ };
182
+ }
183
+
184
+ /**
185
+ * 获取CLAUDE.md模板
186
+ */
187
+ getClaudeTemplate() {
188
+ return {
189
+ header: '# CLAUDE.md - Project Configuration',
190
+ sections: ['overview', 'priority', 'rules', 'conflicts']
191
+ };
192
+ }
193
+ }
194
+
195
+ module.exports = { AgentConfigRender };
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Render Engine - 渲染引擎入口
3
+ * 对接decision-engine决策结果,一键渲染全套配置
4
+ */
5
+
6
+ const path = require('path');
7
+ const { RenderCore } = require('./render-core.js');
8
+
9
+ class RenderEngine {
10
+ constructor(options = {}) {
11
+ this.outputDir = options.outputDir || process.cwd();
12
+ this.renderCore = new RenderCore({ outputDir: this.outputDir });
13
+ }
14
+
15
+ /**
16
+ * 执行完整渲染流程
17
+ * 接收decision-engine的决策结果作为唯一数据源
18
+ */
19
+ async render(decisionResult) {
20
+ console.log('\n[RenderEngine] ========== 配置渲染开始 ==========\n');
21
+
22
+ // 数据源验证:必须来自decision-engine
23
+ if (!decisionResult || !decisionResult.decision) {
24
+ throw new Error('无效的决策结果,数据源必须来自decision-engine');
25
+ }
26
+
27
+ // 执行渲染
28
+ const result = await this.renderCore.render(decisionResult);
29
+
30
+ // 输出结果
31
+ if (result.success) {
32
+ console.log(`[RenderEngine] ✅ 渲染成功,共生成 ${result.files.length} 个文件:\n`);
33
+ for (const file of result.files) {
34
+ console.log(` - ${file.path} [${file.type || file.level || 'file'}]`);
35
+ }
36
+ } else {
37
+ console.log(`[RenderEngine] ❌ 渲染失败:\n`);
38
+ for (const error of result.errors) {
39
+ console.log(` - ${error}`);
40
+ }
41
+ }
42
+
43
+ console.log('\n[RenderEngine] ========== 渲染完成 ==========\n');
44
+
45
+ return result;
46
+ }
47
+
48
+ /**
49
+ * 打印渲染摘要
50
+ */
51
+ printSummary() {
52
+ const summary = this.renderCore.getSummary();
53
+ console.log('\n========== 渲染摘要 ==========');
54
+ console.log(`优先级: ${summary.priority}`);
55
+ console.log(`文件总数: ${summary.totalFiles}`);
56
+ console.log('================================\n');
57
+ }
58
+
59
+ /**
60
+ * 获取引擎信息
61
+ */
62
+ getInfo() {
63
+ return {
64
+ name: 'RenderEngine',
65
+ version: '1.0.0',
66
+ priority: 'AGENTS.md > CLAUDE.md > .trae/rules',
67
+ formats: ['AGENTS.md (Markdown)', 'CLAUDE.md (Markdown)', '.trae/rules/*.yml (YAML)']
68
+ };
69
+ }
70
+ }
71
+
72
+ module.exports = { RenderEngine };
73
+
74
+ // CLI入口
75
+ if (require.main === module) {
76
+ const path = require('path');
77
+
78
+ try {
79
+ // 加载decision-engine结果(模拟)
80
+ console.log('[RenderEngine] CLI模式示例');
81
+ console.log('实际使用时,decision-result应从decision-engine获取\n');
82
+
83
+ // 示例决策结果
84
+ const mockDecisionResult = {
85
+ decision: {
86
+ recommendedMcp: [
87
+ { id: 'context7', name: 'Context7', type: 'context-management' }
88
+ ],
89
+ recommendedRules: [
90
+ { id: 'user-rules', name: 'User Rules', level: 'L1', description: '用户全局行为约束' },
91
+ { id: 'project-rules', name: 'Project Rules', level: 'L2', description: '项目特定规则' },
92
+ { id: 'rzero-agent', name: 'RZero Agent Configuration', level: 'L3', module: 'RZero', description: 'RZero Agent配置' }
93
+ ],
94
+ recommendedAgent: {
95
+ id: 'fullstack-developer',
96
+ name: 'Full Stack Developer',
97
+ type: 'general-purpose',
98
+ recommendedMcp: ['rules-enforcer', 'context7'],
99
+ recommendedRules: ['L1', 'L2']
100
+ },
101
+ confidence: 0.94
102
+ },
103
+ scoreBreakdown: {
104
+ techStackMatch: 93,
105
+ complexityFit: 100,
106
+ dependencyScore: 88,
107
+ reuseScore: 100
108
+ },
109
+ conflicts: [],
110
+ alternatives: []
111
+ };
112
+
113
+ const engine = new RenderEngine({ outputDir: process.cwd() });
114
+ engine.render(mockDecisionResult).then(result => {
115
+ engine.printSummary();
116
+ console.log('完整渲染结果:');
117
+ console.log(JSON.stringify(result, null, 2));
118
+ });
119
+
120
+ } catch (e) {
121
+ console.error('[RenderEngine] 执行失败:', e.message);
122
+ process.exit(1);
123
+ }
124
+ }
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Render Core - 核心渲染引擎
3
+ * 接收decision-engine决策结果,调度各渲染器生成配置
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { RuleRender } = require('./rule-render.js');
9
+ const { AgentConfigRender } = require('./ag-config-render.js');
10
+
11
+ /**
12
+ * Promise化的fs方法
13
+ */
14
+ const fsPromises = {
15
+ writeFile: (path, content, encoding) => fs.promises.writeFile(path, content, encoding),
16
+ readFile: (path, encoding) => fs.promises.readFile(path, encoding),
17
+ ensureDir: async (dirPath) => {
18
+ try {
19
+ await fs.promises.mkdir(dirPath, { recursive: true });
20
+ } catch (e) {
21
+ if (e.code !== 'EEXIST') throw e;
22
+ }
23
+ },
24
+ pathExists: (path) => fs.promises.access(path).then(() => true).catch(() => false),
25
+ readdir: (path, options) => fs.promises.readdir(path, options)
26
+ };
27
+
28
+ class RenderCore {
29
+ constructor(options = {}) {
30
+ this.outputDir = options.outputDir || process.cwd();
31
+ this.ruleRender = new RuleRender();
32
+ this.agentConfigRender = new AgentConfigRender();
33
+ this.renderedFiles = [];
34
+ }
35
+
36
+ /**
37
+ * 执行完整渲染流程
38
+ */
39
+ async render(decisionResult) {
40
+ const results = {
41
+ success: true,
42
+ files: [],
43
+ errors: []
44
+ };
45
+
46
+ try {
47
+ // 1. 渲染Agent配置(最高优先级)
48
+ const agentResult = await this.renderAgentConfigs(decisionResult);
49
+ results.files.push(...agentResult.files);
50
+ if (agentResult.error) results.errors.push(agentResult.error);
51
+
52
+ // 2. 渲染规则文件(次优先级)
53
+ const rulesResult = await this.renderRules(decisionResult);
54
+ results.files.push(...rulesResult.files);
55
+ if (rulesResult.error) results.errors.push(rulesResult.error);
56
+
57
+ results.success = results.errors.length === 0;
58
+ this.renderedFiles = results.files;
59
+
60
+ } catch (e) {
61
+ results.success = false;
62
+ results.errors.push(`渲染核心错误: ${e.message}`);
63
+ }
64
+
65
+ return results;
66
+ }
67
+
68
+ /**
69
+ * 渲染Agent配置文件
70
+ */
71
+ async renderAgentConfigs(decisionResult) {
72
+ const result = { files: [], error: null };
73
+
74
+ try {
75
+ // 渲染AGENTS.md
76
+ const agentsContent = this.agentConfigRender.renderAgentsMd(decisionResult);
77
+ const agentsPath = path.join(this.outputDir, 'AGENTS.md');
78
+ await fsPromises.writeFile(agentsPath, agentsContent, 'utf-8');
79
+ result.files.push({ path: agentsPath, type: 'agents-md' });
80
+
81
+ // 渲染CLAUDE.md
82
+ const claudeContent = this.agentConfigRender.renderClaudeMd(decisionResult);
83
+ const claudePath = path.join(this.outputDir, 'CLAUDE.md');
84
+ await fsPromises.writeFile(claudePath, claudeContent, 'utf-8');
85
+ result.files.push({ path: claudePath, type: 'claude-md' });
86
+
87
+ } catch (e) {
88
+ result.error = `Agent配置渲染失败: ${e.message}`;
89
+ }
90
+
91
+ return result;
92
+ }
93
+
94
+ /**
95
+ * 渲染规则文件
96
+ */
97
+ async renderRules(decisionResult) {
98
+ const result = { files: [], error: null };
99
+
100
+ try {
101
+ // 确保.trae/rules目录存在
102
+ const rulesDir = path.join(this.outputDir, '.trae', 'rules');
103
+ await fsPromises.ensureDir(rulesDir);
104
+
105
+ // 按优先级渲染规则:L1 > L2 > L3
106
+ const rulesByLevel = this.groupRulesByLevel(decisionResult);
107
+
108
+ // 渲染L1规则
109
+ if (rulesByLevel.L1 && rulesByLevel.L1.length > 0) {
110
+ const l1Dir = path.join(rulesDir, 'L1');
111
+ await fsPromises.ensureDir(l1Dir);
112
+ for (const rule of rulesByLevel.L1) {
113
+ const filePath = path.join(l1Dir, `${rule.id}.yml`);
114
+ const content = this.ruleRender.renderRule(rule, 'L1');
115
+ await fsPromises.writeFile(filePath, content, 'utf-8');
116
+ result.files.push({ path: filePath, type: 'rule-L1', level: 'L1' });
117
+ }
118
+ }
119
+
120
+ // 渲染L2规则
121
+ if (rulesByLevel.L2 && rulesByLevel.L2.length > 0) {
122
+ const l2Dir = path.join(rulesDir, 'L2');
123
+ await fsPromises.ensureDir(l2Dir);
124
+ for (const rule of rulesByLevel.L2) {
125
+ const filePath = path.join(l2Dir, `${rule.id}.yml`);
126
+ const content = this.ruleRender.renderRule(rule, 'L2');
127
+ await fsPromises.writeFile(filePath, content, 'utf-8');
128
+ result.files.push({ path: filePath, type: 'rule-L2', level: 'L2' });
129
+ }
130
+ }
131
+
132
+ // 渲染L3规则
133
+ if (rulesByLevel.L3 && rulesByLevel.L3.length > 0) {
134
+ // 按模块分组创建子目录
135
+ const l3Dir = path.join(rulesDir, 'L3');
136
+ await fsPromises.ensureDir(l3Dir);
137
+
138
+ for (const rule of rulesByLevel.L3) {
139
+ const module = rule.module || 'default';
140
+ const moduleDir = path.join(l3Dir, module);
141
+ await fsPromises.ensureDir(moduleDir);
142
+
143
+ const filePath = path.join(moduleDir, `${rule.id}.yml`);
144
+ const content = this.ruleRender.renderRule(rule, 'L3');
145
+ await fsPromises.writeFile(filePath, content, 'utf-8');
146
+ result.files.push({ path: filePath, type: 'rule-L3', level: 'L3', module });
147
+ }
148
+ }
149
+
150
+ // 渲染custom规则
151
+ if (rulesByLevel.custom && rulesByLevel.custom.length > 0) {
152
+ const customDir = path.join(rulesDir, 'custom');
153
+ await fsPromises.ensureDir(customDir);
154
+ for (const rule of rulesByLevel.custom) {
155
+ const filePath = path.join(customDir, `${rule.id}.yml`);
156
+ const content = this.ruleRender.renderRule(rule, 'custom');
157
+ await fsPromises.writeFile(filePath, content, 'utf-8');
158
+ result.files.push({ path: filePath, type: 'rule-custom', level: 'custom' });
159
+ }
160
+ }
161
+
162
+ } catch (e) {
163
+ result.error = `规则渲染失败: ${e.message}`;
164
+ }
165
+
166
+ return result;
167
+ }
168
+
169
+ /**
170
+ * 按优先级分组规则
171
+ */
172
+ groupRulesByLevel(decisionResult) {
173
+ const rules = decisionResult.decision?.recommendedRules || [];
174
+ const groups = { L1: [], L2: [], L3: [], custom: [] };
175
+
176
+ for (const rule of rules) {
177
+ const level = rule.level || 'L3';
178
+ if (groups[level]) {
179
+ groups[level].push(rule);
180
+ } else {
181
+ groups.custom.push(rule);
182
+ }
183
+ }
184
+
185
+ return groups;
186
+ }
187
+
188
+ /**
189
+ * 获取渲染结果摘要
190
+ */
191
+ getSummary() {
192
+ return {
193
+ totalFiles: this.renderedFiles.length,
194
+ files: this.renderedFiles,
195
+ priority: 'AGENTS.md > CLAUDE.md > .trae/rules'
196
+ };
197
+ }
198
+ }
199
+
200
+ module.exports = { RenderCore };