ai-engineering-init 1.5.0 → 1.7.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 (109) hide show
  1. package/.claude/agents/code-reviewer.md +3 -130
  2. package/.claude/hooks/skill-forced-eval.js +2 -0
  3. package/.claude/hooks/stop.js +24 -1
  4. package/.claude/skills/codex-code-review/SKILL.md +327 -0
  5. package/.claude/skills/leniu-report-customization/SKILL.md +82 -2
  6. package/.claude/skills/leniu-report-standard-customization/SKILL.md +65 -2
  7. package/.claude/skills/loki-log-query/SKILL.md +400 -0
  8. package/.claude/skills/mysql-debug/SKILL.md +58 -22
  9. package/.claude/skills/skill-creator/LICENSE.txt +202 -0
  10. package/.claude/skills/skill-creator/SKILL.md +479 -0
  11. package/.claude/skills/skill-creator/agents/analyzer.md +274 -0
  12. package/.claude/skills/skill-creator/agents/comparator.md +202 -0
  13. package/.claude/skills/skill-creator/agents/grader.md +223 -0
  14. package/.claude/skills/skill-creator/assets/eval_review.html +146 -0
  15. package/.claude/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  16. package/.claude/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  17. package/.claude/skills/skill-creator/references/schemas.md +430 -0
  18. package/.claude/skills/skill-creator/scripts/__init__.py +0 -0
  19. package/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  20. package/.claude/skills/skill-creator/scripts/generate_report.py +326 -0
  21. package/.claude/skills/skill-creator/scripts/improve_description.py +248 -0
  22. package/.claude/skills/skill-creator/scripts/package_skill.py +136 -0
  23. package/.claude/skills/skill-creator/scripts/quick_validate.py +103 -0
  24. package/.claude/skills/skill-creator/scripts/run_eval.py +310 -0
  25. package/.claude/skills/skill-creator/scripts/run_loop.py +332 -0
  26. package/.claude/skills/skill-creator/scripts/utils.py +47 -0
  27. package/.claude/skills/sync-back-merge/SKILL.md +66 -0
  28. package/.claude/skills/yunxiao-task-management/SKILL.md +489 -0
  29. package/.codex/skills/leniu-report-customization/SKILL.md +82 -2
  30. package/.codex/skills/leniu-report-standard-customization/SKILL.md +65 -2
  31. package/.codex/skills/loki-log-query/SKILL.md +400 -0
  32. package/.codex/skills/loki-log-query/environments.json +45 -0
  33. package/.codex/skills/mysql-debug/SKILL.md +58 -22
  34. package/.codex/skills/skill-creator/LICENSE.txt +202 -0
  35. package/.codex/skills/skill-creator/SKILL.md +479 -0
  36. package/.codex/skills/skill-creator/agents/analyzer.md +274 -0
  37. package/.codex/skills/skill-creator/agents/comparator.md +202 -0
  38. package/.codex/skills/skill-creator/agents/grader.md +223 -0
  39. package/.codex/skills/skill-creator/assets/eval_review.html +146 -0
  40. package/.codex/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  41. package/.codex/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  42. package/.codex/skills/skill-creator/references/schemas.md +430 -0
  43. package/.codex/skills/skill-creator/scripts/__init__.py +0 -0
  44. package/.codex/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  45. package/.codex/skills/skill-creator/scripts/generate_report.py +326 -0
  46. package/.codex/skills/skill-creator/scripts/improve_description.py +248 -0
  47. package/.codex/skills/skill-creator/scripts/package_skill.py +136 -0
  48. package/.codex/skills/skill-creator/scripts/quick_validate.py +103 -0
  49. package/.codex/skills/skill-creator/scripts/run_eval.py +310 -0
  50. package/.codex/skills/skill-creator/scripts/run_loop.py +332 -0
  51. package/.codex/skills/skill-creator/scripts/utils.py +47 -0
  52. package/.codex/skills/sync-back-merge/SKILL.md +66 -0
  53. package/.codex/skills/yunxiao-task-management/SKILL.md +489 -0
  54. package/.cursor/hooks/stop.js +23 -1
  55. package/.cursor/skills/leniu-report-customization/SKILL.md +82 -2
  56. package/.cursor/skills/leniu-report-standard-customization/SKILL.md +65 -2
  57. package/.cursor/skills/loki-log-query/SKILL.md +400 -0
  58. package/.cursor/skills/loki-log-query/environments.json +45 -0
  59. package/.cursor/skills/mysql-debug/SKILL.md +58 -22
  60. package/.cursor/skills/skill-creator/LICENSE.txt +202 -0
  61. package/.cursor/skills/skill-creator/SKILL.md +479 -0
  62. package/.cursor/skills/skill-creator/agents/analyzer.md +274 -0
  63. package/.cursor/skills/skill-creator/agents/comparator.md +202 -0
  64. package/.cursor/skills/skill-creator/agents/grader.md +223 -0
  65. package/.cursor/skills/skill-creator/assets/eval_review.html +146 -0
  66. package/.cursor/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  67. package/.cursor/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  68. package/.cursor/skills/skill-creator/references/schemas.md +430 -0
  69. package/.cursor/skills/skill-creator/scripts/__init__.py +0 -0
  70. package/.cursor/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  71. package/.cursor/skills/skill-creator/scripts/generate_report.py +326 -0
  72. package/.cursor/skills/skill-creator/scripts/improve_description.py +248 -0
  73. package/.cursor/skills/skill-creator/scripts/package_skill.py +136 -0
  74. package/.cursor/skills/skill-creator/scripts/quick_validate.py +103 -0
  75. package/.cursor/skills/skill-creator/scripts/run_eval.py +310 -0
  76. package/.cursor/skills/skill-creator/scripts/run_loop.py +332 -0
  77. package/.cursor/skills/skill-creator/scripts/utils.py +47 -0
  78. package/.cursor/skills/sync-back-merge/SKILL.md +66 -0
  79. package/.cursor/skills/yunxiao-task-management/SKILL.md +489 -0
  80. package/README.md +20 -236
  81. package/bin/index.js +1040 -28
  82. package/package.json +1 -1
  83. package/src/platform-map.json +4 -0
  84. package/src/skills/codex-code-review/SKILL.md +261 -69
  85. package/src/skills/leniu-report-customization/SKILL.md +82 -2
  86. package/src/skills/leniu-report-standard-customization/SKILL.md +65 -2
  87. package/src/skills/loki-log-query/SKILL.md +400 -0
  88. package/src/skills/loki-log-query/environments.json +45 -0
  89. package/src/skills/mysql-debug/SKILL.md +58 -22
  90. package/src/skills/skill-creator/LICENSE.txt +202 -0
  91. package/src/skills/skill-creator/SKILL.md +479 -0
  92. package/src/skills/skill-creator/agents/analyzer.md +274 -0
  93. package/src/skills/skill-creator/agents/comparator.md +202 -0
  94. package/src/skills/skill-creator/agents/grader.md +223 -0
  95. package/src/skills/skill-creator/assets/eval_review.html +146 -0
  96. package/src/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  97. package/src/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  98. package/src/skills/skill-creator/references/schemas.md +430 -0
  99. package/src/skills/skill-creator/scripts/__init__.py +0 -0
  100. package/src/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  101. package/src/skills/skill-creator/scripts/generate_report.py +326 -0
  102. package/src/skills/skill-creator/scripts/improve_description.py +248 -0
  103. package/src/skills/skill-creator/scripts/package_skill.py +136 -0
  104. package/src/skills/skill-creator/scripts/quick_validate.py +103 -0
  105. package/src/skills/skill-creator/scripts/run_eval.py +310 -0
  106. package/src/skills/skill-creator/scripts/run_loop.py +332 -0
  107. package/src/skills/skill-creator/scripts/utils.py +47 -0
  108. package/src/skills/sync-back-merge/SKILL.md +66 -0
  109. package/src/skills/yunxiao-task-management/SKILL.md +489 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-engineering-init",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "AI 工程化配置初始化工具 — 一键为 Claude Code、OpenAI Codex 等 AI 工具初始化 Skills 和项目规范",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -51,6 +51,10 @@
