create-dwy 0.4.1 → 0.5.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/package.json +1 -1
- package/src/sync.js +10 -1
- package/templates/claude-global/hooks/post-sync-claude-global.sh +72 -0
- package/templates/claude-global/rules/agent-team-patterns.md +1 -1
- package/templates/claude-global/rules/backend-security.md +17 -7
- package/templates/claude-global/rules/git-commit-convention.md +106 -0
- package/templates/claude-global/rules/python-code-style.md +23 -0
- package/templates/claude-global/rules/vue-code-style.md +23 -0
- package/templates/claude-global/settings.json +20 -0
- package/templates/claude-global/skills/dwy-dev-qa/SKILL.md +117 -0
- package/templates/claude-global/skills/dwy-release/SKILL.md +111 -0
- package/templates/claude-global/rules/docs-sync.md +0 -23
- package/templates/claude-global/skills/dwy-auto-sync/SKILL.md +0 -52
package/package.json
CHANGED
package/src/sync.js
CHANGED
|
@@ -43,7 +43,16 @@ export async function syncClaude() {
|
|
|
43
43
|
|
|
44
44
|
if (await fs.pathExists(settingsDest)) {
|
|
45
45
|
const existing = await fs.readJson(settingsDest)
|
|
46
|
-
|
|
46
|
+
// 两层深合并:顶层 key merge + dict value 二级 merge
|
|
47
|
+
const merged = { ...existing }
|
|
48
|
+
for (const [key, value] of Object.entries(newSettings)) {
|
|
49
|
+
if (key in merged && typeof merged[key] === 'object' && !Array.isArray(merged[key])
|
|
50
|
+
&& typeof value === 'object' && !Array.isArray(value)) {
|
|
51
|
+
merged[key] = { ...merged[key], ...value }
|
|
52
|
+
} else {
|
|
53
|
+
merged[key] = value
|
|
54
|
+
}
|
|
55
|
+
}
|
|
47
56
|
await fs.writeJson(settingsDest, merged, { spaces: 2 })
|
|
48
57
|
console.log(chalk.green(' ✓ settings.json — merged'))
|
|
49
58
|
} else {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Claude Code PostToolUse Hook
|
|
3
|
+
# 当 Edit/Write 修改了 claude-global 模板文件时,自动同步到 ~/.claude/
|
|
4
|
+
|
|
5
|
+
# 快速路径检查:不含模板目录标记则直接退出
|
|
6
|
+
TEMPLATE_MARKER="claude-cli/templates/claude-global/"
|
|
7
|
+
echo "$TOOL_INPUT" | grep -q "$TEMPLATE_MARKER" || exit 0
|
|
8
|
+
|
|
9
|
+
# 用 python3 提取 file_path 并执行同步
|
|
10
|
+
python3 -c "
|
|
11
|
+
import json, sys, os, shutil
|
|
12
|
+
|
|
13
|
+
tool_input = os.environ.get('TOOL_INPUT', '')
|
|
14
|
+
if not tool_input:
|
|
15
|
+
sys.exit(0)
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
data = json.loads(tool_input)
|
|
19
|
+
except (json.JSONDecodeError, TypeError):
|
|
20
|
+
sys.exit(0)
|
|
21
|
+
|
|
22
|
+
file_path = data.get('file_path', '')
|
|
23
|
+
marker = '$TEMPLATE_MARKER'
|
|
24
|
+
|
|
25
|
+
if marker not in file_path:
|
|
26
|
+
sys.exit(0)
|
|
27
|
+
|
|
28
|
+
# 提取相对路径
|
|
29
|
+
rel_path = file_path.split(marker, 1)[1]
|
|
30
|
+
if not rel_path or '..' in rel_path:
|
|
31
|
+
sys.exit(0)
|
|
32
|
+
|
|
33
|
+
target_dir = os.path.expanduser('~/.claude')
|
|
34
|
+
dest_path = os.path.join(target_dir, rel_path)
|
|
35
|
+
|
|
36
|
+
# settings.json: 两层深合并
|
|
37
|
+
if rel_path == 'settings.json':
|
|
38
|
+
try:
|
|
39
|
+
with open(file_path) as f:
|
|
40
|
+
new_settings = json.load(f)
|
|
41
|
+
except Exception:
|
|
42
|
+
sys.exit(0)
|
|
43
|
+
|
|
44
|
+
if os.path.exists(dest_path):
|
|
45
|
+
try:
|
|
46
|
+
with open(dest_path) as f:
|
|
47
|
+
existing = json.load(f)
|
|
48
|
+
except Exception:
|
|
49
|
+
existing = {}
|
|
50
|
+
# 两层深合并:顶层 merge + dict value 二级 merge
|
|
51
|
+
merged = dict(existing)
|
|
52
|
+
for key, value in new_settings.items():
|
|
53
|
+
if key in merged and isinstance(merged[key], dict) and isinstance(value, dict):
|
|
54
|
+
merged[key] = {**merged[key], **value}
|
|
55
|
+
else:
|
|
56
|
+
merged[key] = value
|
|
57
|
+
else:
|
|
58
|
+
os.makedirs(target_dir, exist_ok=True)
|
|
59
|
+
merged = new_settings
|
|
60
|
+
|
|
61
|
+
with open(dest_path, 'w') as f:
|
|
62
|
+
json.dump(merged, f, indent=2, ensure_ascii=False)
|
|
63
|
+
f.write('\n')
|
|
64
|
+
print(f'[sync] Merged settings.json -> {dest_path}')
|
|
65
|
+
else:
|
|
66
|
+
# 其他文件:直接复制
|
|
67
|
+
os.makedirs(os.path.dirname(dest_path), exist_ok=True)
|
|
68
|
+
shutil.copy2(file_path, dest_path) # copy2 保留权限和时间戳
|
|
69
|
+
print(f'[sync] Copied {rel_path} -> {dest_path}')
|
|
70
|
+
"
|
|
71
|
+
|
|
72
|
+
exit 0
|
|
@@ -127,7 +127,7 @@ Agent-2 (worktree) → 前端页面 + API 调用
|
|
|
127
127
|
| 多 Agent 改同一文件 | 冲突、覆盖 | 串行修改或拆分文件职责 |
|
|
128
128
|
| 无上下文的 Agent | 产出质量差 | prompt 必须自包含 |
|
|
129
129
|
| 链式依赖硬并行 | B 依赖 A 的输出却并行 | 识别依赖,串行执行 |
|
|
130
|
-
|
|
|
130
|
+
| 超过 5 个 Agent 同时派出 | 难以管理、context 爆炸 | 单批最多 5 个 Agent |
|
|
131
131
|
| 跳过 review 直接提交 | 质量无保障 | 遵循 review 闭环 |
|
|
132
132
|
|
|
133
133
|
## 四、Agent 数量指南
|
|
@@ -581,19 +581,29 @@ async def export_users(request: Request): ...
|
|
|
581
581
|
|
|
582
582
|
## 十五、违规检测清单
|
|
583
583
|
|
|
584
|
-
AI
|
|
584
|
+
**AI 在编写或审查代码时,必须检查以下违规模式。检测到违规时按严重程度执行对应动作:**
|
|
585
|
+
|
|
586
|
+
### 严重程度与动作
|
|
587
|
+
|
|
588
|
+
| 严重程度 | 动作 |
|
|
589
|
+
|---------|------|
|
|
590
|
+
| **致命** | **立即 STOP,不得继续编写或提交代码。** 必须修正后重新检查,修正前不执行任何其他操作。 |
|
|
591
|
+
| **高** | 必须修正后才能继续。向用户说明违规点和修正方案。 |
|
|
592
|
+
| **中** | 提示用户存在风险,建议修正。用户确认后可继续。 |
|
|
593
|
+
|
|
594
|
+
### 检查清单
|
|
585
595
|
|
|
586
596
|
| 检查项 | 违规模式 | 严重程度 |
|
|
587
597
|
|--------|---------|---------|
|
|
598
|
+
| 密码明文 | `password` 字段出现在 Response Schema | **致命 → STOP** |
|
|
599
|
+
| 密码弱存储 | 使用 MD5/SHA 而非 bcrypt | **致命 → STOP** |
|
|
600
|
+
| SQL 拼接 | f-string 拼接 SQL 语句 | **致命 → STOP** |
|
|
601
|
+
| 命令注入 | 直接执行 shell 命令或 `shell=True` | **致命 → STOP** |
|
|
602
|
+
| DolphinDB 拼接 | 用户输入直接进 DolphinDB 脚本 | **致命 → STOP** |
|
|
588
603
|
| 自增 ID 暴露 | 路由参数为 `int` 类型的 ID | 高 |
|
|
589
|
-
| 密码明文 | `password` 字段出现在 Response Schema | 致命 |
|
|
590
|
-
| 密码弱存储 | 使用 MD5/SHA 而非 bcrypt | 致命 |
|
|
591
604
|
| 无认证接口 | 数据接口无 `Depends(get_current_user)` | 高 |
|
|
592
|
-
| SQL 拼接 | `f"SELECT ... {user_input}"` | 致命 |
|
|
593
|
-
| 命令注入 | `os.system()` / `subprocess(shell=True)` | 致命 |
|
|
594
605
|
| 全量返回 | 列表接口无分页限制 | 高 |
|
|
595
606
|
| 错误回显 | `str(exception)` 返回给客户端 | 高 |
|
|
607
|
+
| 文件名不安全 | 使用用户原始文件名做存储路径 | 高 |
|
|
596
608
|
| 物理删除 | `session.delete()` 用于业务数据 | 中 |
|
|
597
609
|
| Redis 无 TTL | `redis.set()` 没有 `ex` 参数 | 中 |
|
|
598
|
-
| 文件名不安全 | 使用用户原始文件名做存储路径 | 高 |
|
|
599
|
-
| DolphinDB 拼接 | 用户输入直接进 DolphinDB 脚本 | 致命 |
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Git Commit 强制规范
|
|
2
|
+
|
|
3
|
+
**每次 `git commit` 前必须完整执行以下检查流程,不可跳过任何步骤。**
|
|
4
|
+
|
|
5
|
+
## 提交前强制检查流程
|
|
6
|
+
|
|
7
|
+
执行 `git commit` 前,按顺序完成以下 4 步。任何一步未通过则 **STOP,不得提交**。
|
|
8
|
+
|
|
9
|
+
### Step 1: 分析变更内容
|
|
10
|
+
|
|
11
|
+
运行 `git diff --cached` 查看暂存区,回答以下问题:
|
|
12
|
+
|
|
13
|
+
- 这次变更做了几件事?
|
|
14
|
+
- 涉及哪些模块/目录?
|
|
15
|
+
|
|
16
|
+
**如果做了多件事** → STOP,必须拆成多个 commit。判断标准:能否用一个 ≤ 72 字符的 subject 清晰描述?不能就必须拆。
|
|
17
|
+
|
|
18
|
+
### Step 2: 确定 scope
|
|
19
|
+
|
|
20
|
+
读取当前项目 CLAUDE.md,查找 `## Git Commit Scope` 段落:
|
|
21
|
+
|
|
22
|
+
- **找到了** → scope 必须从其中定义的枚举值中选取,不得自造
|
|
23
|
+
- **没找到** → 提醒用户:「当前项目 CLAUDE.md 未定义 Git Commit Scope,建议添加。需要我帮你加吗?」,然后 scope 可省略
|
|
24
|
+
|
|
25
|
+
scope 使用规则:
|
|
26
|
+
- 变更仅涉及单个模块 → **必须**带 scope
|
|
27
|
+
- 变更跨多个模块 → 省略 scope
|
|
28
|
+
|
|
29
|
+
### Step 3: 生成 commit message
|
|
30
|
+
|
|
31
|
+
格式必须严格匹配:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
<type>(<scope>): <subject>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
或(无 scope 时):
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
<type>: <subject>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**type 只能从以下枚举中选取:**
|
|
44
|
+
|
|
45
|
+
| type | 用途 |
|
|
46
|
+
|------|------|
|
|
47
|
+
| feat | 新功能 |
|
|
48
|
+
| fix | 修复 bug |
|
|
49
|
+
| refactor | 重构(不改变外部行为) |
|
|
50
|
+
| chore | 构建/依赖/配置/发版等杂务 |
|
|
51
|
+
| docs | 文档变更 |
|
|
52
|
+
| test | 测试新增或修改 |
|
|
53
|
+
| perf | 性能优化 |
|
|
54
|
+
| style | 代码格式调整(不影响逻辑) |
|
|
55
|
+
| ci | CI/CD 配置变更 |
|
|
56
|
+
|
|
57
|
+
**subject 强制要求:**
|
|
58
|
+
|
|
59
|
+
- **中文**描述
|
|
60
|
+
- 不加句号
|
|
61
|
+
- ≤ 72 字符
|
|
62
|
+
- 用简洁的动宾短语:`添加`、`修复`、`移除`、`重构`、`升级`
|
|
63
|
+
|
|
64
|
+
**body(可选):**
|
|
65
|
+
|
|
66
|
+
- 空一行后写
|
|
67
|
+
- 中文,只写 why(动机、背景),不复述 what
|
|
68
|
+
- 破坏性变更加 `BREAKING CHANGE:` 前缀
|
|
69
|
+
|
|
70
|
+
### Step 4: 自检验证
|
|
71
|
+
|
|
72
|
+
生成 commit message 后,逐条验证:
|
|
73
|
+
|
|
74
|
+
- [ ] type 在枚举表中?
|
|
75
|
+
- [ ] scope 符合项目 CLAUDE.md 定义(或正确省略)?
|
|
76
|
+
- [ ] subject 是中文、无句号、≤ 72 字符、简洁动宾短语?
|
|
77
|
+
- [ ] 一个 commit 只做一件事,没有混合不同 type 的变更?
|
|
78
|
+
- [ ] 没有混合不同 scope 的独立变更?
|
|
79
|
+
|
|
80
|
+
**全部通过 → 执行 commit。任何一条未通过 → 修正后重新验证。**
|
|
81
|
+
|
|
82
|
+
## 常见错误(必须避免)
|
|
83
|
+
|
|
84
|
+
| 错误 | 正确 |
|
|
85
|
+
|------|------|
|
|
86
|
+
| `feat: add user login`(英文) | `feat: 添加用户登录功能`(中文) |
|
|
87
|
+
| `fix(eui): 修复了按钮样式。` | `fix(eui): 修复按钮样式`(无句号、不用「了」) |
|
|
88
|
+
| `feat: 添加登录功能并修复登出 bug` | 拆成两个 commit |
|
|
89
|
+
| `update: 修改配置` | `update` 不在 type 枚举中,应为 `chore` |
|
|
90
|
+
| `feat(auth): 添加 JWT 刷新`(项目 scope 枚举无 auth) | 使用项目定义的 scope 值 |
|
|
91
|
+
|
|
92
|
+
## 正确示例
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
feat(eui): 添加 Image 组件,支持懒加载
|
|
96
|
+
|
|
97
|
+
fix: 修复 token 刷新竞态条件
|
|
98
|
+
|
|
99
|
+
refactor(backend): 提取分页逻辑为共享工具
|
|
100
|
+
|
|
101
|
+
chore: 升级 Vite 至 8.x
|
|
102
|
+
|
|
103
|
+
feat(eui)!: 重命名 EDialog open 属性为 v-model:open
|
|
104
|
+
|
|
105
|
+
BREAKING CHANGE: EDialog 不再接受 `visible` 属性,请改用 `v-model:open`。
|
|
106
|
+
```
|
|
@@ -845,6 +845,29 @@ user = cache.get_user(user_id)
|
|
|
845
845
|
async def create_user(body: UserCreate) -> UserResponse:
|
|
846
846
|
"""根据提交的信息创建新用户,邮箱不可重复。"""
|
|
847
847
|
...
|
|
848
|
+
|
|
849
|
+
## 代码自检(写代码时强制执行)
|
|
850
|
+
|
|
851
|
+
**每次生成或修改 Python 代码后,必须逐条验证以下清单。任何一条未通过 → STOP,立即修正后再继续。**
|
|
852
|
+
|
|
853
|
+
| # | 检查项 | 违规即 STOP |
|
|
854
|
+
|---|--------|------------|
|
|
855
|
+
| 1 | 所有公开函数有参数 + 返回值类型标注 | ✓ |
|
|
856
|
+
| 2 | 无 `Any` 类型(除非有注释说明原因) | ✓ |
|
|
857
|
+
| 3 | 使用 `list[int]` / `str \| None` 等现代语法,不用 `typing.List` / `Optional` | ✓ |
|
|
858
|
+
| 4 | service 层不抛 `HTTPException`,只抛业务异常 | ✓ |
|
|
859
|
+
| 5 | 无裸 `except:` 或 `except Exception: pass` | ✓ |
|
|
860
|
+
| 6 | 路由函数只做参数接收 → 调用 service → 返回结果,无业务逻辑 | ✓ |
|
|
861
|
+
| 7 | HTTP 请求用 `httpx`,不用 `requests` | ✓ |
|
|
862
|
+
| 8 | 日志用 `%s` 占位符或 structlog,不用 f-string | ✓ |
|
|
863
|
+
| 9 | 生命周期用 `lifespan`,不用 `@app.on_event` | ✓ |
|
|
864
|
+
| 10 | 无可变默认参数 `def f(items=[])` | ✓ |
|
|
865
|
+
| 11 | Pydantic Schema 请求/响应分离,不复用 | ✓ |
|
|
866
|
+
| 12 | 嵌套不超过 3 层,函数体不超过 50 行 | ✓ |
|
|
867
|
+
| 13 | 所有模块/类/函数有 docstring(Google 风格) | ✓ |
|
|
868
|
+
| 14 | 依赖通过 `Depends()` 注入,不在路由中直接创建 | ✓ |
|
|
869
|
+
|
|
870
|
+
**不执行自检就提交代码 = 违规。**
|
|
848
871
|
```
|
|
849
872
|
|
|
850
873
|
## 十九、安全编码
|
|
@@ -713,3 +713,26 @@ import { UserInfo, getUsers } from '@/api/user'
|
|
|
713
713
|
| `reactive()` 用于简单值 | `ref()` 用于所有场景 |
|
|
714
714
|
| 解构 store 不用 `storeToRefs` | 响应式值必须用 `storeToRefs` |
|
|
715
715
|
| 手写 CSS 为主 | Tailwind 工具类为主 |
|
|
716
|
+
|
|
717
|
+
## 代码自检(写代码时强制执行)
|
|
718
|
+
|
|
719
|
+
**每次生成或修改 Vue/TypeScript 代码后,必须逐条验证以下清单。任何一条未通过 → STOP,立即修正后再继续。**
|
|
720
|
+
|
|
721
|
+
| # | 检查项 | 违规即 STOP |
|
|
722
|
+
|---|--------|------------|
|
|
723
|
+
| 1 | 使用 `<script setup lang="ts">`,不是 Options API | ✓ |
|
|
724
|
+
| 2 | Props 用 `defineProps<{}>()`,Emits 用 `defineEmits<{}>()` | ✓ |
|
|
725
|
+
| 3 | 无 `any` 类型(除非有注释说明原因) | ✓ |
|
|
726
|
+
| 4 | `ref()` 复杂类型有泛型标注(`ref<T>` 而非 `ref(null)`) | ✓ |
|
|
727
|
+
| 5 | Pinia 使用 Setup Store,不是 Options Store | ✓ |
|
|
728
|
+
| 6 | Store 解构用 `storeToRefs`(响应式值),方法直接解构 | ✓ |
|
|
729
|
+
| 7 | 类型导入用 `import type { ... }` | ✓ |
|
|
730
|
+
| 8 | 路由组件使用 `() => import()` 懒加载 | ✓ |
|
|
731
|
+
| 9 | API 调用通过 `api/` 模块,未在组件中直接 `axios.get` | ✓ |
|
|
732
|
+
| 10 | 布尔变量有 `is/has/can/should` 前缀 | ✓ |
|
|
733
|
+
| 11 | 样式以 Tailwind 为主,非必要不写 scoped CSS | ✓ |
|
|
734
|
+
| 12 | 无 `v-if` + `v-for` 同元素 | ✓ |
|
|
735
|
+
| 13 | 模板无复杂表达式,已提取为 `computed` | ✓ |
|
|
736
|
+
| 14 | 枚举用联合类型 `type X = 'a' | 'b'`,不用 `enum` | ✓ |
|
|
737
|
+
|
|
738
|
+
**不执行自检就提交代码 = 违规。**
|
|
@@ -10,6 +10,26 @@
|
|
|
10
10
|
}
|
|
11
11
|
]
|
|
12
12
|
}
|
|
13
|
+
],
|
|
14
|
+
"PostToolUse": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "Edit",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "bash ~/.claude/hooks/post-sync-claude-global.sh"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"matcher": "Write",
|
|
26
|
+
"hooks": [
|
|
27
|
+
{
|
|
28
|
+
"type": "command",
|
|
29
|
+
"command": "bash ~/.claude/hooks/post-sync-claude-global.sh"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
13
33
|
]
|
|
14
34
|
}
|
|
15
35
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dwy-dev-qa
|
|
3
|
+
description: "功能开发完成后的通用质量保障流程。触发条件:完成新功能、修复 bug、重构代码后,准备提交前。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 开发完成后质量保障流程
|
|
7
|
+
|
|
8
|
+
功能开发完成后,按以下 9 步流程逐步执行。**不可跳步,不可调换顺序。**
|
|
9
|
+
|
|
10
|
+
## 流程总览
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
功能完成 → 构建验证 → 写测试 → 跑测试 → Code Review → 修复问题 → 性能优化 → 文档同步 → 集成测试 → 输出报告
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## 第 1 步:构建验证
|
|
17
|
+
|
|
18
|
+
确认代码能编译通过,没有语法错误或类型错误。
|
|
19
|
+
|
|
20
|
+
执行项目的构建命令(查看 `package.json` scripts 或 `Makefile` 确定具体命令)。
|
|
21
|
+
|
|
22
|
+
**不通过 → 修复编译错误,不进入下一步。**
|
|
23
|
+
|
|
24
|
+
## 第 2 步:编写测试用例
|
|
25
|
+
|
|
26
|
+
为本次新增/修改的代码编写测试:
|
|
27
|
+
|
|
28
|
+
- 新组件/模块:至少覆盖核心功能、关键输入输出
|
|
29
|
+
- 新函数:覆盖正常输入、边界条件、异常输入
|
|
30
|
+
- Bug 修复:先写复现 bug 的测试用例,确认失败,再确认修复后通过
|
|
31
|
+
- 只测新增/修改的部分,不给未改动的代码补测试
|
|
32
|
+
|
|
33
|
+
## 第 3 步:运行测试
|
|
34
|
+
|
|
35
|
+
执行项目的测试命令,确认所有测试通过。
|
|
36
|
+
|
|
37
|
+
**有失败 → 修复代码或测试,不进入下一步。**
|
|
38
|
+
|
|
39
|
+
## 第 4 步:Code Review
|
|
40
|
+
|
|
41
|
+
审查本次所有变更(代码 + 测试),检查:
|
|
42
|
+
|
|
43
|
+
- [ ] 逻辑正确性:边界条件、竞态风险、空值处理
|
|
44
|
+
- [ ] 安全性:XSS、注入、硬编码凭证、敏感数据泄露
|
|
45
|
+
- [ ] 向后兼容:已有 API 是否被破坏(参数重命名/删除、返回值结构变更)
|
|
46
|
+
- [ ] 代码风格:是否符合项目规范
|
|
47
|
+
- [ ] 测试质量:测试是否真正验证了功能
|
|
48
|
+
|
|
49
|
+
输出 Review 问题清单。
|
|
50
|
+
|
|
51
|
+
## 第 5 步:修复 Review 问题
|
|
52
|
+
|
|
53
|
+
逐条修复第 4 步发现的问题。每修一条,跑相关测试确认无回归。
|
|
54
|
+
|
|
55
|
+
**有未修复的问题 → 不进入下一步。**
|
|
56
|
+
|
|
57
|
+
## 第 6 步:性能优化
|
|
58
|
+
|
|
59
|
+
审查本次变更的性能影响:
|
|
60
|
+
|
|
61
|
+
- [ ] 是否有不必要的重复计算或重复请求
|
|
62
|
+
- [ ] 是否有大数据集缺少分页、虚拟滚动或懒加载
|
|
63
|
+
- [ ] 是否有 N+1 查询或缺少索引
|
|
64
|
+
- [ ] 是否有不必要的深拷贝或大对象序列化
|
|
65
|
+
- [ ] 前端:是否有不必要的重渲染或未做 memo/computed 优化
|
|
66
|
+
|
|
67
|
+
发现优化点:
|
|
68
|
+
1. 实施优化
|
|
69
|
+
2. 跑测试确认无回归
|
|
70
|
+
3. 如果发现了通用的性能规范不在项目文档中,更新 CLAUDE.md 或 rules
|
|
71
|
+
|
|
72
|
+
## 第 7 步:文档同步
|
|
73
|
+
|
|
74
|
+
检查以下文档是否需要更新:
|
|
75
|
+
|
|
76
|
+
- [ ] **API 文档 / Skills** — 新增或修改了对外接口?更新对应文档
|
|
77
|
+
- [ ] **示例 / Demo** — 新增了用户可感知的功能?补充示例
|
|
78
|
+
- [ ] **项目 CLAUDE.md** — 模块结构、命令、架构发生变化?更新
|
|
79
|
+
- [ ] **导航 / 索引** — 新增了页面或模块?注册到路由和导航
|
|
80
|
+
|
|
81
|
+
如果项目有专门的文档检查 skill(如 `dwy-docs-check`),调用它自动执行。
|
|
82
|
+
|
|
83
|
+
## 第 8 步:集成测试
|
|
84
|
+
|
|
85
|
+
运行全量测试套件 + 构建验证,确认无回归。
|
|
86
|
+
|
|
87
|
+
**任何失败 → 回到第 5 步修复。**
|
|
88
|
+
|
|
89
|
+
## 第 9 步:输出报告
|
|
90
|
+
|
|
91
|
+
向用户输出以下报告,等待审查确认后才能 commit:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
## 质量保障报告
|
|
95
|
+
|
|
96
|
+
### 变更概要
|
|
97
|
+
- 涉及文件:X 个
|
|
98
|
+
- 新增/修改行数:+X / -X
|
|
99
|
+
|
|
100
|
+
### 测试结果
|
|
101
|
+
- 单元测试:X 通过 / X 失败
|
|
102
|
+
- 集成测试:全量 X 用例通过
|
|
103
|
+
|
|
104
|
+
### Code Review
|
|
105
|
+
- 发现问题:X 条
|
|
106
|
+
- 已修复:X 条
|
|
107
|
+
- 遗留:0 条
|
|
108
|
+
|
|
109
|
+
### 性能优化
|
|
110
|
+
- 优化项:(具体优化点,或"无需优化")
|
|
111
|
+
|
|
112
|
+
### 文档同步
|
|
113
|
+
- 更新了:(文件列表,或"无需更新")
|
|
114
|
+
|
|
115
|
+
### 待用户确认
|
|
116
|
+
- [ ] 确认可以提交
|
|
117
|
+
```
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dwy-release
|
|
3
|
+
description: "标准化发版流程:bump version → changelog → build → publish → git tag。触发条件:用户说'发版'、'发布'、'release'、'bump version' 时。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 标准化发版流程
|
|
7
|
+
|
|
8
|
+
通用的发版流程框架,项目特定的包名、路径、命令由 CLAUDE.md 的 `## Release` 段落定义。
|
|
9
|
+
|
|
10
|
+
## 触发条件
|
|
11
|
+
|
|
12
|
+
用户要求发布包时("发版"、"发布"、"release"、"bump version")。
|
|
13
|
+
|
|
14
|
+
## 第 0 步:检查项目 Release 配置
|
|
15
|
+
|
|
16
|
+
**在执行任何操作前**,检查当前项目的 CLAUDE.md 是否包含 `## Release` 段落:
|
|
17
|
+
|
|
18
|
+
- **有** → 读取其中的包列表、版本文件路径、构建命令、发布命令、依赖顺序等配置,按配置执行
|
|
19
|
+
- **没有** → **停止发版流程**,提醒用户:
|
|
20
|
+
|
|
21
|
+
> 「当前项目 CLAUDE.md 未定义 `## Release` 段落,无法执行发版流程。需要我帮你加吗?」
|
|
22
|
+
|
|
23
|
+
参考格式(提供给用户):
|
|
24
|
+
|
|
25
|
+
```markdown
|
|
26
|
+
## Release
|
|
27
|
+
|
|
28
|
+
### 包列表
|
|
29
|
+
|
|
30
|
+
| 包名 | scope | 版本文件 | 构建命令 | 发布命令 | 验证命令 |
|
|
31
|
+
|------|-------|---------|---------|---------|---------|
|
|
32
|
+
| @scope/pkg-a | pkg-a | packages/a/package.json | pnpm build:a | pnpm publish:a | npm view @scope/pkg-a version |
|
|
33
|
+
|
|
34
|
+
### 依赖顺序
|
|
35
|
+
|
|
36
|
+
多包发版时按此顺序执行:pkg-a → pkg-b → pkg-c
|
|
37
|
+
|
|
38
|
+
### Tag 命名
|
|
39
|
+
|
|
40
|
+
- 单包:`@scope/pkg-a@1.0.0`
|
|
41
|
+
- 仅一个包时可简化为:`v1.0.0`
|
|
42
|
+
|
|
43
|
+
### CHANGELOG
|
|
44
|
+
|
|
45
|
+
- 命令:`pnpm changelog`
|
|
46
|
+
- 工具:changelogen
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 发版前确认
|
|
50
|
+
|
|
51
|
+
询问用户:
|
|
52
|
+
|
|
53
|
+
1. **发哪个包?**(从 Release 配置的包列表中选,可多选)
|
|
54
|
+
2. **版本号?** patch / minor / major,或指定具体版本号
|
|
55
|
+
|
|
56
|
+
## 发版流程
|
|
57
|
+
|
|
58
|
+
### 1. Bump Version
|
|
59
|
+
|
|
60
|
+
根据 Release 配置中的版本文件路径,直接编辑 version 字段。
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# 读取当前版本(根据配置的版本文件)
|
|
64
|
+
# 计算新版本:patch=x.y.z+1, minor=x.y+1.0, major=x+1.0.0
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
不使用 `npm version`(避免自动 commit)。Python 项目编辑 `pyproject.toml` 中的 `version` 字段。
|
|
68
|
+
|
|
69
|
+
### 2. Generate CHANGELOG
|
|
70
|
+
|
|
71
|
+
执行 Release 配置中定义的 changelog 命令。检查生成内容,确认无误后继续。
|
|
72
|
+
|
|
73
|
+
### 3. Build
|
|
74
|
+
|
|
75
|
+
执行 Release 配置中对应包的构建命令。**构建必须成功才能继续。**
|
|
76
|
+
|
|
77
|
+
### 4. Commit + Tag
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# 暂存变更(version + changelog)
|
|
81
|
+
git add <changed-files>
|
|
82
|
+
|
|
83
|
+
# 提交(遵循 git-commit-convention)
|
|
84
|
+
git commit -m "chore(<scope>): release v<version>"
|
|
85
|
+
|
|
86
|
+
# 打 tag(按 Release 配置的命名规则)
|
|
87
|
+
git tag <tag-name>
|
|
88
|
+
|
|
89
|
+
# 推送
|
|
90
|
+
git push origin <branch> --tags
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 5. Publish
|
|
94
|
+
|
|
95
|
+
执行 Release 配置中对应包的发布命令。
|
|
96
|
+
|
|
97
|
+
### 6. 发版后验证
|
|
98
|
+
|
|
99
|
+
执行 Release 配置中对应包的验证命令,确认新版本已发布。
|
|
100
|
+
|
|
101
|
+
## 多包同时发版
|
|
102
|
+
|
|
103
|
+
按 Release 配置中定义的依赖顺序,每个包独立走完 bump → build → publish,最后统一 commit + tag + push。
|
|
104
|
+
|
|
105
|
+
## 禁止事项
|
|
106
|
+
|
|
107
|
+
- **禁止**跳过 build 直接 publish
|
|
108
|
+
- **禁止**忘记打 tag
|
|
109
|
+
- **禁止**publish 失败后不回滚 version 变更
|
|
110
|
+
- **禁止**在 CHANGELOG 未生成时发版
|
|
111
|
+
- **禁止**在无 Release 配置的情况下猜测发版命令
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# 文档同步规则
|
|
2
|
-
|
|
3
|
-
代码变更时,必须同步更新所有关联文档。不允许只改代码不更新文档。
|
|
4
|
-
|
|
5
|
-
## 核心原则
|
|
6
|
-
|
|
7
|
-
**代码和文档是一个整体。** 如果一次变更修改了对外可见的 API(props、函数签名、导出类型、命令行参数等),那么描述该 API 的文档必须在同一个 commit 中更新。
|
|
8
|
-
|
|
9
|
-
## 检查清单
|
|
10
|
-
|
|
11
|
-
完成代码变更后,逐项确认:
|
|
12
|
-
|
|
13
|
-
1. **Skills / 速查文档** — 是否有 SKILL.md 或类似的 AI 速查文档描述了被修改的 API?如果有,更新对应条目。
|
|
14
|
-
2. **示例 / Demo 页面** — 新增的功能是否有对应的交互演示?如果没有,补充 demo。
|
|
15
|
-
3. **导航 / 搜索索引** — 新增的页面或组件是否已注册到路由、侧边栏、搜索索引?
|
|
16
|
-
4. **项目 CLAUDE.md** — 模块结构(新增/删除/重命名包或模块)、构建命令、测试命令是否变化?如果是,更新 CLAUDE.md。
|
|
17
|
-
5. **版本号** — 变更是否对外可见?如果是,更新 package.json / pyproject.toml 版本号。
|
|
18
|
-
|
|
19
|
-
## 提交规范
|
|
20
|
-
|
|
21
|
-
- 文档更新应与代码变更在**同一个 commit** 中
|
|
22
|
-
- 遗漏后发现,立即补一个 `docs: sync xxx` 的 commit
|
|
23
|
-
- 纯文档更新用 `docs:` 前缀,代码+文档混合用 `feat:` / `fix:`
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: dwy-auto-sync
|
|
3
|
-
description: "create-dwy 发版后自动更新本地 CLI 并同步 Claude Code 配置。触发条件:执行了 npm publish create-dwy、pnpm publish:cli、或用户要求同步 dwy 配置时。"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# DWY 发版后自动同步
|
|
7
|
-
|
|
8
|
-
当 `create-dwy` 发布新版本后,必须执行以下步骤确保本地 Claude Code 配置与最新版本同步。
|
|
9
|
-
|
|
10
|
-
## 触发时机
|
|
11
|
-
|
|
12
|
-
以下任一情况发生时,执行同步流程:
|
|
13
|
-
|
|
14
|
-
1. 执行了 `npm publish`(在 claude-cli 目录下)
|
|
15
|
-
2. 执行了 `pnpm publish:cli`
|
|
16
|
-
3. 用户要求"同步 dwy"或"更新配置"
|
|
17
|
-
|
|
18
|
-
## 同步流程
|
|
19
|
-
|
|
20
|
-
发版成功后,按顺序执行:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
# 1. 更新全局 CLI 到最新版
|
|
24
|
-
npm i -g create-dwy@latest
|
|
25
|
-
|
|
26
|
-
# 2. 验证版本
|
|
27
|
-
dwy --version
|
|
28
|
-
|
|
29
|
-
# 3. 同步 Claude Code 配置(skills/rules/hooks/commands/settings)
|
|
30
|
-
dwy sync claude
|
|
31
|
-
|
|
32
|
-
# 4. 验证同步结果
|
|
33
|
-
ls ~/.claude/skills/
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## 同步了什么
|
|
37
|
-
|
|
38
|
-
`dwy sync claude` 会将以下内容从 CLI 模板同步到 `~/.claude/`:
|
|
39
|
-
|
|
40
|
-
| 目录 | 内容 | 同步方式 |
|
|
41
|
-
|------|------|---------|
|
|
42
|
-
| `~/.claude/skills/` | AI 速查文档 (dwy-frontend-eui, dwy-frontend-core, dwy-backend-base) | 覆盖同名,保留已有 |
|
|
43
|
-
| `~/.claude/rules/` | 编码规范 (python-code-style, vue-code-style, 安全规则等) | 覆盖同名,保留已有 |
|
|
44
|
-
| `~/.claude/hooks/` | 自动化脚本 (pre-git-commit 检查) | 覆盖同名,保留已有 |
|
|
45
|
-
| `~/.claude/commands/` | 自定义命令 | 覆盖同名,保留已有 |
|
|
46
|
-
| `~/.claude/settings.json` | Claude Code 设置 | 浅合并(新 key 加入,同名覆盖,已有独有 key 保留) |
|
|
47
|
-
|
|
48
|
-
## 注意事项
|
|
49
|
-
|
|
50
|
-
- npm 注册表有传播延迟(~1 分钟),如果 `npm i -g create-dwy@latest` 安装的不是刚发布的版本,等待后重试
|
|
51
|
-
- `dwy sync claude` 从 Gitee 仓库拉取模板,确保代码已 push 到 Gitee 后再执行
|
|
52
|
-
- 同步不会删除用户手动添加的 skills/rules,只覆盖同名文件
|