@routerhub/agent-rules 1.3.11 → 1.4.1

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/AGENTS.base.md CHANGED
@@ -55,6 +55,7 @@
55
55
  - 不允许写 `class`,统一使用函数式编程。
56
56
  - 不要写 `try/catch`。
57
57
  - 代码注释统一使用中文编写。
58
+ - 每一行代码都必须有对应的中文注释,明确说明该行代码的作用。
58
59
  - 能复用现有函数或配置时,不要复制粘贴出第二份近似实现。
59
60
  - 编写 Go 代码时,优先使用值传递与局部变量生命周期控制,避免不必要的内存逃逸(如无必要不要返回局部变量指针、避免在热路径中产生额外堆分配)。
60
61
  - 编写代码需遵循 SOLID 原则,并结合场景合理应用设计模式优化可维护性与扩展性,避免过度设计。
@@ -70,6 +71,13 @@
70
71
 
71
72
  - 每次开发新功能时,尽可能将其封装为组件,方便后续在其它页面或场景中复用。
72
73
 
74
+ ## 需求文档前置规则
75
+
76
+ - 每次开始实现新需求前,必须先编写对应的需求说明 MD 文档。
77
+ - 需求文档统一存放在项目根目录的 `docs/` 文件夹下。
78
+ - 需求文档至少包含以下内容:需求目标、需求范围、功能要求、验收标准。
79
+ - 如存在补充信息,需在文档中增加“备注”章节说明。
80
+
73
81
  ## 依赖安装规范
74
82
 
75
83
  - 无论在 Docker 环境还是本地环境,安装和下载依赖都必须使用 `pnpm`,禁止使用 `npm install`、`yarn install` 等其它包管理器安装命令。
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  只做两件事:
4
4
 
5
- 1. 生成项目可用的 `AGENTS.md`
5
+ 1. 生成项目可用的 `AGENTS.md` 和 `.github/copilot-instructions.md`
6
6
  2. 自动监听 `AGENTS.private.md` 并同步
7
7
 
8
8
  完整中文说明见 `README.zh-CN.md`。
@@ -28,6 +28,6 @@ pnpm add -D concurrently @routerhub/agent-rules
28
28
  ```
29
29
 
30
30
  作用:
31
- - 监听 `AGENTS.private.md` 变更
32
- - 变更后自动重新同步 `AGENTS.md`
33
31
 
32
+ - 监听 `AGENTS.private.md` 变更
33
+ - 变更后自动重新同步 `AGENTS.md` 和 `.github/copilot-instructions.md`
package/README.zh-CN.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # @routerhub/agent-rules 中文说明
2
2
 
3
- `@routerhub/agent-rules` 用来把通用规则和项目私有规则合并成项目根目录下可直接使用的 `AGENTS.md`。
3
+ `@routerhub/agent-rules` 用来把通用规则和项目私有规则合并成项目中可直接使用的规则文件。
4
4
 
5
5
  它主要提供两类能力:
6
6
 
7
- 1. 生成项目可用的 `AGENTS.md`
7
+ 1. 生成项目可用的 `AGENTS.md` 和 `.github/copilot-instructions.md`
8
8
  2. 监听 `AGENTS.private.md` 变更并自动同步
9
9
 
10
10
  ## 安装
@@ -27,7 +27,7 @@ pnpm exec agent-rules init
27
27
 
28
28
  ## 同步规则
29
29
 
30
- 将基础规则与项目私有规则合并为 `AGENTS.md`:
30
+ 将基础规则与项目私有规则合并为 `AGENTS.md` 和 `.github/copilot-instructions.md`:
31
31
 
32
32
  ```bash
33
33
  pnpm exec agent-rules sync
@@ -41,7 +41,7 @@ pnpm exec agent-rules sync
41
41
 
42
42
  ## 监听模式
43
43
 
44
- 开发时建议通过监听模式自动保持 `AGENTS.md` 最新:
44
+ 开发时建议通过监听模式自动保持规则文件最新:
45
45
 