51
51
  "leniu-java-code-style": {
52
52
  "platforms": ["codex", "cursor"],
53
53
  "note": "代码风格规范,Codex 和 Cursor 平台使用"
54
+ },
55
+ "skill-creator": {
56
+ "platforms": ["codex", "cursor"],
57
+ "note": "技能创建元技能,Claude 平台有内置 add-skill,仅分发到 Codex 和 Cursor"
54
58
  }
55
59
  }
56
60
  }
@@ -1,32 +1,30 @@
1
1
  ---
2
2
  name: codex-code-review
3
3
  description: |
4
- Codex 代码审查工作流。在代码实现或 Bug 修复完成后,调用 Codex CLI 进行代码审查,展示审查结果,用户确认后自动修复问题。
4
+ 代码审查工作流。分两阶段:先执行本地规范检查(Grep 即时完成)+ 代码逻辑审查(Read 逐文件),再可选调用 Codex CLI 深度审查。
5
5
 
6
6
  触发场景:
7
7
  - /dev 或 /crud 命令完成代码生成后
8
8
  - Bug 修复完成后
9
- - 用户说"审查代码"、"review"、"代码审查"、"codex审查"
9
+ - 用户说"审查代码"、"review"、"代码审查"、"检查代码"
10
10
  - 用户说"检查一下刚写的代码"
11
+ - Stop Hook 提示后用户输入"review"
11
12
 
12
- 触发词:codex审查、代码审查、review代码、审查代码、codex review、代码review
13
+ 触发词:代码审查、review、审查代码、检查代码、code review、代码质量、codex审查、codex review
13
14
  ---
14
15
 
15
- # Codex 代码审查工作流
16
+ # 代码审查工作流
16
17
 
17
- > 依赖 `collaborating-with-codex` skill `codex_bridge.py` 脚本。
18
-
19
- ## 工作流
18
+ > 两阶段审查:**本地检查**(规范 + 逻辑) + **Codex 深度审查**(可选)。
20
19
 
21
- ### Phase 1: 收集变更范围
20
+ ## Phase 1: 收集变更范围
22
21
 
23
22
  ```bash
24
- # 获取当前未提交的变更文件
25
23
  git diff --name-only HEAD
26
24
  git diff --cached --name-only
27
25
  ```
28
26
 
