@devflow-tools/plugin-git 0.12.6 → 0.13.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/dist/analyzers/analyze-repo.d.ts +20 -0
- package/dist/analyzers/analyze-repo.d.ts.map +1 -0
- package/dist/analyzers/analyze-repo.js +39 -0
- package/dist/analyzers/analyze-repo.js.map +1 -0
- package/dist/analyzers/types.d.ts +5 -0
- package/dist/analyzers/types.d.ts.map +1 -0
- package/dist/analyzers/types.js +2 -0
- package/dist/analyzers/types.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1133 -0
- package/dist/index.js.map +1 -0
- package/package.json +3 -3
package/dist/index.js
ADDED
|
@@ -0,0 +1,1133 @@
|
|
|
1
|
+
const structuredOutputSchema = {
|
|
2
|
+
type: "object",
|
|
3
|
+
additionalProperties: true,
|
|
4
|
+
};
|
|
5
|
+
const readOnlyAnnotations = {
|
|
6
|
+
readOnlyHint: true,
|
|
7
|
+
idempotentHint: true,
|
|
8
|
+
};
|
|
9
|
+
export const gitPlugin = {
|
|
10
|
+
meta: {
|
|
11
|
+
name: "git",
|
|
12
|
+
version: "0.1.0",
|
|
13
|
+
description: "Git 专家 — 提交规范、分支审查、Changelog 生成、冲突解决",
|
|
14
|
+
icon: "🔀",
|
|
15
|
+
tags: ["git", "version-control", "ci", "changelog"],
|
|
16
|
+
},
|
|
17
|
+
knowledge: {
|
|
18
|
+
sources: [
|
|
19
|
+
{
|
|
20
|
+
name: "conventional-commits",
|
|
21
|
+
urls: ["https://www.conventionalcommits.org/en/v1.0.0/"],
|
|
22
|
+
pluginName: "git",
|
|
23
|
+
version: "1.0.0",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "git-scm-docs",
|
|
27
|
+
urls: ["https://git-scm.com/docs", "https://git-scm.com/book/en/v2"],
|
|
28
|
+
pluginName: "git",
|
|
29
|
+
version: "2.45.0",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
memory: {
|
|
34
|
+
project: {
|
|
35
|
+
stack: ["Git", "Conventional Commits", "Semantic Release"],
|
|
36
|
+
conventions: [
|
|
37
|
+
{ key: "commits", value: "使用 Conventional Commits 规范(type(scope): description)", source: "manual", confidence: 0.9 },
|
|
38
|
+
{ key: "branch", value: "GitFlow 分支策略(main/develop/feature/hotfix)", source: "manual", confidence: 0.8 },
|
|
39
|
+
{ key: "pr", value: "每个 PR 必须关联 Issue 并有清晰描述", source: "manual", confidence: 0.85 },
|
|
40
|
+
{ key: "changelog", value: "使用语义化版本自动生成 Changelog", source: "manual", confidence: 0.7 },
|
|
41
|
+
{ key: "review", value: "所有代码合并前必须经过 Code Review", source: "manual", confidence: 0.95 },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
global: [
|
|
45
|
+
{
|
|
46
|
+
id: "git:conventional-commits",
|
|
47
|
+
source: "git",
|
|
48
|
+
title: "Conventional Commits 规范",
|
|
49
|
+
content: "格式:<type>(<scope>): <description>。类型:feat、fix、docs、style、refactor、test、chore、perf、ci。BREAKING CHANGE 在 body 或 footer 标注。",
|
|
50
|
+
embedding: [],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: "git:branch-strategy",
|
|
54
|
+
source: "git",
|
|
55
|
+
title: "GitFlow 分支策略",
|
|
56
|
+
content: "main 保持稳定可发布。develop 为开发主线。feature/ 为功能分支。hotfix/ 为紧急修复。功能分支从 develop 拉出,合并回 develop。",
|
|
57
|
+
embedding: [],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: "git:commit-message-best-practice",
|
|
61
|
+
source: "git",
|
|
62
|
+
title: "提交信息最佳实践",
|
|
63
|
+
content: "主题行不超过 50 字符,祈使语气。正文每行不超过 72 字符。每个提交是逻辑上独立的变更。描述做了什么以及为什么。",
|
|
64
|
+
embedding: [],
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "git:rebase-vs-merge",
|
|
68
|
+
source: "git",
|
|
69
|
+
title: "Rebase vs Merge 策略",
|
|
70
|
+
content: "功能分支推荐 rebase 保持历史线性。公共分支(main、develop)禁止 rebase,只使用 merge。git pull --rebase 拉取远程更新。冲突解决后 git rebase --continue。",
|
|
71
|
+
embedding: [],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: "git:conflict-resolution",
|
|
75
|
+
source: "git",
|
|
76
|
+
title: "冲突解决策略",
|
|
77
|
+
content: "使用 git mergetool 或手动编辑解决冲突。理解 <<<<<<< ======= >>>>>>> 标记。解决后 git add 标记已解决。复杂冲突考虑 cherry-pick 替代 merge。",
|
|
78
|
+
embedding: [],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
workflow: {
|
|
83
|
+
steps: [],
|
|
84
|
+
templates: [
|
|
85
|
+
// ── 规范化提交 ──
|
|
86
|
+
{
|
|
87
|
+
name: "commit",
|
|
88
|
+
description: "规范化提交:分支检查 → 变更分析 → Conventional Commits 生成",
|
|
89
|
+
version: "2.0.0",
|
|
90
|
+
steps: [
|
|
91
|
+
{
|
|
92
|
+
id: "check-branch",
|
|
93
|
+
title: "检查当前分支命名",
|
|
94
|
+
instruction: [
|
|
95
|
+
"## 检查当前分支命名是否合规",
|
|
96
|
+
"",
|
|
97
|
+
"验证当前分支是否符合 GitFlow 命名规范。",
|
|
98
|
+
"",
|
|
99
|
+
"**执行动作**:",
|
|
100
|
+
"1. 获取当前分支名:",
|
|
101
|
+
" ```bash",
|
|
102
|
+
" git branch --show-current",
|
|
103
|
+
" ```",
|
|
104
|
+
"2. 检查是否符合以下 GitFlow 命名规范之一:",
|
|
105
|
+
" - `main` / `master` — 稳定发布分支",
|
|
106
|
+
" - `develop` — 开发主线",
|
|
107
|
+
" - `feature/<description>` — 功能分支(如 `feature/user-auth`)",
|
|
108
|
+
" - `fix/<description>` — 修复分支",
|
|
109
|
+
" - `hotfix/<description>` — 紧急修复分支",
|
|
110
|
+
" - `release/<version>` — 发布准备分支(如 `release/1.2.0`)",
|
|
111
|
+
" - `chore/<description>` — 杂务分支",
|
|
112
|
+
"3. 命名规则:",
|
|
113
|
+
" - 使用小写字母和短横线(kebab-case)",
|
|
114
|
+
" - 不能包含空格、下划线或大写字母",
|
|
115
|
+
" - `<description>` 部分应简短有语义",
|
|
116
|
+
"4. 检查是否处于 detached HEAD 状态:",
|
|
117
|
+
" ```bash",
|
|
118
|
+
" git status | head -1",
|
|
119
|
+
" ```",
|
|
120
|
+
"",
|
|
121
|
+
"**产出格式**:",
|
|
122
|
+
"```",
|
|
123
|
+
"current_branch: feature/user-auth",
|
|
124
|
+
"naming_compliant: true",
|
|
125
|
+
"branch_type: feature",
|
|
126
|
+
"issues: []",
|
|
127
|
+
"```",
|
|
128
|
+
].join("\n"),
|
|
129
|
+
suggestedTools: ["Bash"],
|
|
130
|
+
output: "当前分支名、命名合规状态、分支类型",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "analyze-changes",
|
|
134
|
+
title: "分析变更内容",
|
|
135
|
+
instruction: [
|
|
136
|
+
"## 分析变更内容(新增/修改/删除 + 文件类型)",
|
|
137
|
+
"",
|
|
138
|
+
"全面分析工作区的所有变更,为生成提交信息提供依据。",
|
|
139
|
+
"",
|
|
140
|
+
"**执行动作**:",
|
|
141
|
+
"1. 查看工作区状态:",
|
|
142
|
+
" ```bash",
|
|
143
|
+
" git status --short",
|
|
144
|
+
" ```",
|
|
145
|
+
"2. 查看变更统计(插入/删除行数):",
|
|
146
|
+
" ```bash",
|
|
147
|
+
" git diff --stat",
|
|
148
|
+
" git diff --cached --stat",
|
|
149
|
+
" ```",
|
|
150
|
+
"3. 分类所有变更文件:",
|
|
151
|
+
" - **新增(A)**:新文件",
|
|
152
|
+
" - **修改(M)**:已修改文件",
|
|
153
|
+
" - **删除(D)**:已删除文件",
|
|
154
|
+
" - **重命名(R)**:重命名文件",
|
|
155
|
+
"4. 按文件类型分组:",
|
|
156
|
+
" ```bash",
|
|
157
|
+
" git diff --name-only && git diff --cached --name-only",
|
|
158
|
+
" ```",
|
|
159
|
+
" - 源代码:`.ts` `.tsx` `.js` `.jsx` `.vue`",
|
|
160
|
+
" - 样式:`.css` `.scss` `.less`",
|
|
161
|
+
" - 测试:`.test.ts` `.spec.ts`",
|
|
162
|
+
" - 文档:`.md` `.mdx`",
|
|
163
|
+
" - 配置:`.json` `.yaml` `.toml`",
|
|
164
|
+
"5. 查看具体 diff 内容(重点关注逻辑变更):",
|
|
165
|
+
" ```bash",
|
|
166
|
+
" git diff | head -200",
|
|
167
|
+
" ```",
|
|
168
|
+
"6. 检查是否存在未跟踪的新文件:",
|
|
169
|
+
" ```bash",
|
|
170
|
+
" git ls-files --others --exclude-standard",
|
|
171
|
+
" ```",
|
|
172
|
+
"",
|
|
173
|
+
"**产出格式**:",
|
|
174
|
+
"```",
|
|
175
|
+
"files_changed: 8",
|
|
176
|
+
"insertions: 120",
|
|
177
|
+
"deletions: 30",
|
|
178
|
+
"categories: { added: ['src/utils/format.ts'], modified: ['src/App.tsx'], deleted: [] }",
|
|
179
|
+
"file_types: { source: 3, test: 2, style: 1, config: 1, docs: 1 }",
|
|
180
|
+
"change_summary: 'added format utility, updated App to use it, added tests'",
|
|
181
|
+
"```",
|
|
182
|
+
].join("\n"),
|
|
183
|
+
suggestedTools: ["Bash", "Read"],
|
|
184
|
+
output: "变更文件清单、文件类型分布、变更摘要",
|
|
185
|
+
depends: ["check-branch"],
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: "detect-scope",
|
|
189
|
+
title: "自动检测 scope",
|
|
190
|
+
instruction: [
|
|
191
|
+
"## 自动检测 scope(基于变更文件路径)",
|
|
192
|
+
"",
|
|
193
|
+
"根据变更文件的路径,自动推断 Conventional Commits 的 scope 字段。",
|
|
194
|
+
"",
|
|
195
|
+
"**执行动作**:",
|
|
196
|
+
"1. 从 `analyze-changes` 获取变更文件列表",
|
|
197
|
+
"2. 提取公共目录前缀作为 scope 候选:",
|
|
198
|
+
" - `src/components/Button.tsx` → scope: `components` 或 `button`",
|
|
199
|
+
" - `src/pages/home/index.tsx` → scope: `home` 或 `pages`",
|
|
200
|
+
" - `src/utils/format.ts` → scope: `utils`",
|
|
201
|
+
" - `src/hooks/useAuth.ts` → scope: `hooks` 或 `auth`",
|
|
202
|
+
" - `packages/sdk/src/types.ts` → scope: `sdk`",
|
|
203
|
+
" - `.github/workflows/ci.yml` → scope: `ci`",
|
|
204
|
+
"3. 推断规则(优先级从高到低):",
|
|
205
|
+
" - 如果所有变更集中在单一模块目录 → 使用该模块名",
|
|
206
|
+
" - 如果是跨模块的公共变更(如 utils、types) → 使用公共目录名",
|
|
207
|
+
" - 如果变更分散在多个不相关模块 → scope 留空",
|
|
208
|
+
"4. 对于 monorepo,优先使用 package 名作为 scope:",
|
|
209
|
+
" ```bash",
|
|
210
|
+
" git diff --name-only | cut -d'/' -f1-2 | sort -u",
|
|
211
|
+
" ```",
|
|
212
|
+
"5. scope 应为简短的小写名词,不超过 20 字符",
|
|
213
|
+
"",
|
|
214
|
+
"**产出格式**:",
|
|
215
|
+
"```",
|
|
216
|
+
"detected_scope: utils",
|
|
217
|
+
"scope_reason: 'all changes are in src/utils/ directory'",
|
|
218
|
+
"changed_modules: ['src/utils']",
|
|
219
|
+
"alternative_scopes: ['format']",
|
|
220
|
+
"```",
|
|
221
|
+
].join("\n"),
|
|
222
|
+
suggestedTools: ["Bash"],
|
|
223
|
+
output: "检测到的 scope 值、推断理由、备选 scope",
|
|
224
|
+
depends: ["analyze-changes"],
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
id: "generate-message",
|
|
228
|
+
title: "生成 Conventional Commits 提交信息",
|
|
229
|
+
instruction: [
|
|
230
|
+
"## 生成 Conventional Commits 格式提交信息",
|
|
231
|
+
"",
|
|
232
|
+
"根据变更内容和 scope,生成符合 Conventional Commits 规范的提交信息。",
|
|
233
|
+
"",
|
|
234
|
+
"**执行动作**:",
|
|
235
|
+
"1. 确定提交类型(type):",
|
|
236
|
+
" - `feat` — 新功能(对用户可见)",
|
|
237
|
+
" - `fix` — 修复 Bug",
|
|
238
|
+
" - `docs` — 仅文档变更",
|
|
239
|
+
" - `style` — 代码格式(不影响逻辑)",
|
|
240
|
+
" - `refactor` — 重构(既非 feat 也非 fix)",
|
|
241
|
+
" - `perf` — 性能优化",
|
|
242
|
+
" - `test` — 添加或修改测试",
|
|
243
|
+
" - `chore` — 构建/工具/依赖变更",
|
|
244
|
+
" - `ci` — CI 配置变更",
|
|
245
|
+
" - `revert` — 回退提交",
|
|
246
|
+
"2. 组装提交信息格式:",
|
|
247
|
+
" ```",
|
|
248
|
+
" <type>(<scope>): <subject>",
|
|
249
|
+
" ",
|
|
250
|
+
" <body>",
|
|
251
|
+
" ",
|
|
252
|
+
" <footer>",
|
|
253
|
+
" ```",
|
|
254
|
+
"3. 主题行(subject)规则:",
|
|
255
|
+
" - 使用祈使语气(\"add\" 而非 \"added\")",
|
|
256
|
+
" - 首字母不大写",
|
|
257
|
+
" - 不以句号结尾",
|
|
258
|
+
" - 不超过 50 字符",
|
|
259
|
+
"4. 正文(body):",
|
|
260
|
+
" - 描述 **做了什么** 和 **为什么**",
|
|
261
|
+
" - 每行不超过 72 字符",
|
|
262
|
+
" - 多个逻辑变更时分点列出",
|
|
263
|
+
"5. 脚注(footer):",
|
|
264
|
+
" - `BREAKING CHANGE: <description>` — 不兼容变更",
|
|
265
|
+
" - `Closes #123` — 关联 Issue",
|
|
266
|
+
" - `Refs #456` — 关联其他引用",
|
|
267
|
+
"6. 示例:",
|
|
268
|
+
" ```",
|
|
269
|
+
" feat(auth): add OAuth2 login flow",
|
|
270
|
+
" ",
|
|
271
|
+
" Implement OAuth2 authorization code flow with PKCE.",
|
|
272
|
+
" Supports Google and GitHub providers.",
|
|
273
|
+
" ",
|
|
274
|
+
" Closes #42",
|
|
275
|
+
" ```",
|
|
276
|
+
"",
|
|
277
|
+
"**产出格式**:",
|
|
278
|
+
"```",
|
|
279
|
+
"commit_type: feat",
|
|
280
|
+
"commit_scope: utils",
|
|
281
|
+
"commit_subject: add format utility for date and currency",
|
|
282
|
+
"commit_body: 'Centralize formatting logic to avoid duplication across components.'",
|
|
283
|
+
"commit_footer: ''",
|
|
284
|
+
"full_message: '<type>(<scope>): <subject>\\n\\n<body>'",
|
|
285
|
+
"breaking_change: false",
|
|
286
|
+
"```",
|
|
287
|
+
].join("\n"),
|
|
288
|
+
suggestedTools: ["Read"],
|
|
289
|
+
output: "完整的 Conventional Commits 格式提交信息",
|
|
290
|
+
depends: ["analyze-changes", "detect-scope"],
|
|
291
|
+
},
|
|
292
|
+
{ id: "review-message", stepTemplate: "human-review", depends: ["generate-message"] },
|
|
293
|
+
{
|
|
294
|
+
id: "run-precommit",
|
|
295
|
+
title: "运行 pre-commit hooks",
|
|
296
|
+
instruction: [
|
|
297
|
+
"## 运行 pre-commit hooks(lint + test)",
|
|
298
|
+
"",
|
|
299
|
+
"执行项目的 pre-commit 钩子,确保代码质量达标。",
|
|
300
|
+
"",
|
|
301
|
+
"**执行动作**:",
|
|
302
|
+
"1. 先暂存所有变更文件:",
|
|
303
|
+
" ```bash",
|
|
304
|
+
" git add -A",
|
|
305
|
+
" ```",
|
|
306
|
+
"2. 检查项目是否使用 husky + lint-staged:",
|
|
307
|
+
" ```bash",
|
|
308
|
+
" ls .husky/ 2>/dev/null && cat .husky/pre-commit 2>/dev/null",
|
|
309
|
+
" cat package.json | grep -A5 'lint-staged' 2>/dev/null",
|
|
310
|
+
" ```",
|
|
311
|
+
"3. 如果有 husky pre-commit hook,直接运行:",
|
|
312
|
+
" ```bash",
|
|
313
|
+
" # 方式 1:通过 husky 运行(模拟 git commit 触发)",
|
|
314
|
+
" .husky/pre-commit 2>&1",
|
|
315
|
+
" ```",
|
|
316
|
+
"4. 如果没有 husky,手动执行常见 pre-commit 检查:",
|
|
317
|
+
" ```bash",
|
|
318
|
+
" # ESLint 检查变更文件",
|
|
319
|
+
" npx eslint $(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.(ts|tsx|js|jsx)$') 2>&1 | tail -20",
|
|
320
|
+
"",
|
|
321
|
+
" # TypeScript 类型检查",
|
|
322
|
+
" npx tsc --noEmit 2>&1 | tail -20",
|
|
323
|
+
"",
|
|
324
|
+
" # 运行相关测试",
|
|
325
|
+
" npm test -- --related $(git diff --cached --name-only) 2>&1 | tail -20",
|
|
326
|
+
" ```",
|
|
327
|
+
"5. 如果有 Prettier,检查格式:",
|
|
328
|
+
" ```bash",
|
|
329
|
+
" npx prettier --check $(git diff --cached --name-only --diff-filter=ACM) 2>&1 | tail -10",
|
|
330
|
+
" ```",
|
|
331
|
+
"6. 如果任一检查失败,列出具体问题并停止,等待修复",
|
|
332
|
+
"",
|
|
333
|
+
"**产出格式**:",
|
|
334
|
+
"```",
|
|
335
|
+
"precommit_hooks: ['lint-staged', 'tsc --noEmit']",
|
|
336
|
+
"lint_result: passed | failed",
|
|
337
|
+
"type_check_result: passed | failed",
|
|
338
|
+
"test_result: passed | failed",
|
|
339
|
+
"format_check_result: passed | failed",
|
|
340
|
+
"overall: passed | failed",
|
|
341
|
+
"errors: [{ hook: 'eslint', message: '...' }]",
|
|
342
|
+
"```",
|
|
343
|
+
].join("\n"),
|
|
344
|
+
suggestedTools: ["Bash"],
|
|
345
|
+
output: "pre-commit 各钩子检查结果(lint、类型检查、测试、格式)",
|
|
346
|
+
depends: ["review-message"],
|
|
347
|
+
},
|
|
348
|
+
{ id: "commit", stepTemplate: "git-commit", depends: ["run-precommit"] },
|
|
349
|
+
],
|
|
350
|
+
triggers: [{ type: "cli", command: "commit" }],
|
|
351
|
+
},
|
|
352
|
+
// ── 发布流程 ──
|
|
353
|
+
{
|
|
354
|
+
name: "release",
|
|
355
|
+
description: "发布流程:版本号确定 → Changelog 生成 → Tag 创建",
|
|
356
|
+
version: "2.0.0",
|
|
357
|
+
steps: [
|
|
358
|
+
{
|
|
359
|
+
id: "analyze-commits",
|
|
360
|
+
title: "分析自上次 release 以来的所有提交",
|
|
361
|
+
instruction: [
|
|
362
|
+
"## 分析自上次 release 以来的所有提交",
|
|
363
|
+
"",
|
|
364
|
+
"获取自上一个 Git tag 以来的所有提交,按 Conventional Commits 类型分类。",
|
|
365
|
+
"",
|
|
366
|
+
"**执行动作**:",
|
|
367
|
+
"1. 查找上一个 tag(即上一次发布版本):",
|
|
368
|
+
" ```bash",
|
|
369
|
+
" git describe --tags --abbrev=0 2>/dev/null || echo 'no previous tag'",
|
|
370
|
+
" ```",
|
|
371
|
+
"2. 获取自上一个 tag 以来的所有提交:",
|
|
372
|
+
" ```bash",
|
|
373
|
+
" LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null)",
|
|
374
|
+
" if [ -n \"$LAST_TAG\" ]; then",
|
|
375
|
+
" git log \"$LAST_TAG..HEAD\" --oneline --no-merges",
|
|
376
|
+
" else",
|
|
377
|
+
" git log --oneline --no-merges",
|
|
378
|
+
" fi",
|
|
379
|
+
" ```",
|
|
380
|
+
"3. 按 Conventional Commits 类型分类统计:",
|
|
381
|
+
" ```bash",
|
|
382
|
+
" git log \"$LAST_TAG..HEAD\" --oneline --no-merges | grep -cE '^[a-f0-9]+ feat'",
|
|
383
|
+
" git log \"$LAST_TAG..HEAD\" --oneline --no-merges | grep -cE '^[a-f0-9]+ fix'",
|
|
384
|
+
" git log \"$LAST_TAG..HEAD\" --oneline --no-merges | grep -cE '^[a-f0-9]+ (docs|style|refactor|test|chore|perf|ci)'",
|
|
385
|
+
" ```",
|
|
386
|
+
"4. 检查是否有 BREAKING CHANGE:",
|
|
387
|
+
" ```bash",
|
|
388
|
+
" git log \"$LAST_TAG..HEAD\" --oneline --no-merges | grep -iE 'BREAKING CHANGE|!:'",
|
|
389
|
+
" ```",
|
|
390
|
+
"5. 获取每个提交的完整信息(type + scope + subject):",
|
|
391
|
+
" ```bash",
|
|
392
|
+
" git log \"$LAST_TAG..HEAD\" --format='%h %s' --no-merges",
|
|
393
|
+
" ```",
|
|
394
|
+
"6. 统计提交总数、作者数量、时间跨度:",
|
|
395
|
+
" ```bash",
|
|
396
|
+
" git log \"$LAST_TAG..HEAD\" --format='%an' --no-merges | sort -u | wc -l",
|
|
397
|
+
" git log \"$LAST_TAG..HEAD\" --format='%ai' --no-merges | head -1",
|
|
398
|
+
" git log \"$LAST_TAG..HEAD\" --format='%ai' --no-merges | tail -1",
|
|
399
|
+
" ```",
|
|
400
|
+
"",
|
|
401
|
+
"**产出格式**:",
|
|
402
|
+
"```",
|
|
403
|
+
"last_tag: v1.2.3",
|
|
404
|
+
"total_commits: 25",
|
|
405
|
+
"authors: 4",
|
|
406
|
+
"date_range: '2024-01-15 to 2024-02-20'",
|
|
407
|
+
"commits_by_type: { feat: 8, fix: 10, docs: 3, refactor: 2, test: 1, chore: 1 }",
|
|
408
|
+
"breaking_changes: []",
|
|
409
|
+
"commit_list: [{ hash: 'abc1234', type: 'feat', scope: 'auth', subject: 'add OAuth login' }]",
|
|
410
|
+
"```",
|
|
411
|
+
].join("\n"),
|
|
412
|
+
suggestedTools: ["Bash"],
|
|
413
|
+
output: "自上次发布以来的提交清单、类型分布、BREAKING CHANGE 检测结果",
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
id: "determine-version",
|
|
417
|
+
title: "根据提交类型确定版本号",
|
|
418
|
+
instruction: [
|
|
419
|
+
"## 根据提交类型确定版本号(major/minor/patch)",
|
|
420
|
+
"",
|
|
421
|
+
"基于 Conventional Commits 和语义化版本规范,确定下一个发布版本号。",
|
|
422
|
+
"",
|
|
423
|
+
"**执行动作**:",
|
|
424
|
+
"1. 获取当前版本号:",
|
|
425
|
+
" ```bash",
|
|
426
|
+
" git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//'",
|
|
427
|
+
" # 或从 package.json 读取",
|
|
428
|
+
" node -e \"console.log(require('./package.json').version)\"",
|
|
429
|
+
" ```",
|
|
430
|
+
"2. 语义化版本升级规则:",
|
|
431
|
+
" - **MAJOR**(x.0.0):存在 `BREAKING CHANGE` 或不兼容的 API 变更",
|
|
432
|
+
" - **MINOR**(x.y.0):新增 `feat` 类型提交(向后兼容的新功能)",
|
|
433
|
+
" - **PATCH**(x.y.z):仅有 `fix` 类型提交(向后兼容的 Bug 修复)",
|
|
434
|
+
"3. 判定逻辑(优先级从高到低):",
|
|
435
|
+
" - 如果 `analyze-commits` 检测到 BREAKING CHANGE → bump **MAJOR**",
|
|
436
|
+
" - 如果有 `feat` 提交 → bump **MINOR**",
|
|
437
|
+
" - 如果仅有 `fix`/`perf` 提交 → bump **PATCH**",
|
|
438
|
+
" - 如果仅有 `docs`/`style`/`refactor`/`test`/`chore` → 通常不发布,或 bump **PATCH**",
|
|
439
|
+
"4. 计算新版本:",
|
|
440
|
+
" ```bash",
|
|
441
|
+
" # 假设当前版本 1.2.3,bump MINOR",
|
|
442
|
+
" echo '1.2.3' | awk -F. '{printf \"%d.%d.0\", $1, $2+1}'",
|
|
443
|
+
" # 输出: 1.3.0",
|
|
444
|
+
" ```",
|
|
445
|
+
"5. 如果是 0.x.x 版本,规则略有不同:",
|
|
446
|
+
" - 0.x.x 阶段,MAJOR bump 通常是 MINOR bump",
|
|
447
|
+
" - BREAKING CHANGE 在 0.x.x 中可以只 bump MINOR",
|
|
448
|
+
"",
|
|
449
|
+
"**产出格式**:",
|
|
450
|
+
"```",
|
|
451
|
+
"current_version: 1.2.3",
|
|
452
|
+
"bump_type: minor",
|
|
453
|
+
"bump_reason: '8 feat commits detected, no breaking changes'",
|
|
454
|
+
"new_version: 1.3.0",
|
|
455
|
+
"is_prerelease: false",
|
|
456
|
+
"```",
|
|
457
|
+
].join("\n"),
|
|
458
|
+
suggestedTools: ["Bash"],
|
|
459
|
+
output: "当前版本号、bump 类型、新版本号",
|
|
460
|
+
depends: ["analyze-commits"],
|
|
461
|
+
},
|
|
462
|
+
{ id: "generate-changelog", stepTemplate: "generate-report", depends: ["analyze-commits"] },
|
|
463
|
+
{ id: "review-changelog", stepTemplate: "human-review", depends: ["generate-changelog"] },
|
|
464
|
+
{
|
|
465
|
+
id: "bump-version",
|
|
466
|
+
title: "更新 package.json version 字段",
|
|
467
|
+
instruction: [
|
|
468
|
+
"## 更新 package.json version 字段",
|
|
469
|
+
"",
|
|
470
|
+
"将新版本号写入项目配置文件。",
|
|
471
|
+
"",
|
|
472
|
+
"**执行动作**:",
|
|
473
|
+
"1. 使用 `npm version` 命令自动更新版本号(推荐):",
|
|
474
|
+
" ```bash",
|
|
475
|
+
" # 使用 --no-git-tag-version 避免自动创建 commit 和 tag",
|
|
476
|
+
" # 我们稍后会手动创建",
|
|
477
|
+
" npm version <new_version> --no-git-tag-version",
|
|
478
|
+
" ```",
|
|
479
|
+
" 或指定 bump 类型:",
|
|
480
|
+
" ```bash",
|
|
481
|
+
" npm version minor --no-git-tag-version",
|
|
482
|
+
" ```",
|
|
483
|
+
"2. 如果是 monorepo,更新所有相关 package 的版本:",
|
|
484
|
+
" ```bash",
|
|
485
|
+
" # 使用 lerna 统一版本",
|
|
486
|
+
" npx lerna version <new_version> --no-git-tag-version --yes",
|
|
487
|
+
" # 或手动更新每个 package",
|
|
488
|
+
" find packages/ -name 'package.json' -maxdepth 2 -exec node -e \"",
|
|
489
|
+
" const fs = require('fs');",
|
|
490
|
+
" const p = JSON.parse(fs.readFileSync('{}', 'utf8'));",
|
|
491
|
+
" p.version = '<new_version>';",
|
|
492
|
+
" fs.writeFileSync('{}', JSON.stringify(p, null, 2) + '\\n');",
|
|
493
|
+
" \" \\;",
|
|
494
|
+
" ```",
|
|
495
|
+
"3. 同步更新 `package-lock.json`:",
|
|
496
|
+
" ```bash",
|
|
497
|
+
" npm install --package-lock-only",
|
|
498
|
+
" ```",
|
|
499
|
+
"4. 验证版本号已正确更新:",
|
|
500
|
+
" ```bash",
|
|
501
|
+
" node -e \"console.log(require('./package.json').version)\"",
|
|
502
|
+
" git diff package.json",
|
|
503
|
+
" ```",
|
|
504
|
+
"5. 如果有 `lerna.json`,同步更新其 version 字段",
|
|
505
|
+
"",
|
|
506
|
+
"**产出格式**:",
|
|
507
|
+
"```",
|
|
508
|
+
"files_updated: ['package.json', 'package-lock.json', 'lerna.json']",
|
|
509
|
+
"old_version: 1.2.3",
|
|
510
|
+
"new_version: 1.3.0",
|
|
511
|
+
"version_verified: true",
|
|
512
|
+
"```",
|
|
513
|
+
].join("\n"),
|
|
514
|
+
suggestedTools: ["Bash", "Edit"],
|
|
515
|
+
output: "已更新的版本号文件清单、新旧版本号",
|
|
516
|
+
depends: ["determine-version", "review-changelog"],
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
id: "create-tag",
|
|
520
|
+
title: "创建 Git Tag",
|
|
521
|
+
instruction: [
|
|
522
|
+
"## 创建 Git Tag(语义化版本号)",
|
|
523
|
+
"",
|
|
524
|
+
"为发布版本创建带注释的 Git tag。",
|
|
525
|
+
"",
|
|
526
|
+
"**执行动作**:",
|
|
527
|
+
"1. 先暂存版本变更文件:",
|
|
528
|
+
" ```bash",
|
|
529
|
+
" git add package.json package-lock.json lerna.json CHANGELOG.md",
|
|
530
|
+
" git commit -m \"chore(release): v<new_version>\"",
|
|
531
|
+
" ```",
|
|
532
|
+
"2. 创建带注释的 tag(annotated tag):",
|
|
533
|
+
" ```bash",
|
|
534
|
+
" git tag -a v<new_version> -m \"release: v<new_version>\"",
|
|
535
|
+
" ```",
|
|
536
|
+
" 或使用 Changelog 内容作为 tag message:",
|
|
537
|
+
" ```bash",
|
|
538
|
+
" git tag -a v<new_version> -F CHANGELOG.md",
|
|
539
|
+
" ```",
|
|
540
|
+
"3. 验证 tag 已正确创建:",
|
|
541
|
+
" ```bash",
|
|
542
|
+
" git tag -l 'v*' | sort -V | tail -5",
|
|
543
|
+
" git show v<new_version> --stat",
|
|
544
|
+
" ```",
|
|
545
|
+
"4. Tag 命名规范:",
|
|
546
|
+
" - 始终带 `v` 前缀:`v1.2.3`",
|
|
547
|
+
" - 使用语义化版本号",
|
|
548
|
+
" - Pre-release 版本:`v1.3.0-beta.1`、`v1.3.0-rc.1`",
|
|
549
|
+
" - 使用 annotated tag(`-a`)而非 lightweight tag",
|
|
550
|
+
"5. 检查 tag 指向的 commit 是否正确:",
|
|
551
|
+
" ```bash",
|
|
552
|
+
" git log --oneline -1 v<new_version>",
|
|
553
|
+
" ```",
|
|
554
|
+
"",
|
|
555
|
+
"**产出格式**:",
|
|
556
|
+
"```",
|
|
557
|
+
"tag_name: v1.3.0",
|
|
558
|
+
"tag_type: annotated",
|
|
559
|
+
"tag_commit: abc1234",
|
|
560
|
+
"tag_message: 'release: v1.3.0'",
|
|
561
|
+
"tag_verified: true",
|
|
562
|
+
"```",
|
|
563
|
+
].join("\n"),
|
|
564
|
+
suggestedTools: ["Bash"],
|
|
565
|
+
output: "创建的 tag 名、指向的 commit、验证状态",
|
|
566
|
+
depends: ["bump-version"],
|
|
567
|
+
},
|
|
568
|
+
{
|
|
569
|
+
id: "push-tag",
|
|
570
|
+
title: "推送 Tag 到远程仓库",
|
|
571
|
+
instruction: [
|
|
572
|
+
"## 推送 Tag 到远程仓库",
|
|
573
|
+
"",
|
|
574
|
+
"将新创建的 tag 和版本变更推送到远程 Git 仓库。",
|
|
575
|
+
"",
|
|
576
|
+
"**执行动作**:",
|
|
577
|
+
"1. 推送 tag 到远程:",
|
|
578
|
+
" ```bash",
|
|
579
|
+
" git push origin v<new_version>",
|
|
580
|
+
" ```",
|
|
581
|
+
"2. 同时推送版本 commit(如果尚未推送):",
|
|
582
|
+
" ```bash",
|
|
583
|
+
" git push origin HEAD",
|
|
584
|
+
" ```",
|
|
585
|
+
"3. 验证远程 tag 已正确推送:",
|
|
586
|
+
" ```bash",
|
|
587
|
+
" git ls-remote --tags origin | grep 'v<new_version>'",
|
|
588
|
+
" ```",
|
|
589
|
+
"4. 如果使用 GitHub,可以通过 API 创建 Release:",
|
|
590
|
+
" ```bash",
|
|
591
|
+
" gh release create v<new_version> --title \"v<new_version>\" --notes-file CHANGELOG.md",
|
|
592
|
+
" ```",
|
|
593
|
+
"5. 如果推送失败,排查常见原因:",
|
|
594
|
+
" - 权限不足 → 检查 SSH key 或 token",
|
|
595
|
+
" - tag 已存在 → 使用 `git tag -d v<version>` 删除后重试",
|
|
596
|
+
" - 远程有更新 → 先 `git pull --rebase` 再推送",
|
|
597
|
+
"6. 推送成功后确认 CI 是否被触发:",
|
|
598
|
+
" ```bash",
|
|
599
|
+
" gh run list --limit 3",
|
|
600
|
+
" ```",
|
|
601
|
+
"",
|
|
602
|
+
"**产出格式**:",
|
|
603
|
+
"```",
|
|
604
|
+
"remote: origin (git@github.com:org/repo.git)",
|
|
605
|
+
"tag_pushed: v1.3.0",
|
|
606
|
+
"release_created: true",
|
|
607
|
+
"release_url: https://github.com/org/repo/releases/tag/v1.3.0",
|
|
608
|
+
"ci_triggered: true",
|
|
609
|
+
"```",
|
|
610
|
+
].join("\n"),
|
|
611
|
+
suggestedTools: ["Bash"],
|
|
612
|
+
output: "推送状态、Release URL、CI 触发状态",
|
|
613
|
+
depends: ["create-tag"],
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
triggers: [{ type: "cli", command: "release" }],
|
|
617
|
+
},
|
|
618
|
+
// ── 分支审查 ──
|
|
619
|
+
{
|
|
620
|
+
name: "branch-audit",
|
|
621
|
+
description: "分支审查:命名规范 → 合并状态 → 清理建议",
|
|
622
|
+
version: "2.0.0",
|
|
623
|
+
steps: [
|
|
624
|
+
{
|
|
625
|
+
id: "list-branches",
|
|
626
|
+
title: "列出所有本地和远程分支",
|
|
627
|
+
instruction: [
|
|
628
|
+
"## 列出所有本地和远程分支",
|
|
629
|
+
"",
|
|
630
|
+
"收集项目中所有本地和远程分支的完整信息。",
|
|
631
|
+
"",
|
|
632
|
+
"**执行动作**:",
|
|
633
|
+
"1. 列出所有本地分支(含最后提交信息):",
|
|
634
|
+
" ```bash",
|
|
635
|
+
" git branch -v --sort=-committerdate",
|
|
636
|
+
" ```",
|
|
637
|
+
"2. 列出所有远程分支:",
|
|
638
|
+
" ```bash",
|
|
639
|
+
" git branch -r -v --sort=-committerdate",
|
|
640
|
+
" ```",
|
|
641
|
+
"3. 列出所有分支(本地 + 远程),含详细日期信息:",
|
|
642
|
+
" ```bash",
|
|
643
|
+
" git for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:iso) %(subject)' refs/heads/ refs/remotes/",
|
|
644
|
+
" ```",
|
|
645
|
+
"4. 统计分支总数:",
|
|
646
|
+
" ```bash",
|
|
647
|
+
" echo \"Local branches: $(git branch | wc -l)\"",
|
|
648
|
+
" echo \"Remote branches: $(git branch -r | wc -l)\"",
|
|
649
|
+
" ```",
|
|
650
|
+
"5. 查看当前分支:",
|
|
651
|
+
" ```bash",
|
|
652
|
+
" git branch --show-current",
|
|
653
|
+
" ```",
|
|
654
|
+
"6. 清理过期的远程跟踪引用:",
|
|
655
|
+
" ```bash",
|
|
656
|
+
" git remote prune origin --dry-run",
|
|
657
|
+
" ```",
|
|
658
|
+
"",
|
|
659
|
+
"**产出格式**:",
|
|
660
|
+
"```",
|
|
661
|
+
"current_branch: main",
|
|
662
|
+
"local_branches: [{ name: 'main', last_commit: 'abc1234', date: '2024-02-20', subject: '...' }]",
|
|
663
|
+
"remote_branches: [{ name: 'origin/feature/auth', last_commit: 'def5678', date: '2024-02-18', subject: '...' }]",
|
|
664
|
+
"total_local: 8",
|
|
665
|
+
"total_remote: 15",
|
|
666
|
+
"stale_remotes: ['origin/feature/old-task']",
|
|
667
|
+
"```",
|
|
668
|
+
].join("\n"),
|
|
669
|
+
suggestedTools: ["Bash"],
|
|
670
|
+
output: "本地和远程分支完整清单、提交日期信息",
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
id: "check-naming",
|
|
674
|
+
title: "检查分支命名规范",
|
|
675
|
+
instruction: [
|
|
676
|
+
"## 检查分支命名是否符合 GitFlow 规范",
|
|
677
|
+
"",
|
|
678
|
+
"验证所有分支名称是否符合项目约定的命名规范。",
|
|
679
|
+
"",
|
|
680
|
+
"**执行动作**:",
|
|
681
|
+
"1. 获取所有本地分支名称:",
|
|
682
|
+
" ```bash",
|
|
683
|
+
" git branch --format='%(refname:short)'",
|
|
684
|
+
" ```",
|
|
685
|
+
"2. 定义合规的分支命名模式:",
|
|
686
|
+
" - `main` / `master` — 主分支",
|
|
687
|
+
" - `develop` — 开发分支",
|
|
688
|
+
" - `feature/<desc>` — 功能分支",
|
|
689
|
+
" - `fix/<desc>` — 修复分支",
|
|
690
|
+
" - `hotfix/<desc>` — 紧急修复",
|
|
691
|
+
" - `release/<version>` — 发布分支",
|
|
692
|
+
" - `chore/<desc>` — 杂务分支",
|
|
693
|
+
"3. 检查每个分支是否匹配上述模式:",
|
|
694
|
+
" ```bash",
|
|
695
|
+
" git branch --format='%(refname:short)' | while read branch; do",
|
|
696
|
+
" if echo \"$branch\" | grep -qE '^(main|master|develop|feature/|fix/|hotfix/|release/|chore/)'; then",
|
|
697
|
+
" echo \"COMPLIANT: $branch\"",
|
|
698
|
+
" else",
|
|
699
|
+
" echo \"NON-COMPLIANT: $branch\"",
|
|
700
|
+
" fi",
|
|
701
|
+
" done",
|
|
702
|
+
" ```",
|
|
703
|
+
"4. 额外检查命名质量:",
|
|
704
|
+
" - 不能包含大写字母(应使用 kebab-case)",
|
|
705
|
+
" - 不能包含空格或特殊字符",
|
|
706
|
+
" - `<desc>` 部分应有语义(不应是随机字符串)",
|
|
707
|
+
" - `release/` 分支应包含版本号",
|
|
708
|
+
"",
|
|
709
|
+
"**产出格式**:",
|
|
710
|
+
"```",
|
|
711
|
+
"total_branches: 12",
|
|
712
|
+
"compliant: ['main', 'develop', 'feature/user-auth', 'fix/login-bug']",
|
|
713
|
+
"non_compliant: [{ name: 'my-feature', issue: 'missing type prefix (feature/)', suggestion: 'feature/my-feature' }]",
|
|
714
|
+
"compliance_rate: '83%' (10/12)",
|
|
715
|
+
"```",
|
|
716
|
+
].join("\n"),
|
|
717
|
+
suggestedTools: ["Bash"],
|
|
718
|
+
output: "命名合规分支列表、不合规列表及修正建议",
|
|
719
|
+
depends: ["list-branches"],
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
id: "check-merged",
|
|
723
|
+
title: "检查已合并但未删除的分支",
|
|
724
|
+
instruction: [
|
|
725
|
+
"## 检查已合并但未删除的分支",
|
|
726
|
+
"",
|
|
727
|
+
"找出已经合并到主分支但本地尚未删除的分支。",
|
|
728
|
+
"",
|
|
729
|
+
"**执行动作**:",
|
|
730
|
+
"1. 查找已合并到 main 的本地分支:",
|
|
731
|
+
" ```bash",
|
|
732
|
+
" git branch --merged main",
|
|
733
|
+
" ```",
|
|
734
|
+
"2. 查找已合并到 develop 的本地分支:",
|
|
735
|
+
" ```bash",
|
|
736
|
+
" git branch --merged develop",
|
|
737
|
+
" ```",
|
|
738
|
+
"3. 过滤掉保护分支(不应删除的):",
|
|
739
|
+
" ```bash",
|
|
740
|
+
" git branch --merged main | grep -vE '^\\*|main|master|develop|release/'",
|
|
741
|
+
" ```",
|
|
742
|
+
"4. 对每个已合并分支,查看合并时间和相关 PR:",
|
|
743
|
+
" ```bash",
|
|
744
|
+
" for branch in $(git branch --merged main | grep -vE '^\\*|main|master|develop'); do",
|
|
745
|
+
" echo \"Branch: $branch\"",
|
|
746
|
+
" echo \" Last commit: $(git log -1 --format='%h %s (%cr)' $branch)\"",
|
|
747
|
+
" echo \" Merged at: $(git log main --ancestry-path $branch..main --format='%ai' | tail -1)\"",
|
|
748
|
+
" done",
|
|
749
|
+
" ```",
|
|
750
|
+
"5. 同时检查远程已合并的分支:",
|
|
751
|
+
" ```bash",
|
|
752
|
+
" git branch -r --merged main | grep -vE 'main|master|develop|HEAD'",
|
|
753
|
+
" ```",
|
|
754
|
+
"6. 这些分支通常可以安全删除",
|
|
755
|
+
"",
|
|
756
|
+
"**产出格式**:",
|
|
757
|
+
"```",
|
|
758
|
+
"merged_local: [{ name: 'feature/user-auth', last_commit: 'abc1234', merged_days_ago: 15 }]",
|
|
759
|
+
"merged_remote: [{ name: 'origin/fix/login-bug', merged_days_ago: 30 }]",
|
|
760
|
+
"total_merged_local: 3",
|
|
761
|
+
"total_merged_remote: 5",
|
|
762
|
+
"safe_to_delete: ['feature/user-auth', 'fix/login-bug']",
|
|
763
|
+
"```",
|
|
764
|
+
].join("\n"),
|
|
765
|
+
suggestedTools: ["Bash"],
|
|
766
|
+
output: "已合并分支清单、合并时间、可安全删除列表",
|
|
767
|
+
depends: ["list-branches"],
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
id: "check-stale",
|
|
771
|
+
title: "检查长期未更新的分支",
|
|
772
|
+
instruction: [
|
|
773
|
+
"## 检查长期未更新的分支(>30 天)",
|
|
774
|
+
"",
|
|
775
|
+
"找出超过 30 天没有任何提交的陈旧分支。",
|
|
776
|
+
"",
|
|
777
|
+
"**执行动作**:",
|
|
778
|
+
"1. 列出所有本地分支,按最后提交日期排序:",
|
|
779
|
+
" ```bash",
|
|
780
|
+
" git for-each-ref --sort=committerdate --format='%(refname:short) %(committerdate:iso) %(committerdate:relative)' refs/heads/",
|
|
781
|
+
" ```",
|
|
782
|
+
"2. 筛选超过 30 天未更新的分支:",
|
|
783
|
+
" ```bash",
|
|
784
|
+
" git for-each-ref --sort=committerdate --format='%(refname:short)|%(committerdate:unix)|%(subject)' refs/heads/ | while IFS='|' read name ts subject; do",
|
|
785
|
+
" now=$(date +%s)",
|
|
786
|
+
" age=$(( (now - ts) / 86400 ))",
|
|
787
|
+
" if [ $age -gt 30 ]; then",
|
|
788
|
+
" echo \"STALE: $name (${age} days old) - $subject\"",
|
|
789
|
+
" fi",
|
|
790
|
+
" done",
|
|
791
|
+
" ```",
|
|
792
|
+
"3. 对远程分支执行相同检查:",
|
|
793
|
+
" ```bash",
|
|
794
|
+
" git for-each-ref --sort=committerdate --format='%(refname:short)|%(committerdate:unix)|%(subject)' refs/remotes/origin/ | head -20",
|
|
795
|
+
" ```",
|
|
796
|
+
"4. 分类陈旧分支:",
|
|
797
|
+
" - 30-90 天:可能需要清理",
|
|
798
|
+
" - 90-180 天:很可能已废弃",
|
|
799
|
+
" - >180 天:几乎可以确定应删除",
|
|
800
|
+
"5. 检查陈旧分支是否有未合并的变更:",
|
|
801
|
+
" ```bash",
|
|
802
|
+
" git log main..<stale-branch> --oneline",
|
|
803
|
+
" ```",
|
|
804
|
+
"6. 如果分支有未合并的 commit,标记为「需要确认」",
|
|
805
|
+
"",
|
|
806
|
+
"**产出格式**:",
|
|
807
|
+
"```",
|
|
808
|
+
"stale_branches: [",
|
|
809
|
+
" { name: 'feature/old-auth', days_stale: 120, last_commit: 'abc1234', unmerged_commits: 3, recommendation: 'delete' },",
|
|
810
|
+
" { name: 'fix/legacy-bug', days_stale: 45, last_commit: 'def5678', unmerged_commits: 0, recommendation: 'delete' }",
|
|
811
|
+
"]",
|
|
812
|
+
"total_stale: 5",
|
|
813
|
+
"safe_to_delete: ['fix/legacy-bug']",
|
|
814
|
+
"needs_confirmation: ['feature/old-auth']",
|
|
815
|
+
"```",
|
|
816
|
+
].join("\n"),
|
|
817
|
+
suggestedTools: ["Bash"],
|
|
818
|
+
output: "陈旧分支清单、废弃天数、未合并 commit 数、删除建议",
|
|
819
|
+
depends: ["list-branches"],
|
|
820
|
+
},
|
|
821
|
+
{ id: "generate-report", stepTemplate: "generate-report", depends: ["check-naming", "check-merged", "check-stale"] },
|
|
822
|
+
{ id: "cleanup-approval", stepTemplate: "human-review", depends: ["generate-report"] },
|
|
823
|
+
],
|
|
824
|
+
triggers: [{ type: "cli", command: "audit:branches" }],
|
|
825
|
+
},
|
|
826
|
+
// ── 冲突解决辅助 ──
|
|
827
|
+
{
|
|
828
|
+
name: "conflict-resolve",
|
|
829
|
+
description: "冲突解决辅助:冲突分析 → 策略建议 → 逐文件解决",
|
|
830
|
+
version: "2.0.0",
|
|
831
|
+
steps: [
|
|
832
|
+
{
|
|
833
|
+
id: "detect-conflicts",
|
|
834
|
+
title: "检测所有冲突文件",
|
|
835
|
+
instruction: [
|
|
836
|
+
"## 检测所有冲突文件和冲突类型",
|
|
837
|
+
"",
|
|
838
|
+
"在合并/rebase 过程中,识别所有冲突文件及其冲突类型。",
|
|
839
|
+
"",
|
|
840
|
+
"**执行动作**:",
|
|
841
|
+
"1. 查看当前 Git 状态(确认处于冲突状态):",
|
|
842
|
+
" ```bash",
|
|
843
|
+
" git status",
|
|
844
|
+
" ```",
|
|
845
|
+
"2. 列出所有冲突文件:",
|
|
846
|
+
" ```bash",
|
|
847
|
+
" git diff --name-only --diff-filter=U",
|
|
848
|
+
" # 或",
|
|
849
|
+
" git ls-files -u",
|
|
850
|
+
" ```",
|
|
851
|
+
"3. 对每个冲突文件,查看冲突标记:",
|
|
852
|
+
" ```bash",
|
|
853
|
+
" grep -n '<<<<<<<\\|=======\\|>>>>>>>' <conflict-file>",
|
|
854
|
+
" ```",
|
|
855
|
+
"4. 冲突类型分类:",
|
|
856
|
+
" - **内容冲突**(最常见):两边修改了同一行或相邻行",
|
|
857
|
+
" - **重命名冲突**:一边重命名文件,另一边修改了该文件",
|
|
858
|
+
" - **删除冲突**:一边删除文件,另一边修改了该文件",
|
|
859
|
+
" - **add/add 冲突**:两边同时添加了同名新文件",
|
|
860
|
+
"5. 统计每个文件的冲突块数量:",
|
|
861
|
+
" ```bash",
|
|
862
|
+
" for f in $(git diff --name-only --diff-filter=U); do",
|
|
863
|
+
" count=$(grep -c '<<<<<<<' \"$f\")",
|
|
864
|
+
" echo \"$f: $count conflict(s)\"",
|
|
865
|
+
" done",
|
|
866
|
+
" ```",
|
|
867
|
+
"6. 确认当前操作类型(merge/rebase/cherry-pick):",
|
|
868
|
+
" ```bash",
|
|
869
|
+
" ls .git/MERGE_HEAD 2>/dev/null && echo 'merge in progress'",
|
|
870
|
+
" ls .git/REBASE_HEAD 2>/dev/null && echo 'rebase in progress'",
|
|
871
|
+
" ls .git/CHERRY_PICK_HEAD 2>/dev/null && echo 'cherry-pick in progress'",
|
|
872
|
+
" ```",
|
|
873
|
+
"",
|
|
874
|
+
"**产出格式**:",
|
|
875
|
+
"```",
|
|
876
|
+
"operation_type: merge",
|
|
877
|
+
"conflict_files: [",
|
|
878
|
+
" { path: 'src/auth.ts', type: 'content', conflict_blocks: 2 },",
|
|
879
|
+
" { path: 'src/utils.ts', type: 'content', conflict_blocks: 1 }",
|
|
880
|
+
"]",
|
|
881
|
+
"total_conflicts: 3",
|
|
882
|
+
"```",
|
|
883
|
+
].join("\n"),
|
|
884
|
+
suggestedTools: ["Bash", "Read"],
|
|
885
|
+
output: "冲突文件清单、冲突类型、冲突块数量",
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
id: "analyze-conflict-source",
|
|
889
|
+
title: "分析冲突来源",
|
|
890
|
+
instruction: [
|
|
891
|
+
"## 分析冲突来源(两边的最后修改者)",
|
|
892
|
+
"",
|
|
893
|
+
"理解冲突两边的修改意图和上下文,为冲突解决提供决策依据。",
|
|
894
|
+
"",
|
|
895
|
+
"**执行动作**:",
|
|
896
|
+
"1. 确认当前分支和合入分支:",
|
|
897
|
+
" ```bash",
|
|
898
|
+
" echo \"Current branch: $(git branch --show-current)\"",
|
|
899
|
+
" # 对于 merge",
|
|
900
|
+
" git log MERGE_HEAD --oneline -5 2>/dev/null",
|
|
901
|
+
" # 对于 rebase",
|
|
902
|
+
" git log REBASE_HEAD --oneline -5 2>/dev/null",
|
|
903
|
+
" ```",
|
|
904
|
+
"2. 对每个冲突文件,查看两边的最后修改者和修改内容:",
|
|
905
|
+
" ```bash",
|
|
906
|
+
" # ours 版本(当前分支)的最后修改",
|
|
907
|
+
" git log -1 --format='%h %an <%ae> %s' HEAD -- <file>",
|
|
908
|
+
"",
|
|
909
|
+
" # theirs 版本(合入分支)的最后修改",
|
|
910
|
+
" git log -1 --format='%h %an <%ae> %s' MERGE_HEAD -- <file>",
|
|
911
|
+
" ```",
|
|
912
|
+
"3. 查看冲突文件两边的具体 diff:",
|
|
913
|
+
" ```bash",
|
|
914
|
+
" # 查看 ours 版本的修改",
|
|
915
|
+
" git diff HEAD...MERGE_HEAD -- <file>",
|
|
916
|
+
"",
|
|
917
|
+
" # 查看 theirs 版本的修改",
|
|
918
|
+
" git diff MERGE_HEAD...HEAD -- <file>",
|
|
919
|
+
" ```",
|
|
920
|
+
"4. 查看冲突文件的原始版本(merge base):",
|
|
921
|
+
" ```bash",
|
|
922
|
+
" BASE=$(git merge-base HEAD MERGE_HEAD)",
|
|
923
|
+
" git show $BASE:<file> | head -50",
|
|
924
|
+
" ```",
|
|
925
|
+
"5. 查看两边修改的意图(从 commit message 推断):",
|
|
926
|
+
" ```bash",
|
|
927
|
+
" git log --oneline HEAD...MERGE_HEAD -- <file>",
|
|
928
|
+
" git log --oneline MERGE_HEAD...HEAD -- <file>",
|
|
929
|
+
" ```",
|
|
930
|
+
"6. 评估冲突复杂度:",
|
|
931
|
+
" - 是否涉及同一函数的不同修改?",
|
|
932
|
+
" - 是否是 API 签名变更?",
|
|
933
|
+
" - 是否涉及数据库迁移?",
|
|
934
|
+
"",
|
|
935
|
+
"**产出格式**:",
|
|
936
|
+
"```",
|
|
937
|
+
"conflict_analysis: [",
|
|
938
|
+
" {",
|
|
939
|
+
" file: 'src/auth.ts',",
|
|
940
|
+
" ours: { author: 'Alice', commit: 'abc1234', intent: 'refactor auth to use new SDK' },",
|
|
941
|
+
" theirs: { author: 'Bob', commit: 'def5678', intent: 'add OAuth2 support' },",
|
|
942
|
+
" merge_base_commit: 'xyz9876',",
|
|
943
|
+
" complexity: 'medium',",
|
|
944
|
+
" notes: 'both modify authInit() function - need to combine SDK refactor with OAuth2'",
|
|
945
|
+
" }",
|
|
946
|
+
"]",
|
|
947
|
+
"```",
|
|
948
|
+
].join("\n"),
|
|
949
|
+
suggestedTools: ["Bash", "Read"],
|
|
950
|
+
output: "每个冲突文件的两边修改者、意图、复杂度评估",
|
|
951
|
+
depends: ["detect-conflicts"],
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
id: "suggest-strategy",
|
|
955
|
+
title: "建议冲突解决策略",
|
|
956
|
+
instruction: [
|
|
957
|
+
"## 建议冲突解决策略(保留 ours/theirs/手动合并)",
|
|
958
|
+
"",
|
|
959
|
+
"基于冲突分析结果,为每个冲突提供具体的解决策略。",
|
|
960
|
+
"",
|
|
961
|
+
"**执行动作**:",
|
|
962
|
+
"1. 对每个冲突块,评估以下策略:",
|
|
963
|
+
"",
|
|
964
|
+
" **策略 A:保留 ours(当前分支版本)**",
|
|
965
|
+
" - 适用场景:ours 的修改更新、更全面",
|
|
966
|
+
" ```bash",
|
|
967
|
+
" git checkout --ours <file>",
|
|
968
|
+
" ```",
|
|
969
|
+
"",
|
|
970
|
+
" **策略 B:保留 theirs(合入分支版本)**",
|
|
971
|
+
" - 适用场景:theirs 的修改更符合需求",
|
|
972
|
+
" ```bash",
|
|
973
|
+
" git checkout --theirs <file>",
|
|
974
|
+
" ```",
|
|
975
|
+
"",
|
|
976
|
+
" **策略 C:手动合并两边修改**",
|
|
977
|
+
" - 适用场景:两边的修改都需要保留",
|
|
978
|
+
" - 需要理解两边意图,合并为逻辑上一致的代码",
|
|
979
|
+
"",
|
|
980
|
+
" **策略 D:使用 diff3 模式查看三方合并**",
|
|
981
|
+
" ```bash",
|
|
982
|
+
" git checkout -m <file> # 显示 base/ours/theirs 三段",
|
|
983
|
+
" ```",
|
|
984
|
+
"",
|
|
985
|
+
"2. 评估维度:",
|
|
986
|
+
" - 哪边的修改更完整?",
|
|
987
|
+
" - 哪边更新了依赖/API?",
|
|
988
|
+
" - 是否有测试覆盖可以验证?",
|
|
989
|
+
" - 合并后是否需要调整其他文件?",
|
|
990
|
+
"3. 对于复杂冲突,建议使用 `git mergetool`:",
|
|
991
|
+
" ```bash",
|
|
992
|
+
" git mergetool # 打开可视化合并工具",
|
|
993
|
+
" ```",
|
|
994
|
+
"4. 输出每个冲突的推荐策略和理由",
|
|
995
|
+
"",
|
|
996
|
+
"**产出格式**:",
|
|
997
|
+
"```",
|
|
998
|
+
"resolution_strategy: [",
|
|
999
|
+
" {",
|
|
1000
|
+
" file: 'src/auth.ts',",
|
|
1001
|
+
" conflict_block: 1,",
|
|
1002
|
+
" strategy: 'manual-merge',",
|
|
1003
|
+
" reasoning: 'both changes are needed - combine SDK refactor with OAuth2 addition',",
|
|
1004
|
+
" risk: 'medium - need to verify auth flow still works'",
|
|
1005
|
+
" },",
|
|
1006
|
+
" {",
|
|
1007
|
+
" file: 'src/utils.ts',",
|
|
1008
|
+
" conflict_block: 1,",
|
|
1009
|
+
" strategy: 'theirs',",
|
|
1010
|
+
" reasoning: 'theirs adds new utility function, ours only reformats - take theirs'",
|
|
1011
|
+
" risk: 'low'",
|
|
1012
|
+
" }",
|
|
1013
|
+
"]",
|
|
1014
|
+
"overall_risk: medium",
|
|
1015
|
+
"```",
|
|
1016
|
+
].join("\n"),
|
|
1017
|
+
suggestedTools: ["Bash", "Read"],
|
|
1018
|
+
output: "每个冲突的推荐解决策略、理由、风险评估",
|
|
1019
|
+
depends: ["analyze-conflict-source"],
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
id: "resolve-files",
|
|
1023
|
+
title: "逐文件解决冲突",
|
|
1024
|
+
instruction: [
|
|
1025
|
+
"## 逐文件解决冲突",
|
|
1026
|
+
"",
|
|
1027
|
+
"根据 `suggest-strategy` 的推荐策略,逐个解决冲突文件。",
|
|
1028
|
+
"",
|
|
1029
|
+
"**执行动作**:",
|
|
1030
|
+
"1. 对每个冲突文件,按推荐策略执行:",
|
|
1031
|
+
"",
|
|
1032
|
+
" **如果是「保留 ours」:**",
|
|
1033
|
+
" ```bash",
|
|
1034
|
+
" git checkout --ours <file>",
|
|
1035
|
+
" git add <file>",
|
|
1036
|
+
" ```",
|
|
1037
|
+
"",
|
|
1038
|
+
" **如果是「保留 theirs」:**",
|
|
1039
|
+
" ```bash",
|
|
1040
|
+
" git checkout --theirs <file>",
|
|
1041
|
+
" git add <file>",
|
|
1042
|
+
" ```",
|
|
1043
|
+
"",
|
|
1044
|
+
" **如果是「手动合并」:**",
|
|
1045
|
+
" a. 打开冲突文件,定位冲突标记:",
|
|
1046
|
+
" ```",
|
|
1047
|
+
" <<<<<<< HEAD",
|
|
1048
|
+
" ours version of code",
|
|
1049
|
+
" =======",
|
|
1050
|
+
" theirs version of code",
|
|
1051
|
+
" >>>>>>> branch-name",
|
|
1052
|
+
" ```",
|
|
1053
|
+
" b. 理解两边的修改意图",
|
|
1054
|
+
" c. 编写合并后的代码(移除所有冲突标记)",
|
|
1055
|
+
" d. 确保合并后的代码逻辑正确",
|
|
1056
|
+
" e. 标记为已解决:",
|
|
1057
|
+
" ```bash",
|
|
1058
|
+
" git add <file>",
|
|
1059
|
+
" ```",
|
|
1060
|
+
"",
|
|
1061
|
+
"2. 检查是否还有未解决的冲突:",
|
|
1062
|
+
" ```bash",
|
|
1063
|
+
" git diff --name-only --diff-filter=U",
|
|
1064
|
+
" grep -rn '<<<<<<<\\|=======\\|>>>>>>>' <file>",
|
|
1065
|
+
" ```",
|
|
1066
|
+
"3. 确认所有冲突都已标记解决:",
|
|
1067
|
+
" ```bash",
|
|
1068
|
+
" git status",
|
|
1069
|
+
" ```",
|
|
1070
|
+
"4. 对于 merge 操作,完成合并:",
|
|
1071
|
+
" ```bash",
|
|
1072
|
+
" git commit # 使用默认的 merge commit message",
|
|
1073
|
+
" ```",
|
|
1074
|
+
" 对于 rebase 操作,继续 rebase:",
|
|
1075
|
+
" ```bash",
|
|
1076
|
+
" git rebase --continue",
|
|
1077
|
+
" ```",
|
|
1078
|
+
"",
|
|
1079
|
+
"**产出格式**:",
|
|
1080
|
+
"```",
|
|
1081
|
+
"resolved_files: [",
|
|
1082
|
+
" { path: 'src/auth.ts', strategy: 'manual-merge', status: 'resolved' },",
|
|
1083
|
+
" { path: 'src/utils.ts', strategy: 'theirs', status: 'resolved' }",
|
|
1084
|
+
"]",
|
|
1085
|
+
"remaining_conflicts: 0",
|
|
1086
|
+
"merge_completed: true",
|
|
1087
|
+
"merge_commit: 'abc1234'",
|
|
1088
|
+
"```",
|
|
1089
|
+
].join("\n"),
|
|
1090
|
+
suggestedTools: ["Bash", "Read", "Edit"],
|
|
1091
|
+
output: "已解决的冲突文件清单、剩余冲突数、合并状态",
|
|
1092
|
+
depends: ["suggest-strategy"],
|
|
1093
|
+
},
|
|
1094
|
+
{ id: "verify-build", stepTemplate: "build-verify", depends: ["resolve-files"] },
|
|
1095
|
+
{ id: "run-tests", stepTemplate: "run-tests", depends: ["verify-build"] },
|
|
1096
|
+
],
|
|
1097
|
+
triggers: [{ type: "cli", command: "resolve:conflicts" }],
|
|
1098
|
+
},
|
|
1099
|
+
],
|
|
1100
|
+
},
|
|
1101
|
+
prompt: {
|
|
1102
|
+
system: "你是一个 Git 工作流专家。遵循 Conventional Commits 规范和 GitFlow 分支策略。",
|
|
1103
|
+
rules: [
|
|
1104
|
+
"提交信息使用 Conventional Commits 格式:type(scope): description",
|
|
1105
|
+
"功能分支从 develop 拉出,完成后合并回 develop",
|
|
1106
|
+
"提交信息主题行不超过 50 字符",
|
|
1107
|
+
"每个提交是逻辑上独立的变更",
|
|
1108
|
+
"公共分支禁止 force push 和 rebase",
|
|
1109
|
+
"PR 必须关联 Issue",
|
|
1110
|
+
"解决冲突前先理解两边变更的意图",
|
|
1111
|
+
],
|
|
1112
|
+
},
|
|
1113
|
+
tools: [
|
|
1114
|
+
{
|
|
1115
|
+
name: 'git_analyze_repo',
|
|
1116
|
+
description: '分析 Git 仓库状态:分支、变更文件、最近提交',
|
|
1117
|
+
inputSchema: {
|
|
1118
|
+
type: 'object',
|
|
1119
|
+
properties: {
|
|
1120
|
+
projectRoot: { type: 'string', description: '项目根目录' },
|
|
1121
|
+
},
|
|
1122
|
+
required: ['projectRoot'],
|
|
1123
|
+
},
|
|
1124
|
+
outputSchema: structuredOutputSchema,
|
|
1125
|
+
annotations: readOnlyAnnotations,
|
|
1126
|
+
handler: async (input) => {
|
|
1127
|
+
const { analyzeRepo } = await import('./analyzers/analyze-repo.js');
|
|
1128
|
+
return analyzeRepo(input);
|
|
1129
|
+
},
|
|
1130
|
+
},
|
|
1131
|
+
],
|
|
1132
|
+
};
|
|
1133
|
+
//# sourceMappingURL=index.js.map
|