46
46
  ```json
47
47
  {
@@ -53,7 +53,7 @@ pnpm exec agent-rules sync
53
53
 
54
54
  监听模式会:
55
55
 
56
- - 先执行一次同步,生成最新的 `AGENTS.md`
56
+ - 先执行一次同步,生成最新的 `AGENTS.md` 和 `.github/copilot-instructions.md`
57
57
  - 持续监听项目根目录下的 `AGENTS.private.md`
58
58
  - 在文件变更后自动重新同步
59
59
 
@@ -61,7 +61,8 @@ pnpm exec agent-rules sync
61
61
 
62
62
  - `AGENTS.base.md`:规则包内置的通用基础规则
63
63
  - `AGENTS.private.md`:项目自己的私有规则
64
- - `AGENTS.md`:最终合并结果,供项目中的 Copilot 或 Agent 使用
64
+ - `AGENTS.md`:最终合并结果,供项目中的 Agent 使用
65
+ - `.github/copilot-instructions.md`:最终合并结果,供 GitHub Copilot 强制规则使用
65
66
 
66
67
  ## 推荐用法
67
68
 
@@ -76,4 +77,4 @@ pnpm exec agent-rules sync
76
77
 
77
78
  - 私有规则应只写项目特有的限制、接口地址、组件路径和业务规范
78
79
  - 通用规范应维护在规则包的 `AGENTS.base.md` 中
79
- - 若私有规则与基础规则冲突,以项目私有规则为准
80
+ - 若私有规则与基础规则冲突,以项目私有规则为准
package/merge.js CHANGED
@@ -12,200 +12,245 @@
12
12
  * watch 监听 AGENTS.private.md 变化并自动同步
13
13
  */
14
14
 
15
- const fs = require('fs')
16
- const path = require('path')
15
+ const fs = require("fs");
16
+ const path = require("path");
17
17
 
18
- const packageRoot = __dirname
19
- const currentRoot = process.cwd()
18
+ const packageRoot = __dirname;
19
+ const currentRoot = process.cwd();
20
20
 
21
- let syncTimer = null
22
- let isSyncing = false
23
- let pendingSync = false
21
+ let syncTimer = null;
22
+ let isSyncing = false;
23
+ let pendingSync = false;
24
24
 
25
25
  function getDefaultConfig() {
26
26
  return {
27
- output: path.join(currentRoot, 'AGENTS.md'),
28
- baseRulesPath: path.join(packageRoot, 'AGENTS.base.md'),
29
- privateRulesPath: path.join(currentRoot, 'AGENTS.private.md'),
27
+ output: path.join(currentRoot, "AGENTS.md"),
28
+ copilotOutput: path.join(currentRoot, ".github", "copilot-instructions.md"),
29
+ baseRulesPath: path.join(packageRoot, "AGENTS.base.md"),
30
+ privateRulesPath: path.join(currentRoot, "AGENTS.private.md"),
31
+ };
32
+ }
33
+
34
+ function ensureParentDir(filePath) {
35
+ const parentDir = path.dirname(filePath);
36
+ fs.mkdirSync(parentDir, { recursive: true });
37
+ }
38
+
39
+ function resolveOutputPaths(config) {
40
+ if (Array.isArray(config.outputs) && config.outputs.length > 0) {
41
+ return config.outputs;
30
42
  }
43
+
44
+ const defaultConfig = getDefaultConfig();
45
+ const output = config.output || defaultConfig.output;
46
+ const copilotOutput = config.copilotOutput || defaultConfig.copilotOutput;
47
+ return [output, copilotOutput];
31
48
  }
32
49
 
33
50
  function readFileIfExists(filePath) {
34
51
  try {
35
52
  if (fs.existsSync(filePath)) {
36
- return fs.readFileSync(filePath, 'utf-8')
53
+ return fs.readFileSync(filePath, "utf-8");
37
54
  }
38
55
  } catch (e) {
39
- console.warn(`无法读取文件 ${filePath}:`, e.message)
56
+ console.warn(`无法读取文件 ${filePath}:`, e.message);
40
57
  }
41
- return null
58
+ return null;
42
59
  }
43
60
 
44
61
  function mergeAgents(config) {
45
62
  const {
46
- output = getDefaultConfig().output,
47
63
  baseRulesPath = getDefaultConfig().baseRulesPath,
48
64
  privateRulesPath = getDefaultConfig().privateRulesPath,
49
- } = config
65
+ } = config;
66
+ const outputs = resolveOutputPaths(config);
50
67
 
51
- console.log('📦 开始合并规则文件...')
52
- console.log(` 基础规则: ${baseRulesPath}`)
53
- console.log(` 私有规则: ${privateRulesPath}`)
54
- console.log(` 输出文件: ${output}`)
68
+ console.log("📦 开始合并规则文件...");
69
+ console.log(` 基础规则: ${baseRulesPath}`);
70
+ console.log(` 私有规则: ${privateRulesPath}`);
71
+ console.log(` 输出文件: ${outputs.join(", ")}`);
55
72
 
56
- const baseRules = readFileIfExists(baseRulesPath)
73
+ const baseRules = readFileIfExists(baseRulesPath);
57
74
  if (!baseRules) {
58
- console.error(`❌ 基础规则文件不存在: ${baseRulesPath}`)
59
- process.exit(1)
75
+ console.error(`❌ 基础规则文件不存在: ${baseRulesPath}`);
76
+ process.exit(1);
60
77
  }
61
78
 
62
- const privateRules = readFileIfExists(privateRulesPath)
79
+ const privateRules = readFileIfExists(privateRulesPath);
63
80
 
64
- let merged = baseRules
81
+ let merged = baseRules;
65
82
 
66
83
  if (privateRules) {
67
- merged += '\n\n---\n\n'
68
- merged += '# 项目私有规则\n\n'
69
- merged += '以下规则仅适用于本项目,会覆盖基础规则中的相同部分。\n\n'
70
- merged += privateRules
84
+ merged += "\n\n---\n\n";
85
+ merged += "# 项目私有规则\n\n";
86
+ merged += "以下规则仅适用于本项目,会覆盖基础规则中的相同部分。\n\n";
87
+ merged += privateRules;
71
88
  }
72
89
 
73
- try {
74
- fs.writeFileSync(output, merged, 'utf-8')
75
- console.log(`✅ 规则已合并到 ${output}`)
76
- } catch (e) {
77
- console.error(`❌ 写入文件失败 ${output}:`, e.message)
78
- process.exit(1)
90
+ for (const outputPath of outputs) {
91
+ try {
92
+ ensureParentDir(outputPath);
93
+ fs.writeFileSync(outputPath, merged, "utf-8");
94
+ console.log(`✅ 规则已合并到 ${outputPath}`);
95
+ } catch (e) {
96
+ console.error(`❌ 写入文件失败 ${outputPath}:`, e.message);
97
+ process.exit(1);
98
+ }
79
99
  }
80
100
  }
81
101
 
82
102
  function initAgents() {
83
- const privateTemplatePath = path.join(packageRoot, 'AGENTS.private.example.md')
84
- const privateOutputPath = path.join(currentRoot, 'AGENTS.private.md')
103
+ const privateTemplatePath = path.join(
104
+ packageRoot,
105
+ "AGENTS.private.example.md",
106
+ );
107
+ const privateOutputPath = path.join(currentRoot, "AGENTS.private.md");
85
108
 
86
- mergeAgents(getDefaultConfig())
109
+ mergeAgents(getDefaultConfig());
87
110
 
88
111
  if (!fs.existsSync(privateOutputPath) && fs.existsSync(privateTemplatePath)) {
89
- fs.copyFileSync(privateTemplatePath, privateOutputPath)
90
- console.log(`✅ 已创建私有规则模板 ${privateOutputPath}`)
112
+ fs.copyFileSync(privateTemplatePath, privateOutputPath);
113
+ console.log(`✅ 已创建私有规则模板 ${privateOutputPath}`);
91
114
  }
92
115
 
93
- console.log('✅ 初始化完成,后续执行 agent-rules sync 即可刷新 AGENTS.md')
116
+ console.log(
117
+ "✅ 初始化完成,后续执行 agent-rules sync 即可刷新 AGENTS.md 和 .github/copilot-instructions.md",
118
+ );
94
119
  }
95
120
 
96
121
  function runSync(triggerSource) {
97
122
  if (isSyncing) {
98
- pendingSync = true
99
- return
123
+ pendingSync = true;
124
+ return;
100
125
  }
101
126
 
102
- isSyncing = true
103
- console.log(`[agent-rules:watch] ${triggerSource} -> 执行同步`)
127
+ isSyncing = true;
128
+ console.log(`[agent-rules:watch] ${triggerSource} -> 执行同步`);
104
129
 
105
- mergeAgents(getDefaultConfig())
130
+ mergeAgents(getDefaultConfig());
106
131
 
107
- isSyncing = false
132
+ isSyncing = false;
108
133
 
109
134
  if (pendingSync) {
110
- pendingSync = false
111
- runSync('检测到等待中的改动')
135
+ pendingSync = false;
136
+ runSync("检测到等待中的改动");
112
137
  }
113
138
  }
114
139
 
115
140
  function scheduleSync(triggerSource) {
116
141
  if (syncTimer) {
117
- clearTimeout(syncTimer)
142
+ clearTimeout(syncTimer);
118
143
  }
119
144
 
120
145
  syncTimer = setTimeout(() => {
121
- syncTimer = null
122
- runSync(triggerSource)
123
- }, 300)
146
+ syncTimer = null;
147
+ runSync(triggerSource);
148
+ }, 300);
124
149
  }
125
150
 
126
151
  function watchAgents() {
127
- const privateRulesName = 'AGENTS.private.md'
128
- const privateRulesPath = path.join(currentRoot, privateRulesName)
129
- const privateTemplatePath = path.join(packageRoot, 'AGENTS.private.example.md')
152
+ const privateRulesName = "AGENTS.private.md";
153
+ const privateRulesPath = path.join(currentRoot, privateRulesName);
154
+ const privateTemplatePath = path.join(
155
+ packageRoot,
156
+ "AGENTS.private.example.md",
157
+ );
130
158
 
131
159
  // 不存在则从模板创建
132
160
  if (!fs.existsSync(privateRulesPath) && fs.existsSync(privateTemplatePath)) {
133
- fs.copyFileSync(privateTemplatePath, privateRulesPath)
134
- console.log(`[agent-rules:watch] 已创建 ${privateRulesPath},请按项目情况修改`)
161
+ fs.copyFileSync(privateTemplatePath, privateRulesPath);
162
+ console.log(
163
+ `[agent-rules:watch] 已创建 ${privateRulesPath},请按项目情况修改`,
164
+ );
135
165
  }
136
166
 
137
- runSync('启动监听')
167
+ runSync("启动监听");
138
168
 
139
169
  fs.watch(currentRoot, (eventType, fileName) => {
140
- const normalizedFileName = typeof fileName === 'string' ? fileName : ''
170
+ const normalizedFileName = typeof fileName === "string" ? fileName : "";
141
171
  if (normalizedFileName !== privateRulesName) {
142
- return
172
+ return;
143
173
  }
144
174
 
145
- scheduleSync(`${privateRulesName} 已变更`)
146
- })
175
+ scheduleSync(`${privateRulesName} 已变更`);
176
+ });
147
177
 
148
- console.log(`[agent-rules:watch] 正在监听 ${privateRulesPath}`)
178
+ console.log(`[agent-rules:watch] 正在监听 ${privateRulesPath}`);
149
179
 
150
- process.on('SIGINT', () => {
151
- process.exit(0)
152
- })
180
+ process.on("SIGINT", () => {
181
+ process.exit(0);
182
+ });
153
183
 
154
- process.on('SIGTERM', () => {
155
- process.exit(0)
156
- })
184
+ process.on("SIGTERM", () => {
185
+ process.exit(0);
186
+ });
157
187
  }
158
188
 
159
189
  function main() {
160
- const command = process.argv[2]
161
-
162
- if (command === '--help' || command === '-h' || command === 'help') {
163
- console.log('agent-rules 使用说明:')
164
- console.log(' agent-rules 初始化 AGENTS.md,并在缺失时创建 AGENTS.private.md 模板')
165
- console.log(' agent-rules init 初始化 AGENTS.md,并在缺失时创建 AGENTS.private.md 模板')
166
- console.log(' agent-rules sync 重新生成项目根目录下的 AGENTS.md')
167
- console.log(' agent-rules watch 监听 AGENTS.private.md,变更后自动同步 AGENTS.md')
168
- console.log(' agent-rules help 查看帮助')
169
- return
190
+ const command = process.argv[2];
191
+
192
+ if (command === "--help" || command === "-h" || command === "help") {
193
+ console.log("agent-rules 使用说明:");
194
+ console.log(
195
+ " agent-rules 初始化 AGENTS.md 与 .github/copilot-instructions.md,并在缺失时创建 AGENTS.private.md 模板",
196
+ );
197
+ console.log(
198
+ " agent-rules init 初始化 AGENTS.md 与 .github/copilot-instructions.md,并在缺失时创建 AGENTS.private.md 模板",
199
+ );
200
+ console.log(
201
+ " agent-rules sync 重新生成项目根目录下的 AGENTS.md 与 .github/copilot-instructions.md",
202
+ );
203
+ console.log(
204
+ " agent-rules watch 监听 AGENTS.private.md,变更后自动同步规则文件",
205
+ );
206
+ console.log(" agent-rules help 查看帮助");
207
+ return;
170
208
  }
171
209
 
172
- if (!command || command === 'init') {
173
- initAgents()
174
- return
210
+ if (!command || command === "init") {
211
+ initAgents();
212
+ return;
175
213
  }
176
214
 
177
- if (command === 'sync') {
178
- mergeAgents(getDefaultConfig())
179
- return
215
+ if (command === "sync") {
216
+ mergeAgents(getDefaultConfig());
217
+ return;
180
218
  }
181
219
 
182
- if (command === 'watch') {
183
- watchAgents()
184
- return
220
+ if (command === "watch") {
221
+ watchAgents();
222
+ return;
185
223
  }
186
224
 
187
- const configPath = command
225
+ const configPath = command;
188
226
 
189
- let config = {}
227
+ let config = {};
190
228
 
191
229
  if (fs.existsSync(configPath)) {
192
230
  try {
193
- const configContent = fs.readFileSync(configPath, 'utf-8')
194
- config = JSON.parse(configContent)
195
- console.log(`📄 已加载配置文件: ${configPath}`)
231
+ const configContent = fs.readFileSync(configPath, "utf-8");
232
+ config = JSON.parse(configContent);
233
+ console.log(`📄 已加载配置文件: ${configPath}`);
196
234
  } catch (e) {
197
- console.error(`❌ 配置文件解析失败 ${configPath}:`, e.message)
198
- process.exit(1)
235
+ console.error(`❌ 配置文件解析失败 ${configPath}:`, e.message);
236
+ process.exit(1);
199
237
  }
200
238
  } else {
201
- console.log(`⚠️ 配置文件不存在 ${configPath},使用默认配置`)
239
+ console.log(`⚠️ 配置文件不存在 ${configPath},使用默认配置`);
202
240
  }
203
241
 
204
- mergeAgents(config)
242
+ mergeAgents(config);
205
243
  }
206
244
 
207
245
  if (require.main === module) {
208
- main()
246
+ main();
209
247
  }
210
248
 
211
- module.exports = { mergeAgents, readFileIfExists, initAgents, getDefaultConfig, watchAgents }
249
+ module.exports = {
250
+ mergeAgents,
251
+ readFileIfExists,
252
+ initAgents,
253
+ getDefaultConfig,
254
+ watchAgents,
255
+ resolveOutputPaths,
256
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routerhub/agent-rules",
3
- "version": "1.3.11",
3
+ "version": "1.4.1",
4
4
  "description": "Shared Copilot agent rules and guidelines for RouterHub projects",
5
5
  "main": "AGENTS.base.md",
6
6
  "bin": {