29
- 如果没有变更文件,提示用户"没有检测到代码变更"并终止。
27
+ 如果没有变更文件,提示"没有检测到代码变更"并终止。
30
28
 
31
29
  将变更文件按类型分组:
32
30
  - **Java 文件**:Controller / Business / Service / Mapper / Entity / VO / DTO
@@ -34,12 +32,216 @@ git diff --cached --name-only
34
32
  - **SQL 文件**:建表/变更脚本
35
33
  - **其他**:配置文件等
36
34
 
37
- ### Phase 2: 调用 Codex 审查
35
+ ---
36
+
37
+ ## Phase 2: 本地检查(必做)
38
38
 
39
- 针对变更的 Java 文件,构造审查 PROMPT:
39
+ 分两步执行:**Step A** Grep 批量扫描规范问题(秒级),**Step B** 用 Read 逐文件审查代码逻辑。
40
40
 
41
+ ### Step A: 项目规范扫描(Grep 批量检查)
42
+
43
+ #### 🔴 A1. 包名规范
41
44
  ```bash
42
- python .claude/skills/collaborating-with-codex/scripts/codex_bridge.py \
45
+ Grep pattern: "package org\.dromara\." path: [目标目录] glob: "*.java"
46
+ ```
47
+ - ❌ `package org.dromara.xxx` → ✅ `package net.xnzn.core.xxx`
48
+
49
+ #### 🔴 A2. 禁止 RuoYi 工具类
50
+ ```bash
51
+ Grep pattern: "MapstructUtils" path: [目标目录] glob: "*.java"
52
+ Grep pattern: "ServiceException" path: [目标目录] glob: "*.java"
53
+ Grep pattern: "import javax\.validation" path: [目标目录] glob: "*.java"
54
+ ```
55
+ - ❌ `MapstructUtils` → ✅ `BeanUtil.copyProperties()`
56
+ - ❌ `ServiceException` → ✅ `LeException`
57
+ - ❌ `javax.validation.*` → ✅ `jakarta.validation.*`(JDK 21)
58
+
59
+ #### 🔴 A3. 审计字段名称
60
+ ```bash
61
+ Grep pattern: "private.*createBy|private.*updateBy|private.*createTime|private.*updateTime" path: [目标目录] glob: "*.java"
62
+ ```
63
+ - ❌ `createBy/updateBy/createTime/updateTime` → ✅ `crby/upby/crtime/uptime`
64
+
65
+ #### 🔴 A4. del_flag 值语义
66
+ ```bash
67
+ Grep pattern: "delFlag.*=.*0|del_flag.*=.*0" path: [目标目录] glob: "*.java"
68
+ ```
69
+ - ❌ `delFlag = 0`(RuoYi 正常值) → ✅ `delFlag = 2`(leniu 正常值,1=删除)
70
+
71
+ #### 🔴 A5. Entity 不含 tenant_id
72
+ ```bash
73
+ Grep pattern: "tenantId|tenant_id" path: [目标目录] glob: "*.java"
74
+ ```
75
+ - ❌ 双库物理隔离,无需 `tenant_id` 字段
76
+
77
+ #### 🔴 A6. 禁止 Map 传递业务数据
78
+ ```bash
79
+ Grep pattern: "Map<String,\s*Object>" path: [目标目录] glob: "*.java"
80
+ ```
81
+ - ❌ `Map<String, Object>` → ✅ 使用 VO/DTO 类
82
+
83
+ #### 🟡 A7. 事务注解缺少 rollbackFor
84
+ ```bash
85
+ Grep pattern: "@Transactional\b" path: [目标目录] glob: "*.java"
86
+ # 对命中文件二次检查:是否缺少 rollbackFor
87
+ Grep pattern: "@Transactional\((?!.*rollbackFor)" path: [命中文件]
88
+ ```
89
+ - ❌ `@Transactional` → ✅ `@Transactional(rollbackFor = Exception.class)`
90
+
91
+ #### 🟡 A8. 请求体封装
92
+ ```bash
93
+ Grep pattern: "@RequestBody [^L]" path: [目标目录] glob: "*Controller.java"
94
+ ```
95
+ - 建议 POST 请求使用 `@RequestBody LeRequest<T>` 封装
96
+
97
+ #### 🟡 A9. 金额类型错误
98
+ ```bash
99
+ Grep pattern: "Double|Float|double|float" path: [目标目录] glob: "*.java"
100
+ # 在命中行中检查是否涉及金额字段(amount/price/money/fee/cost)
101
+ ```
102
+ - ❌ `Double/Float` 处理金额 → ✅ `Long`(分)或 `BigDecimal`
103
+
104
+ #### 🟡 A10. BigDecimal 比较错误
105
+ ```bash
106
+ Grep pattern: "BigDecimal.*==|==.*BigDecimal" path: [目标目录] glob: "*.java"
107
+ ```
108
+ - ❌ `bigDecimal1 == bigDecimal2` → ✅ `bigDecimal1.compareTo(bigDecimal2) == 0`
109
+
110
+ #### 🟡 A11. SELECT * 查询
111
+ ```bash
112
+ Grep pattern: "SELECT \*|select \*" path: [目标目录] glob: "*.xml"
113
+ ```
114
+ - ❌ `SELECT *` → ✅ 明确列出需要的字段
115
+
116
+ #### 🟡 A12. SQL 注入风险
117
+ ```bash
118
+ Grep pattern: '\$\{' path: [目标目录] glob: "*.xml"
119
+ ```
120
+ - ❌ `${}` 拼接参数 → ✅ `#{}` 参数化查询(ORDER BY 等特殊场景除外)
121
+
122
+ #### 🟡 A13. 国际化异常
123
+ ```bash
124
+ Grep pattern: 'new LeException\("[^"]*[\u4e00-\u9fa5]' path: [目标目录] glob: "*.java"
125
+ ```
126
+ - 建议使用 `I18n.getMessage()` 替代硬编码中文
127
+
128
+ ---
129
+
130
+ ### Step B: 代码逻辑审查(Read 逐文件检查)
131
+
132
+ 对每个变更的 Java 文件执行 Read,按以下清单逐项审查。
133
+
134
+ #### Java 必检项(所有 Java 文件)
135
+
136
+ | # | 检查项 | 检查要点 | 严重级 |
137
+ |---|--------|---------|--------|
138
+ | B1 | **空指针风险** | `selectOne`/`getOne`/`selectById` 返回值是否有 null 判断;Optional 是否正确处理 | 🔴 |
139
+ | B2 | **参数校验** | 入参是否校验非空和合法性(`@NotNull`/`@NotEmpty`/`Objects.requireNonNull`/手动 if 判断) | 🔴 |
140
+ | B3 | **并发安全** | 查询+新增/查询+更新的组合操作是否有竞态条件;是否需要分布式锁 | 🔴 |
141
+ | B4 | **事务边界** | 多表写操作是否加了 `@Transactional(rollbackFor = Exception.class)` | 🔴 |
142
+ | B5 | **资源关闭** | Stream/IO流/数据库连接是否用 try-with-resources 或 finally 关闭 | 🔴 |
143
+ | B6 | **集合并发修改** | `forEach` 内是否有 remove/add 操作;应使用 `Iterator` 或 `removeIf` | 🔴 |
144
+ | B7 | **分页泄漏** | `PageMethod.startPage()` 是否紧贴查询语句,中间不能有其他 SQL 查询 | 🔴 |
145
+
146
+ #### Java 安全项
147
+
148
+ | # | 检查项 | 检查要点 | 严重级 |
149
+ |---|--------|---------|--------|
150
+ | B8 | **租户隔离(仅定时任务)** | 定时任务中是否使用 `Executors.doInTenant()`/`doInAllTenant()` 切换到商户库;普通接口默认在商户库,无需额外处理 | 🔴 |
151
+ | B9 | **SQL 注入** | 动态 SQL 是否使用参数化查询;拼接 SQL 是否转义 | 🔴 |
152
+ | B10 | **越权访问** | 删除/修改操作是否校验数据归属(检查 where 条件是否包含归属字段) | 🔴 |
153
+ | B11 | **敏感信息** | 日志中是否打印了密码、token、身份证、银行卡等敏感信息 | 🔴 |
154
+ | B12 | **批量操作限制** | 批量删除/更新是否限制了最大数量,防止误操作全表 | 🟡 |
155
+
156
+ #### Java 跨模块调用项
157
+
158
+ | # | 检查项 | 检查要点 | 严重级 |
159
+ |---|--------|---------|--------|
160
+ | B13 | **返回值兜底** | 返回 `List`/`Map` 时是否有空集合兜底(`Collections.emptyList()`),避免调用方 NPE | 🟡 |
161
+ | B14 | **集合参数防御** | 集合入参(`List`/`Set`)是否判空,空集合的 `IN()` 会导致 SQL 异常 | 🔴 |
162
+ | B15 | **异常透传** | 是否吞掉异常不抛出(空 catch 块);跨模块调用需要明确的异常传递 | 🔴 |
163
+ | B16 | **日志追踪** | 关键操作或异常分支是否有日志(`log.info`/`log.error`),便于跨模块问题排查 | 🟡 |
164
+
165
+ #### Java 代码规范项
166
+
167
+ | # | 检查项 | 检查要点 | 严重级 |
168
+ |---|--------|---------|--------|
169
+ | B17 | **魔法值** | 是否存在未定义的常量(状态码 1/2/3 必须用枚举,字符串必须定义常量) | 🟡 |
170
+ | B18 | **方法长度** | 方法是否过长(>50 行),需要拆分为子方法 | 🔵 |
171
+ | B19 | **注释完整性** | 公共 API(Controller/Business 方法)是否有 JavaDoc 注释 | 🔵 |
172
+ | B20 | **空 catch 块** | catch 块是否为空或仅打印日志而不处理/不抛出 | 🟡 |
173
+ | B21 | **过时 API** | 是否使用了 `@Deprecated` 的方法或类 | 🔵 |
174
+ | B22 | **返回值一致性** | Controller 层是否统一返回 `LeResponse<T>`,不能裸返回 | 🟡 |
175
+
176
+ ---
177
+
178
+ #### MyBatis XML 检查(仅 XML 文件)
179
+
180
+ | # | 检查项 | 检查要点 | 严重级 |
181
+ |---|--------|---------|--------|
182
+ | X1 | **SQL 注入** | 使用 `${}` 而非 `#{}` 进行参数拼接(ORDER BY 等场景需白名单校验) | 🔴 |
183
+ | X2 | **IN 查询防护** | IN 查询是否用 `<foreach>` 且考虑集合为空的情况(空 IN 会 SQL 异常) | 🔴 |
184
+ | X3 | **动态 SQL 语法** | `<if>`/`<where>`/`<choose>` 标签使用是否正确,是否会产生多余的 AND/OR | 🟡 |
185
+ | X4 | **SELECT *** | 是否使用 `SELECT *`,应明确列出需要的字段 | 🟡 |
186
+ | X5 | **缺少 WHERE** | UPDATE/DELETE 是否缺少 WHERE 条件(全表操作风险) | 🔴 |
187
+ | X6 | **索引失效** | WHERE 条件是否对索引字段使用了函数(`DATE(crtime)`)或隐式类型转换 | 🟡 |
188
+ | X7 | **LIKE 前模糊** | `LIKE '%xxx%'` 或 `LIKE CONCAT('%', #{}, '%')` 前模糊导致全表扫描 | 🟡 |
189
+ | X8 | **大表无分页** | 大表查询是否遗漏分页,可能造成 OOM | 🟡 |
190
+ | X9 | **namespace 匹配** | namespace 是否与 Mapper 接口全限定名完全匹配 | 🔴 |
191
+ | X10 | **resultMap 映射** | 是否正确定义 resultMap,字段名和属性名是否对应 | 🟡 |
192
+
193
+ ---
194
+
195
+ ### 本地检查结果展示
196
+
197
+ ```
198
+ # 代码审查报告
199
+
200
+ 审查范围: [变更文件列表]
201
+
202
+ ## 🔴 严重问题(X 项)
203
+ 1. [B1 空指针风险]
204
+ 文件: OrderServiceImpl.java:42
205
+ 问题: selectById 返回值未做 null 判断
206
+ 修复: if (ObjectUtil.isNull(entity)) throw new LeException("数据不存在");
207
+
208
+ 2. [A2 禁止 RuoYi 工具类]
209
+ 文件: UserServiceImpl.java:15
210
+ 问题: 使用了 MapstructUtils
211
+ 修复: 替换为 BeanUtil.copyProperties()
212
+
213
+ ## 🟡 警告问题(X 项)
214
+ ...
215
+
216
+ ## 🔵 建议(X 项)
217
+ ...
218
+
219
+ ## ✅ 通过项
220
+ - [x] A1 包名规范 (net.xnzn.core.*)
221
+ - [x] A3 审计字段正确 (crby/crtime/upby/uptime)
222
+ - [x] A4 del_flag 语义正确 (2=正常)
223
+ - [x] B8 租户隔离正确
224
+ ...
225
+
226
+ 结论: ✅ 通过 / ⚠️ 需修复 X 项 / ❌ 不通过
227
+ ```
228
+
229
+ 如果全部通过 → 展示"本地检查通过",询问是否需要 Codex 深度审查。
230
+ 如果有问题 → 先修复严重问题,修复后再询问是否需要 Codex 深度审查。
231
+
232
+ ---
233
+
234
+ ## Phase 3: Codex 深度审查(可选)
235
+
236
+ > 依赖 `collaborating-with-codex` skill 的 `codex_bridge.py` 脚本。
237
+ > Codex 擅长发现本地规则难以覆盖的**逻辑 Bug、复杂并发问题、架构缺陷**。
238
+
239
+ Phase 2 完成后询问用户:"是否需要 Codex 深度审查?"
240
+ - 用户同意 → 执行以下流程
241
+ - 用户拒绝 → 跳到 Phase 5
242
+
243
+ ```bash
244
+ python3 .claude/skills/collaborating-with-codex/scripts/codex_bridge.py \
43
245
  --cd . \
44
246
  --sandbox read-only \
45
247
  --PROMPT "Review the following changed files for code quality issues:
@@ -47,25 +249,34 @@ python .claude/skills/collaborating-with-codex/scripts/codex_bridge.py \
47
249
  FILES TO REVIEW:
48
250
  {变更文件列表,含相对路径}
49
251
 
50
- REVIEW CHECKLIST:
51
- 1. Bug risks: null pointer, off-by-one, resource leaks, concurrency issues
52
- 2. Security: SQL injection, XSS, missing auth checks, sensitive data exposure
53
- 3. Architecture: layer violations (Controller calling Mapper directly), missing Business layer for complex logic
54
- 4. Code quality: duplicate code, overly complex methods, missing error handling
55
- 5. Project conventions: wrong package name (must be net.xnzn.core.*), wrong audit fields (must use crby/crtime/upby/uptime), javax.validation (must use jakarta.validation)
252
+ REVIEW FOCUS (beyond basic lint):
253
+ 1. Logic bugs: race conditions, off-by-one, incorrect state transitions, edge cases
254
+ 2. Security: privilege escalation, data leakage across tenants, missing auth checks
255
+ 3. Architecture: Controller calling Mapper directly, Business layer bypassed, circular dependencies
256
+ 4. Performance: N+1 queries, missing pagination on large tables, unnecessary DB calls in loops
257
+ 5. Concurrency: check-then-act without locking, shared mutable state, CompletableFuture error handling
258
+
259
+ PROJECT CONTEXT:
260
+ - Package: net.xnzn.core.* (NOT org.dromara.*)
261
+ - 4-layer: Controller → Business → Service → Mapper
262
+ - Dual-database: tenant DB is default (by MERCHANT-ID header); only scheduled tasks need Executors.doInTenant()/doInAllTenant() to switch; Executors.doInSystem() for system DB access
263
+ - Audit fields: crby/crtime/upby/uptime
264
+ - del_flag: 1=deleted, 2=normal
265
+ - Exception: LeException (NOT ServiceException)
266
+ - Object copy: BeanUtil.copyProperties() (NOT MapstructUtils)
267
+ - Amount: stored as Long (fen/cents), NOT Double/Float
268
+ - Pagination: PageMethod.startPage() must be immediately before query
56
269
 
57
270
  OUTPUT FORMAT:
58
- For each issue found, output:
271
+ For each issue:
59
272
  - [SEVERITY] CRITICAL / WARNING / SUGGESTION
60
273
  - [FILE] filepath:line_number
61
- - [ISSUE] Brief description
274
+ - [ISSUE] Description
62
275
  - [FIX] Recommended fix
63
276
 
64
- If no issues found, output: ALL CLEAR - No issues detected.
277
+ If no issues: ALL CLEAR
65
278
 
66
- IMPORTANT LANGUAGE RULES:
67
- - All review comments MUST be in Chinese
68
- - File paths and code snippets remain in English"
279
+ IMPORTANT: All comments in Chinese, code/paths in English."
69
280
  ```
70
281
 
71
282
  **关键约束**:
@@ -73,63 +284,44 @@ IMPORTANT LANGUAGE RULES:
73
284
  - 变更文件过多时(>10 个),按模块分批审查
74
285
  - 使用 `run_in_background` 避免阻塞
75
286
 
76
- ### Phase 3: 展示审查结果
77
-
78
- 解析 Codex 返回的 JSON,提取 `agent_messages`,按严重程度分组展示:
79
-
80
- ```
81
- ## Codex 审查结果
82
-
83
- ### 🔴 严重问题 (CRITICAL)
84
- - `OrderInfoService.java:42` — 未做空值检查,可能 NPE
85
- 建议:添加 ObjectUtil.isNull() 判断
86
-
87
- ### 🟡 警告 (WARNING)
88
- - `OrderWebController.java:15` — 缺少 @RequiresAuthentication 注解
89
- 建议:添加认证注解
90
-
91
- ### 🔵 建议 (SUGGESTION)
92
- - `OrderDTO.java:8` — 字段命名可优化
93
- 建议:使用更具描述性的名称
94
-
95
287
  ---
96
- 是否需要修复以上问题?
97
- ```
98
-
99
- 如果结果为 `ALL CLEAR`,展示"审查通过,未发现问题"并终止。
100
288
 
101
- ### Phase 4: 用户确认后修复
289
+ ## Phase 4: 用户确认后修复
102
290
 
103
- 等待用户确认。用户可能:
104
- - **全部修复**:"修复所有问题" → 逐个修复所有 CRITICAL + WARNING
105
- - **选择性修复**:"只修复严重问题" → 仅修复 CRITICAL
291
+ 合并 Phase 2 和 Phase 3 的所有问题,等待用户确认:
292
+ - **全部修复**:"修复所有问题" → 逐个修复所有 🔴 + 🟡
293
+ - **选择性修复**:"只修复严重问题" → 仅修复 🔴
106
294
  - **跳过**:"不需要修复" → 终止
107
295
 
108
296
  修复时:
109
297
  1. 按文件逐个修复,使用 Edit 工具
110
298
  2. 每修复一个文件,简要说明改动
111
- 3. SUGGESTION 级别的问题默认跳过,除非用户明确要求
299
+ 3. 🔵 建议级别默认跳过,除非用户明确要求
112
300
  4. 修复完成后运行 `git diff` 展示所有变更
113
301
 
114
- ### Phase 5: 可选二次审查
302
+ ---
303
+
304
+ ## Phase 5: 最终确认
115
305
 
116
306
  修复完成后询问:"是否需要再次审查确认?"
117
307
  - 如果用户同意 → 回到 Phase 2 重新审查
118
- - 如果用户拒绝 → 终止
119
-
120
- ## 审查重点(leniu 项目特有)
121
-
122
- Codex PROMPT 中追加项目特有检查项:
308
+ - 如果用户拒绝 → 输出最终结论并终止
123
309
 
124
310
  ```
125
- PROJECT-SPECIFIC CHECKS:
126
- - Package must be net.xnzn.core.* (NOT org.dromara.*)
127
- - Audit fields: crby/crtime/upby/uptime (NOT createBy/createTime)
128
- - del_flag: 1=deleted, 2=normal (NOT 0=normal)
129
- - Use LeException (NOT ServiceException)
130
- - Use BeanUtil.copyProperties() (NOT MapstructUtils)
131
- - Use jakarta.validation.* (NOT javax.validation.*)
132
- - No tenant_id field in Entity (dual-database physical isolation)
133
- - Architecture: Controller → Business → Service → Mapper (4-layer)
134
- - No Map for business data transfer (use VO/DTO)
311
+ 结论: ✅ 通过 / ⚠️ 需修复 / ❌ 不通过
135
312
  ```
313
+
314
+ ---
315
+
316
+ ## 前端审查(如涉及前端文件变更)
317
+
318
+ 前端项目路径:`/Users/xujiajun/Developer/frontProj/web`
319
+
320
+ | # | 检查项 | 检查要点 |
321
+ |---|--------|---------|
322
+ | F1 | 响应码 | 成功码是 `10000`(不是 200) |
323
+ | F2 | Token | `Admin-Token`(localStorage) |
324
+ | F3 | 租户头 | `MERCHANT-ID`(请求头) |
325
+ | F4 | 金额显示 | 后端返回分,前端用 `money()` 转元 |
326
+ | F5 | 权限指令 | 按钮权限使用 `v-hasPerm` |
327
+ | F6 | 加密 | 敏感字段使用 SM4 加密 |
@@ -291,7 +291,83 @@ GROUP BY d.wallet_id
291
291
 
292
292
  ---
293
293
 
294
- ## 九、开发检查清单
294
+ ## 九、MySQL only_full_group_by 规范(必须遵守)
295
+
296
+ > 生产环境 MySQL 开启了 `sql_mode=only_full_group_by`,所有报表 SQL 必须满足此规则,否则报 `BadSqlGrammarException`。
297
+
298
+ ### 核心规则
299
+
300
+ **SELECT 中所有非聚合字段,必须出现在 GROUP BY 中,且表达式必须完全一致。**
301
+
302
+ ### 常见错误:GROUP BY 表达式与 SELECT 不一致
303
+
304
+ ```sql
305
+ -- ❌ 错误:SELECT 用 DATE_FORMAT,GROUP BY 用 DATE
306
+ SELECT
307
+ DATE_FORMAT(atr.trade_time, '%Y-%m-%d') AS statisticDate,
308
+ SUM(atr.amount) AS totalAmount
309
+ FROM acc_trade atr
310
+ GROUP BY DATE(atr.trade_time) -- ❌ 表达式不同,触发 only_full_group_by 报错
311
+ ORDER BY DATE(atr.trade_time) ASC
312
+
313
+ -- ✅ 正确:GROUP BY 与 SELECT 使用完全相同的表达式
314
+ SELECT
315
+ DATE_FORMAT(atr.trade_time, '%Y-%m-%d') AS statisticDate,
316
+ SUM(atr.amount) AS totalAmount
317
+ FROM acc_trade atr
318
+ GROUP BY DATE_FORMAT(atr.trade_time, '%Y-%m-%d') -- ✅ 与 SELECT 一致
319
+ ORDER BY DATE_FORMAT(atr.trade_time, '%Y-%m-%d') ASC
320
+ ```
321
+
322
+ ### 常见错误:SELECT 包含非聚合字段未加入 GROUP BY
323
+
324
+ ```sql
325
+ -- ❌ 错误:canteen_name 未在 GROUP BY 中
326
+ SELECT
327
+ DATE(pay_time) AS orderDate,
328
+ canteen_name, -- ❌ 非聚合字段,未在 GROUP BY
329
+ SUM(real_amount) AS netAmount
330
+ FROM report_order_info
331
+ GROUP BY DATE(pay_time), canteen_id
332
+
333
+ -- ✅ 正确:所有非聚合字段都加入 GROUP BY
334
+ SELECT
335
+ DATE(pay_time) AS orderDate,
336
+ canteen_name,
337
+ SUM(real_amount) AS netAmount
338
+ FROM report_order_info
339
+ GROUP BY DATE(pay_time), canteen_id, canteen_name -- ✅ 包含 canteen_name
340
+ ```
341
+
342
+ ### fix SQL 中的正确写法
343
+
344
+ ```xml
345
+ <insert id="initFix">
346
+ INSERT INTO report_sum_xxx (id, statistic_date, canteen_id, canteen_name,
347
+ order_count, consume_amount, net_amount)
348
+ SELECT
349
+ #{id},
350
+ DATE(pay_time), -- SELECT 用 DATE(pay_time)
351
+ canteen_id,
352
+ canteen_name,
353
+ COUNT(*),
354
+ SUM(CASE WHEN consume_type = 1 THEN real_amount ELSE 0 END),
355
+ SUM(real_amount)
356
+ FROM report_order_info
357
+ WHERE pay_time BETWEEN #{startTime} AND #{endTime}
358
+ GROUP BY DATE(pay_time), canteen_id, canteen_name -- ✅ 与 SELECT 完全一致
359
+ </insert>
360
+ ```
361
+
362
+ ### 开发检查项
363
+
364
+ - [ ] SELECT 每个非聚合字段,在 GROUP BY 中都有对应
365
+ - [ ] GROUP BY 的表达式与 SELECT 中的**完全一致**(`DATE_FORMAT(x, 'Y-m-d')` ≠ `DATE(x)`)
366
+ - [ ] ORDER BY 也使用相同表达式(保持一致)
367
+
368
+ ---
369
+
370
+ ## 十、开发检查清单
295
371
 
296
372
  ### 建表
297
373
  - [ ] 分组维度字段 + 金额汇总字段 + 审计字段(crby/crtime/upby/uptime/del_flag),无 tenant_id
@@ -308,9 +384,13 @@ GROUP BY d.wallet_id
308
384
  ### 查询接口
309
385
  - [ ] 分页 + 合计行(PageVO + TotalVO)+ 三并行 CompletableFuture
310
386
 
387
+ ### SQL 合规(only_full_group_by)
388
+ - [ ] SELECT 非聚合字段全部在 GROUP BY 中
389
+ - [ ] GROUP BY 表达式与 SELECT 完全一致
390
+
311
391
  ---
312
392
 
313
- ## 十、关键代码位置
393
+ ## 十一、关键代码位置
314
394
 
315
395
  | 类型 | 路径 |
316
396
  |------|------|
@@ -286,7 +286,69 @@ public ReportBaseTotalVO<XxxVO> pageSummary(XxxParam param) {
286
286
 
287
287
  ---
288
288
 
289
- ## 九、开发检查清单
289
+ ## 九、MySQL only_full_group_by 规范(必须遵守)
290
+
291
+ > MySQL 默认开启 `sql_mode=ONLY_FULL_GROUP_BY`,SELECT 中所有非聚合列必须出现在 GROUP BY 中,且 GROUP BY 表达式必须与 SELECT 表达式**完全一致**。
292
+
293
+ ### 核心规则
294
+
295
+ **SELECT 的表达式 == GROUP BY 的表达式**(字符级别完全一致)
296
+
297
+ ### ❌ 错误示例(GROUP BY 与 SELECT 不一致)
298
+
299
+ ```xml
300
+ <!-- 报错:Expression #1 of SELECT list is not in GROUP BY clause -->
301
+ SELECT
302
+ DATE_FORMAT(roi.consume_time, '%Y-%m-%d') AS statisticDate,
303
+ SUM(roi.real_amount) AS totalAmount
304
+ FROM report_order_info roi
305
+ GROUP BY DATE(roi.consume_time) <!-- ❌ DATE() ≠ DATE_FORMAT(..., '%Y-%m-%d') -->
306
+ ORDER BY DATE(roi.consume_time)
307
+ ```
308
+
309
+ ### ✅ 正确示例(GROUP BY 与 SELECT 完全一致)
310
+
311
+ ```xml
312
+ SELECT
313
+ DATE_FORMAT(roi.consume_time, '%Y-%m-%d') AS statisticDate,
314
+ SUM(roi.real_amount) AS totalAmount
315
+ FROM report_order_info roi
316
+ GROUP BY DATE_FORMAT(roi.consume_time, '%Y-%m-%d') <!-- ✅ 与 SELECT 完全一致 -->
317
+ ORDER BY DATE_FORMAT(roi.consume_time, '%Y-%m-%d') <!-- ✅ ORDER BY 也保持一致 -->
318
+ ```
319
+
320
+ ### ❌ 错误示例(SELECT 含非聚合列未加入 GROUP BY)
321
+
322
+ ```xml
323
+ SELECT
324
+ roi.canteen_id,
325
+ roi.canteen_name, <!-- ❌ 非聚合列未在 GROUP BY 中 -->
326
+ SUM(roi.real_amount) AS totalAmount
327
+ FROM report_order_info roi
328
+ GROUP BY roi.canteen_id
329
+ ```
330
+
331
+ ### ✅ 正确示例(所有非聚合列都在 GROUP BY 中)
332
+
333
+ ```xml
334
+ SELECT
335
+ roi.canteen_id,
336
+ roi.canteen_name,
337
+ SUM(roi.real_amount) AS totalAmount
338
+ FROM report_order_info roi
339
+ GROUP BY roi.canteen_id, roi.canteen_name <!-- ✅ 所有非聚合列都在 GROUP BY -->
340
+ ```
341
+
342
+ ### 检查清单
343
+
344
+ - [ ] SELECT 中按日期分组时使用 `DATE_FORMAT(col, '%Y-%m-%d')`,**不要用 `DATE()`**
345
+ - [ ] GROUP BY 表达式与 SELECT 中对应列**逐字相同**(复制粘贴而非重写)
346
+ - [ ] ORDER BY 中同样使用与 GROUP BY 一致的表达式
347
+ - [ ] SELECT 中所有非聚合列(无 SUM/COUNT/AVG/MAX/MIN 包裹)都出现在 GROUP BY 中
348
+
349
+ ---
350
+
351
+ ## 十、开发检查清单
290
352
 
291
353
  ### 建表
292
354
  - [ ] 分组维度 + 金额汇总 + 审计字段(crby/crtime/upby/uptime/del_flag),无 tenant_id
@@ -302,10 +364,11 @@ public ReportBaseTotalVO<XxxVO> pageSummary(XxxParam param) {
302
364
 
303
365
  ### 查询
304
366
  - [ ] ReportBaseTotalVO + CompletableFuture 并行 + MgrUserAuthPO 权限
367
+ - [ ] GROUP BY / ORDER BY 表达式与 SELECT 完全一致(only_full_group_by)
305
368
 
306
369
  ---
307
370
 
308
- ## 十、关键代码位置
371
+ ## 十一、关键代码位置
309
372
 
310
373
  > 路径前缀均为 `core-report/.../statistics/`
311
374