@yottameta/yotta-code-quality 0.3.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.
- package/LICENSE +22 -0
- package/README.md +247 -0
- package/SKILL.md +130 -0
- package/assets/banner.png +0 -0
- package/bin/install.js +163 -0
- package/install.sh +132 -0
- package/package.json +32 -0
- package/references/AGENTS-template.md +44 -0
- package/references/common.md +141 -0
- package/references/decay-risks.md +252 -0
- package/references/editorial-extensions.md +63 -0
- package/references/examples.md +59 -0
- package/references/hooks.json +10 -0
- package/references/pr-review-guide.md +93 -0
- package/references/source-coverage.md +89 -0
- package/references/test-decay-risks.md +201 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hyhmrright (original quality-review methodology)
|
|
4
|
+
Copyright (c) 2026 YottaMeta (this normalized, agent-agnostic packaging)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/banner.png" alt="yotta-code-quality banner" width="100%" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">yotta-code-quality(代码质量守卫)</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">面向 **Cursor / Codex / Claude Code / 通用 Agent** 的结对代码审查技能。把「代码质量审查」沉淀为可复用、可配置、有方法论支撑的技能,让智能体在交付前像资深工程师一样通读代码、定位劣化,并给出带依据的修复方案。</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
一句话定位:**先诊断、再修复,只出报告不动代码。**
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-blue" /></a>
|
|
15
|
+
<a href="https://agentskills.io/"><img alt="Standard: agentskills.io" src="https://img.shields.io/badge/standard-agentskills.io-orange" /></a>
|
|
16
|
+
<a href="https://www.npmjs.com/package/@yottameta/yotta-code-quality"><img alt="npm package" src="https://img.shields.io/npm/v/@yottameta/yotta-code-quality" /></a>
|
|
17
|
+
<a href="https://github.com/YottaMeta/yotta-code-quality"><img alt="GitHub stars" src="https://img.shields.io/github/stars/YottaMeta/yotta-code-quality" /></a>
|
|
18
|
+
<a href="https://github.com/YottaMeta/yotta-code-quality/commits/main"><img alt="last commit" src="https://img.shields.io/github/last-commit/YottaMeta/yotta-code-quality" /></a>
|
|
19
|
+
<a href="https://github.com/YottaMeta/yotta-code-quality"><img alt="PRs welcome" src="https://img.shields.io/badge/PRs-welcome-brightgreen" /></a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
## 核心价值
|
|
23
|
+
|
|
24
|
+
- **有依据,不拍脑袋。** 方法论蒸馏自 12 本经典软件工程著作(Fowler《重构》、McConnell《代码大全》、Ousterhout《软件设计哲学》、Evans《领域驱动设计》等),每条发现都锚定到具体书籍原则或坏味道。
|
|
25
|
+
- **铁律(Iron Law)防灌水。** 每条发现必须走 `症状 → 根源 → 后果 → 修复`(Symptom → Source → Consequence → Remedy),缺「后果」或「修复」的发现一律视为噪声,不会报出来。
|
|
26
|
+
- **默认只读、先诊断后修复。** 只出审查报告,不动代码;除非你明确要求 `--fix`(按 Remedy 修)。
|
|
27
|
+
- **健康分(Health Score)可追踪。** 每次审查给出 0–100 扣分指数(刻意定义成**单次扣分指数**,而非绝对评级),支持跨次趋势比较。
|
|
28
|
+
- **按需加载,不臃肿。** 按模式(Quick / PR / 架构 / 测试 / 发布)只读需要的参考文件,避免把整套方法论塞进上下文。
|
|
29
|
+
- **跨智能体 + 零依赖。** 纯文件技能,Cursor / Codex / Claude Code / 通用 Agent 均可用;不引入任何运行时依赖。
|
|
30
|
+
|
|
31
|
+
## 核心优势
|
|
32
|
+
|
|
33
|
+
| 维度 | yotta-code-quality | 说明 |
|
|
34
|
+
|------|--------------------|------|
|
|
35
|
+
| 方法论 | 12 本经典 SE 著作 + 坏味道 | 每条发现可溯源,非经验主义空谈 |
|
|
36
|
+
| 发现结构 | Iron Law 四段式 | 强制带「后果 + 修复」,避免无效吐槽 |
|
|
37
|
+
| 评分 | 单次扣分指数(0–100) | 明确"非绝对评级",防误读、支持趋势 |
|
|
38
|
+
| 覆盖面 | R1–R6 + T1–T6 + R7 + UX1 | 生产、测试、发布/供应链、首屏体验全覆盖 |
|
|
39
|
+
| 配置 | `.code-quality.yaml` | 按风险开关/降级/忽略/聚焦,自适应项目 |
|
|
40
|
+
| 触发 | 对话即触发 | 「结对评审」「发版前扫一眼」也能命中 |
|
|
41
|
+
| 附加件 | AGENTS-template / hooks.json | 可选,不装不影响审查核心 |
|
|
42
|
+
|
|
43
|
+
## 工作流程(协议详解)
|
|
44
|
+
|
|
45
|
+
### 铁律(不可协商)
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
NEVER suggest fixes before completing risk diagnosis.
|
|
49
|
+
EVERY finding must follow: Symptom → Source → Consequence → Remedy.
|
|
50
|
+
Default: report only — do NOT edit code unless the user asks to fix / passes --fix.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 会话契约
|
|
54
|
+
|
|
55
|
+
1. **默认只读**:只出报告,不做顺手重构。
|
|
56
|
+
2. **范围纪律**:用户点名文件 / diff /「刀子」,就留在该范围内。
|
|
57
|
+
3. **健康分不是评级**:它是**单次扣分指数**,不是对代码库的客观打分。
|
|
58
|
+
4. **语言**:报告用用户语言;Iron Law 字段名、书名、坏味道名、固定表头(`Findings` / `Summary` / `Critical` / `Warning` / `Suggestion`)保留英文。
|
|
59
|
+
|
|
60
|
+
### 按需加载(Mode 路由)
|
|
61
|
+
|
|
62
|
+
| 模式 | 何时使用 | 先读 | 需要时再读 |
|
|
63
|
+
|------|----------|------|-----------|
|
|
64
|
+
| **Quick** | 粘贴函数 / < 50 行 diff / 扫一眼 | `SKILL.md` + 速查 | `decay-risks.md` |
|
|
65
|
+
| **PR 审查** | PR / 分支 diff / ready to merge | `common.md` + `pr-review-guide.md` | `decay-risks.md` / `test-decay-risks.md` / `examples.md` |
|
|
66
|
+
| **架构 / 技术债** | 整模块 / 审计 / `--full` | `common.md` + `decay-risks.md` + `source-coverage.md` | `editorial-extensions.md` |
|
|
67
|
+
| **测试质量** | 测试 / 覆盖率 / flaky | `common.md` + `test-decay-risks.md` | `examples.md` |
|
|
68
|
+
| **发布 / 上架** | 发版前 / updater / CSP / 密钥 | `common.md` + `editorial-extensions.md` | R1–R6 表 |
|
|
69
|
+
|
|
70
|
+
### 评分(Health Score)
|
|
71
|
+
|
|
72
|
+
基础 100 分,按 `strictness` 扣分,下限 0。**仍会报告每一条发现**,评分只是趋势参考。
|
|
73
|
+
|
|
74
|
+
| 预设 | Critical | Warning | Suggestion |
|
|
75
|
+
|------|----------|---------|------------|
|
|
76
|
+
| `strict` | −20 | −8 | −2 |
|
|
77
|
+
| `balanced`(默认) | −15 | −5 | −1 |
|
|
78
|
+
| `legacy-friendly` | −8 | −3 | −1 |
|
|
79
|
+
|
|
80
|
+
### 配置(`.code-quality.yaml`)
|
|
81
|
+
|
|
82
|
+
审查前会在仓库根尝试读取该文件,缺失则用默认值(全部风险开启,`balanced`)。
|
|
83
|
+
|
|
84
|
+
| 字段 | 作用 |
|
|
85
|
+
|------|------|
|
|
86
|
+
| `disable` | 跳过指定风险(R1–R7 / T1–T6 / UX1) |
|
|
87
|
+
| `severity` | 强制某风险为 critical / warning / suggestion |
|
|
88
|
+
| `ignore` | 按 glob 排除(如 `**/*.generated.*`) |
|
|
89
|
+
| `focus` | 只审这些风险(不能与 `disable` 同时用) |
|
|
90
|
+
| `strictness` | strict / balanced(默认)/ legacy-friendly |
|
|
91
|
+
| `suppress` | 由 `--triage` 写入的忽略项 `{ id, reason, expires? }` |
|
|
92
|
+
| `history` | `true` 写入 `.code-quality-history.json` 趋势记录;默认关(见 History Tracking) |
|
|
93
|
+
|
|
94
|
+
```yaml
|
|
95
|
+
version: 1
|
|
96
|
+
strictness: balanced
|
|
97
|
+
disable: []
|
|
98
|
+
severity: {}
|
|
99
|
+
ignore:
|
|
100
|
+
- "**/*.generated.*"
|
|
101
|
+
- "**/node_modules/**"
|
|
102
|
+
suppress: []
|
|
103
|
+
history: false
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 可选参数
|
|
107
|
+
|
|
108
|
+
- `--fix` / 「按 Remedy 修」→ 进入修复模式(按 Remedy 最小改动,并重审这些发现)
|
|
109
|
+
- `--triage` / 「逐条处理」→ 交互式忽略 / 延期(写入 `suppress`)
|
|
110
|
+
- `.code-quality.yaml` 设 `history: true` → 生成 `.code-quality-history.json` 趋势记录
|
|
111
|
+
|
|
112
|
+
> 附加件 `AGENTS-template.md` 与 `hooks.json` 不装也不影响审查。
|
|
113
|
+
|
|
114
|
+
## 风险矩阵(canonical)
|
|
115
|
+
|
|
116
|
+
| 代码 | 名称 | 诊断要点 |
|
|
117
|
+
|------|------|----------|
|
|
118
|
+
| R1 | 认知过载 Cognitive Overload | 读这段代码需要多少脑力 |
|
|
119
|
+
| R2 | 变更传播 Change Propagation | 改一处会连带坏多少无关处 |
|
|
120
|
+
| R3 | 知识重复 Knowledge Duplication | 同一决策是否散落多处 |
|
|
121
|
+
| R4 | 意外复杂度 Accidental Complexity | 是否比问题本身更复杂 |
|
|
122
|
+
| R5 | 依赖失序 Dependency Disorder | 依赖方向是否一致 |
|
|
123
|
+
| R6 | 领域模型失真 Domain Model Distortion | 是否忠实于领域语言 |
|
|
124
|
+
| T1 | 测试晦涩 Test Obscurity | 是否清楚在验证什么 |
|
|
125
|
+
| T2 | 测试脆弱 Test Brittleness | 是否被行为等价的重构打破 |
|
|
126
|
+
| T3 | 测试重复 Test Duplication | 同一场景是否无层价值地重复 |
|
|
127
|
+
| T4 | Mock 滥用 Mock Abuse | 测试是否比行为更复杂 |
|
|
128
|
+
| T5 | 覆盖幻觉 Coverage Illusion | 套件是否真保护了会出错的点 |
|
|
129
|
+
| T6 | 架构失配 Architecture Mismatch | 套件形状是否匹配风险画像 |
|
|
130
|
+
| R7 | 发布 / 供应链安全 | 明文密钥、跳过校验的 updater、产物开 DevTools |
|
|
131
|
+
| UX1 | 首屏 / 状态清晰度 | 空窗、splash 不居中、状态文案与门禁不符 |
|
|
132
|
+
|
|
133
|
+
> 详细症状、书源、严重度与「不误报清单」见 `references/decay-risks.md`、`references/test-decay-risks.md`、`references/editorial-extensions.md`。`anti-over-flag` 在报 R1 等前先抑制噪声告警,避免「狼来了」式疲劳。
|
|
134
|
+
|
|
135
|
+
## 目录结构
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
yotta-code-quality/
|
|
139
|
+
├── SKILL.md # 入口 + 按模式按需加载的路由
|
|
140
|
+
├── references/
|
|
141
|
+
│ ├── common.md # 配置 / 模板 / 评分(单一信息源)
|
|
142
|
+
│ ├── decay-risks.md # R1–R6 生产风险
|
|
143
|
+
│ ├── test-decay-risks.md # T1–T6 测试风险
|
|
144
|
+
│ ├── editorial-extensions.md # R7 / UX1 / 防过度告警
|
|
145
|
+
│ ├── source-coverage.md # 书籍矩阵(深度模式)
|
|
146
|
+
│ ├── pr-review-guide.md # 7 步 PR 审查
|
|
147
|
+
│ ├── examples.md # 语气 / 评分校准
|
|
148
|
+
│ ├── AGENTS-template.md # 可选:丢进仓库当 AGENTS.md 强制规范
|
|
149
|
+
│ └── hooks.json # 可选:PreToolUse 拦截 rm -rf / git push --force
|
|
150
|
+
├── bin/install.js # npx 跨平台安装器
|
|
151
|
+
├── install.sh # 一键安装到 17 类智能体(含国内 Trae/Qwen/Comate/CodeBuddy/Kimi)
|
|
152
|
+
├── assets/banner.png # 品牌头图
|
|
153
|
+
└── LICENSE # MIT
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## 安装
|
|
157
|
+
|
|
158
|
+
三种方式任选其一,技能文件统一从 **npm** 获取(GitHub 无代理时较慢,npm 可配国内镜像加速)。
|
|
159
|
+
|
|
160
|
+
### 方式一:npm(推荐,一行安装)
|
|
161
|
+
```bash
|
|
162
|
+
# 国内加速(可选):npm config set registry https://registry.npmmirror.com
|
|
163
|
+
npx -y @yottameta/yotta-code-quality -g
|
|
164
|
+
npx -y @yottameta/yotta-code-quality --dir <你的技能目录> # 任意智能体:指定目录安装
|
|
165
|
+
```
|
|
166
|
+
> 智能体不在预置列表?用 `--dir` 指定它的 skills 目录,或手动复制(方式三)。`--list` 可查看各智能体对应的默认目录。想手动拿文件也可 `npm pack @yottameta/yotta-code-quality` 解包后按方式二/三安装。
|
|
167
|
+
|
|
168
|
+
### 方式二:install.sh 一键安装
|
|
169
|
+
获取技能文件夹后(`npm pack` 解包或 `git clone`),进入技能文件夹:
|
|
170
|
+
```bash
|
|
171
|
+
bash install.sh -g # 用户级;bash install.sh --list 查看全部目录
|
|
172
|
+
bash install.sh --agent codex # 指定智能体(--list 可查看可用项)
|
|
173
|
+
bash install.sh # 项目级:自动检测已存在的 .claude/.cursor/.codex 等 skills 目录
|
|
174
|
+
bash install.sh --dir /path/to/skills
|
|
175
|
+
```
|
|
176
|
+
> Windows 用户:装有 Git Bash 即可用;否则用方式三手动复制。
|
|
177
|
+
|
|
178
|
+
### 方式三:手动复制
|
|
179
|
+
把整个 `yotta-code-quality` 文件夹复制到目标智能体的 skills 目录。常见位置(用户级;Windows 用 `%USERPROFILE%`,Linux/macOS 用 `~`):
|
|
180
|
+
|
|
181
|
+
| 智能体 | 用户级目录 | 项目级目录 |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| Codex | `%USERPROFILE%\.codex\skills\yotta-code-quality\` | `.codex\skills\` |
|
|
184
|
+
| Claude Code | `%USERPROFILE%\.claude\skills\yotta-code-quality\` | `.claude\skills\` |
|
|
185
|
+
| Cursor | `%USERPROFILE%\.cursor\skills\yotta-code-quality\` | `.cursor\skills\` |
|
|
186
|
+
| Windsurf | `%USERPROFILE%\.codeium\windsurf\skills\yotta-code-quality\` | `.windsurf\skills\` |
|
|
187
|
+
| opencode | `%USERPROFILE%\.config\opencode\skills\yotta-code-quality\` | `.opencode\skills\` |
|
|
188
|
+
| Gemini | `%USERPROFILE%\.gemini\skills\yotta-code-quality\` | `.gemini\skills\` |
|
|
189
|
+
| Goose | `%USERPROFILE%\.config\goose\skills\yotta-code-quality\` | `.goose\skills\` |
|
|
190
|
+
| Amp | `%USERPROFILE%\.config\agents\skills\yotta-code-quality\` | `.agents\skills\` |
|
|
191
|
+
| Kiro | `%USERPROFILE%\.kiro\skills\yotta-code-quality\` | `.kiro\skills\` |
|
|
192
|
+
| WorkBuddy | `%USERPROFILE%\.workbuddy\skills\yotta-code-quality\` | `.workbuddy\skills\` |
|
|
193
|
+
| Trae Code CLI | `%USERPROFILE%\.traecli\skills\yotta-code-quality\` | `.traecli\skills\` |
|
|
194
|
+
| Trae IDE(国内) | `%USERPROFILE%\.trae-cn\skills\yotta-code-quality\` | `.trae\skills\` |
|
|
195
|
+
| Qwen Code | `%USERPROFILE%\.qwen\skills\yotta-code-quality\` | `.qwen\skills\` |
|
|
196
|
+
| Comate | `%USERPROFILE%\.comate\skills\yotta-code-quality\` | `.comate\skills\` |
|
|
197
|
+
| CodeBuddy | `%USERPROFILE%\.codebuddy\skills\yotta-code-quality\` | `.codebuddy\skills\` |
|
|
198
|
+
| Kimi | `%USERPROFILE%\.kimi\skills\yotta-code-quality\` | `.kimi\skills\` |
|
|
199
|
+
| 通用 AGENTS.md | `%USERPROFILE%\.agents\skills\yotta-code-quality\` | `.agents\skills\` |
|
|
200
|
+
|
|
201
|
+
> Codex 默认目录若设置了环境变量 `CODEX_HOME`,以该变量为准;opencode 若设置 `XDG_CONFIG_HOME` 同理。`.agents\skills` 并非通用目录,仅 OpenCode / Cursor / Cline / Amp / Kimi / Gemini CLI / GitHub Copilot 等会读取,**Claude Code 与 Codex 默认不读**。不确定时用 `--dir` 指定,或让该智能体自行安装。
|
|
202
|
+
|
|
203
|
+
## 使用
|
|
204
|
+
|
|
205
|
+
对话中说「review this PR」「结对评审」「发版前扫一眼」,或直接调用 `/yotta-code-quality`。可选参数见上文「可选参数」。
|
|
206
|
+
|
|
207
|
+
### 示例:Quick 审查(粘贴一段函数)
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
用户:帮我看看这段函数有没有问题 / 结对评审
|
|
211
|
+
智能体:按 Quick 模式 → 读 SKILL + 速查 → 输出 Findings + Health Score
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### 示例:PR 审查(带 7 步流程)
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
用户:review this PR / ready to merge?
|
|
218
|
+
智能体:按 PR 模式 → .code-quality.yaml 配置 → 自动 scope → 走 pr-review-guide.md 7 步
|
|
219
|
+
→ 输出 Findings(Critical/Warning/Suggestion 排序)+ 修复顺序建议
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 示例:接入项目并配置
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
# 1. 在仓库根放一个 .code-quality.yaml(可选)
|
|
226
|
+
# 2. 对话触发审查,或用 --dir 把技能装到目标智能体
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## 升级与卸载
|
|
230
|
+
|
|
231
|
+
- **升级**:重新执行一次安装命令即可覆盖为最新版(npm 方式:`npx -y @yottameta/yotta-code-quality -g`;install.sh 方式:重新在技能文件夹运行)。版本号见 npm。
|
|
232
|
+
- **卸载**:删除目标智能体 skills 目录下的 `yotta-code-quality/` 文件夹即可。
|
|
233
|
+
- **无副作用**:技能不写项目外文件;可选的历史/趋势文件(`.code-quality-history.json`)只在你开启 `history: true` 时生成,位于仓库根。
|
|
234
|
+
|
|
235
|
+
## 常见问题(FAQ)
|
|
236
|
+
|
|
237
|
+
- **它和通用 code review 或 linter 有何区别?** 通用工具多基于规则/风格;本技能提供「方法论依据 + 铁律四段式 + 单次扣分指数」,聚焦系统性劣化(复杂度、传播、重复、依赖、领域建模、测试与发布安全),而非风格挑刺。
|
|
238
|
+
- **健康分会算出一个"分数"来判断代码好坏吗?** 不会。它是**单次扣分指数**,且明确非绝对评级,用于横向比较趋势。
|
|
239
|
+
- **会直接改我的代码吗?** 默认只出报告;只有你要求 `--fix` 或「按 Remedy 修」才会改,且按最小行为等价方式修改。
|
|
240
|
+
- **想只审某几类风险怎么办?** 用 `.code-quality.yaml` 的 `disable` / `focus` / `severity` 即可。
|
|
241
|
+
- **`.agents/skills` 是通用目录吗?** 不是。Claude Code 与 Codex 默认不读它;不确定时用 `--dir` 指定目标目录。
|
|
242
|
+
- **需要联网或装依赖吗?** 不需要。技能是零依赖的纯文件,运行只依赖宿主智能体的读文件能力。
|
|
243
|
+
|
|
244
|
+
## 来源与许可
|
|
245
|
+
|
|
246
|
+
- **方法论**蒸馏自 12 本经典软件工程著作及开源社区质量审查实践(MIT);原始方法论版权归 hyhmrright,本技能在其基础上重写为单一自包含、跨智能体通用的版本,并增补 R7 / UX1 / 按需加载会话契约。
|
|
247
|
+
- **许可:** MIT —— 详见 `LICENSE`(版权人:hyhmrright(原始方法论)+ YottaMeta(本打包))。
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yotta-code-quality
|
|
3
|
+
description: >-
|
|
4
|
+
Pair-style code quality reviewer: twelve book-grounded decay risks (R1–R6, T1–T6) plus
|
|
5
|
+
release-safety and first-paint UX checks. Findings always use Iron Law
|
|
6
|
+
(Symptom → Source → Consequence → Remedy) and a 0–100 review-index Health Score.
|
|
7
|
+
Triggers when: user asks to review code/PR/diff, "any issues", "ready to merge", smells,
|
|
8
|
+
refactoring, tech debt, test quality, coverage, or architecture health; or says
|
|
9
|
+
「结对评审」/「发版前扫一眼」/ yotta-code-quality.
|
|
10
|
+
Do NOT trigger for: greenfield "how do I write X" with no code, pure syntax questions,
|
|
11
|
+
or tool/framework questions with no shared code.
|
|
12
|
+
version: 0.3.0
|
|
13
|
+
license: MIT
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Code Quality Reviewer
|
|
17
|
+
|
|
18
|
+
Portable reviewer for Cursor and other Agent-Skills hosts.
|
|
19
|
+
|
|
20
|
+
**Origin:** methodology distilled from twelve classic SE books and prior open-source quality-review work (MIT).
|
|
21
|
+
**Editorial process & workflow defaults:** this skill’s maintainers (pair-review oriented).
|
|
22
|
+
Canonical tables live under `references/` — do not treat this file as a second copy of templates or score math.
|
|
23
|
+
|
|
24
|
+
## The Iron Law (non-negotiable)
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
NEVER suggest fixes before completing risk diagnosis.
|
|
28
|
+
EVERY finding must follow: Symptom → Source → Consequence → Remedy.
|
|
29
|
+
Default: report only — do NOT edit code unless the user asks to fix / passes --fix.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
A finding without Consequence and Remedy is noise.
|
|
33
|
+
|
|
34
|
+
## Session contract
|
|
35
|
+
|
|
36
|
+
1. **Review-only by default** — output the report; no drive-by refactors.
|
|
37
|
+
2. **Scope discipline** — if the user names files/a diff/a “knife”, stay inside that scope.
|
|
38
|
+
3. **Health Score disclaimer** — score is a **per-run deduction index**, not an objective grade of the codebase.
|
|
39
|
+
4. **Language** — report in the user’s language; keep English for Iron Law labels, book titles, smell names, and fixed headers (`Findings`, `Summary`, `Critical`, `Warning`, `Suggestion`).
|
|
40
|
+
|
|
41
|
+
## Load by Mode (do not read every reference every time)
|
|
42
|
+
|
|
43
|
+
| Mode | Detect when | Read first | Read if needed |
|
|
44
|
+
|------|-------------|------------|----------------|
|
|
45
|
+
| **Quick** | pasted function / < ~50-line diff / “扫一眼” | This `SKILL.md` + cheat-sheet below | `decay-risks.md` only for a borderline Critical |
|
|
46
|
+
| **PR Review** | PR / branch diff / “ready to merge” | `common.md` (config + template + score) + `pr-review-guide.md` | `decay-risks.md` / `test-decay-risks.md` for raised findings; `examples.md` if calibrating tone |
|
|
47
|
+
| **Architecture / Tech Debt** | whole module / “审计” / `--full` | `common.md` + `decay-risks.md` + `source-coverage.md` | `editorial-extensions.md` |
|
|
48
|
+
| **Test Quality** | tests / coverage / flaky | `common.md` + `test-decay-risks.md` | `examples.md` |
|
|
49
|
+
| **Release / ship gate** | “发版前” / updater / CSP / secrets | `common.md` + `editorial-extensions.md` | R1–R6 tables as needed |
|
|
50
|
+
|
|
51
|
+
Always try `.code-quality.yaml` at repo root (see `common.md`).
|
|
52
|
+
Optional extras (`AGENTS-template.md`, `hooks.json`) are **not** part of the review core — install only if the user wants them.
|
|
53
|
+
|
|
54
|
+
## Risk index
|
|
55
|
+
|
|
56
|
+
### Production (canonical: `decay-risks.md`)
|
|
57
|
+
|
|
58
|
+
| Code | Risk | Diagnostic |
|
|
59
|
+
|------|------|------------|
|
|
60
|
+
| R1 | Cognitive Overload | How much mental effort to understand this? |
|
|
61
|
+
| R2 | Change Propagation | How many unrelated things break on one change? |
|
|
62
|
+
| R3 | Knowledge Duplication | Same decision in multiple places? |
|
|
63
|
+
| R4 | Accidental Complexity | More complex than the problem? |
|
|
64
|
+
| R5 | Dependency Disorder | Consistent dependency direction? |
|
|
65
|
+
| R6 | Domain Model Distortion | Faithful to the domain language? |
|
|
66
|
+
|
|
67
|
+
### Tests (canonical: `test-decay-risks.md`)
|
|
68
|
+
|
|
69
|
+
| Code | Risk | Diagnostic |
|
|
70
|
+
|------|------|------------|
|
|
71
|
+
| T1 | Test Obscurity | Clear what is verified? |
|
|
72
|
+
| T2 | Test Brittleness | Breaks on behavior-preserving refactors? |
|
|
73
|
+
| T3 | Test Duplication | Same scenario repeated without layer value? |
|
|
74
|
+
| T4 | Mock Abuse | Test more complex than behavior? |
|
|
75
|
+
| T5 | Coverage Illusion | Suite protect failures that matter? |
|
|
76
|
+
| T6 | Architecture Mismatch | Suite shape match risk profile? |
|
|
77
|
+
|
|
78
|
+
### Editorial extensions (canonical: `editorial-extensions.md`)
|
|
79
|
+
|
|
80
|
+
| Code | Risk | Diagnostic |
|
|
81
|
+
|------|------|------------|
|
|
82
|
+
| R7 | Release / Supply-chain Safety | Secrets, insecure update/CSP/devtools, unsigned artifacts — ship risk *today*? |
|
|
83
|
+
| UX1 | First-paint / Status Clarity | First seconds: empty chrome, mis-centered splash, status copy vs gate mismatch? |
|
|
84
|
+
|
|
85
|
+
## Symptom cheat-sheet (hints — check blast radius)
|
|
86
|
+
|
|
87
|
+
Thresholds are **hints**, not automatic Criticals. Dense business branching matters more than raw line count. Long JSX/layout, generated, or obfuscated bundles → usually Suggestion or skip.
|
|
88
|
+
|
|
89
|
+
**Production:** R1 long/nested/flag-args/primitive-obsession; R2 shotgun edits / Hyrum; R3 copy-paste / synonym soup; R4 speculative abstraction; R5 cycles / domain→infra; R6 anemic model / language drift.
|
|
90
|
+
**Tests:** T1 vague names / assertion roulette; T2 private asserts / flaky; T3 lazy dupes; T4 mock theater; T5 happy-path-only; T6 inverted pyramid.
|
|
91
|
+
**Editorial:** R7 plaintext keys, skip-verify updaters, prod DevTools; UX1 splash not centered, solid empty window, “校验中” never appears, etc.
|
|
92
|
+
|
|
93
|
+
## Severity
|
|
94
|
+
|
|
95
|
+
- Critical — velocity or production risk *today*
|
|
96
|
+
- Warning — will hurt within the next few features if ignored
|
|
97
|
+
- Suggestion — fix when nearby
|
|
98
|
+
|
|
99
|
+
Scoring math and report template: **`references/common.md` only** (do not duplicate here).
|
|
100
|
+
|
|
101
|
+
## Default PR process (summary)
|
|
102
|
+
|
|
103
|
+
1. Scope (+ skip generated).
|
|
104
|
+
2. R2 first.
|
|
105
|
+
3. R1 / R3 / R4.
|
|
106
|
+
4. R5 if imports/structure changed; R6 if names/types introduced.
|
|
107
|
+
5. Quick test signals (see `pr-review-guide.md` Step 7).
|
|
108
|
+
6. If release-ish: skim R7 / UX1.
|
|
109
|
+
7. Iron Law → template in `common.md`.
|
|
110
|
+
|
|
111
|
+
## Guardrails
|
|
112
|
+
|
|
113
|
+
- Cite a book only when the match is real.
|
|
114
|
+
- Prefer concrete consequences over style nits.
|
|
115
|
+
- State tradeoffs when sources disagree.
|
|
116
|
+
- **Triage / history are opt-in** — see `common.md` (never block the report on them).
|
|
117
|
+
|
|
118
|
+
## Companion files
|
|
119
|
+
|
|
120
|
+
| File | Role |
|
|
121
|
+
|------|------|
|
|
122
|
+
| `references/common.md` | Config, scope, **template**, **score**, opt-in history/triage |
|
|
123
|
+
| `references/decay-risks.md` | R1–R6 |
|
|
124
|
+
| `references/test-decay-risks.md` | T1–T6 |
|
|
125
|
+
| `references/editorial-extensions.md` | R7 + UX1 + anti-over-flag |
|
|
126
|
+
| `references/source-coverage.md` | Book matrix (Architecture / disputes) |
|
|
127
|
+
| `references/pr-review-guide.md` | 7-step PR |
|
|
128
|
+
| `references/examples.md` | Tone calibration |
|
|
129
|
+
| `references/AGENTS-template.md` | Optional repo drop-in |
|
|
130
|
+
| `references/hooks.json` | Optional dangerous-command hook |
|
|
Binary file
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* yotta-code-quality 跨平台安装器(YottaSkills)
|
|
4
|
+
* 用法:
|
|
5
|
+
* npx -y @yottameta/yotta-code-quality --agent <name> # 按智能体默认用户级目录安装(推荐)
|
|
6
|
+
* npx -y @yottameta/yotta-code-quality --dir PATH # 装到指定目录(用户改了目录的智能体)
|
|
7
|
+
* npx -y @yottameta/yotta-code-quality -g # 安装到全部已知智能体用户级目录
|
|
8
|
+
* npx -y @yottameta/yotta-code-quality # 安装到检测到的项目级目录
|
|
9
|
+
* npx -y @yottameta/yotta-code-quality --list # 列出智能体 -> 默认目录
|
|
10
|
+
*/
|
|
11
|
+
'use strict';
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const os = require('os');
|
|
15
|
+
|
|
16
|
+
const SKILL_NAME = 'yotta-code-quality';
|
|
17
|
+
const PKG_ROOT = path.join(__dirname, '..');
|
|
18
|
+
|
|
19
|
+
// 智能体 -> 用户级默认技能目录(dirs 按优先级排列;--agent 装到第一个)
|
|
20
|
+
// 依据官方文档:.agents/skills 并非通用目录,被 OpenCode / Cursor / Cline / Amp /
|
|
21
|
+
// Kimi / Gemini CLI / GitHub Copilot 等读取;Claude Code 与 Codex 默认不读 .agents。
|
|
22
|
+
const AGENT_DIRS = {
|
|
23
|
+
claude: { label: 'Claude Code', dirs: ['.claude/skills'] },
|
|
24
|
+
cursor: { label: 'Cursor', dirs: ['.cursor/skills', '.agents/skills'] },
|
|
25
|
+
codex: { label: 'Codex', dirs: ['.codex/skills'] }, // 特判:$CODEX_HOME/skills
|
|
26
|
+
gemini: { label: 'Gemini CLI', dirs: ['.gemini/skills', '.agents/skills'] },
|
|
27
|
+
goose: { label: 'Goose', dirs: ['.config/goose/skills', '.agents/skills'] },
|
|
28
|
+
amp: { label: 'Amp', dirs: ['.config/agents/skills', '.agents/skills'] },
|
|
29
|
+
opencode: { label: 'OpenCode', dirs: ['.config/opencode/skills'] }, // 特判:$XDG_CONFIG_HOME
|
|
30
|
+
windsurf: { label: 'Windsurf', dirs: ['.codeium/windsurf/skills'] },
|
|
31
|
+
workbuddy: { label: 'WorkBuddy', dirs: ['.workbuddy/skills'] },
|
|
32
|
+
kiro: { label: 'Kiro', dirs: ['.kiro/skills'] },
|
|
33
|
+
trae: { label: 'Trae Code CLI', dirs: ['.traecli/skills'] },
|
|
34
|
+
'trae-cn': { label: 'Trae IDE(国内)', dirs: ['.trae-cn/skills'] },
|
|
35
|
+
qwen: { label: 'Qwen Code', dirs: ['.qwen/skills'] },
|
|
36
|
+
comate: { label: 'Comate 文心快码', dirs: ['.comate/skills'] },
|
|
37
|
+
codebuddy: { label: 'CodeBuddy Code', dirs: ['.codebuddy/skills'] },
|
|
38
|
+
kimi: { label: 'Kimi Code CLI', dirs: ['.kimi/skills'] },
|
|
39
|
+
agents: { label: '通用 AGENTS.md', dirs: ['.agents/skills'] },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Codex 用户级目录特判:优先 $CODEX_HOME/skills,否则 ~/.codex/skills
|
|
43
|
+
function codexUserDir() {
|
|
44
|
+
const base = process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
|
|
45
|
+
return path.join(base, 'skills');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// OpenCode 用户级目录特判:优先 $XDG_CONFIG_HOME/opencode/skills,否则 ~/.config/opencode/skills
|
|
49
|
+
function opencodeUserDir() {
|
|
50
|
+
const base = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
|
|
51
|
+
return path.join(base, 'opencode', 'skills');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function resolveUserDir(rel) {
|
|
55
|
+
if (rel === '.codex/skills') return codexUserDir();
|
|
56
|
+
if (rel === '.config/opencode/skills') return opencodeUserDir();
|
|
57
|
+
return path.join(os.homedir(), rel);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function installTo(dest) {
|
|
61
|
+
const target = path.join(dest, SKILL_NAME);
|
|
62
|
+
fs.mkdirSync(target, { recursive: true });
|
|
63
|
+
copyDir(PKG_ROOT, target, new Set(['package.json', 'bin', 'node_modules', '.git']));
|
|
64
|
+
console.log('installed -> ' + target);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function copyDir(src, dst, skip) {
|
|
68
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
69
|
+
if (skip.has(entry.name)) continue;
|
|
70
|
+
const s = path.join(src, entry.name);
|
|
71
|
+
const d = path.join(dst, entry.name);
|
|
72
|
+
if (entry.isDirectory()) {
|
|
73
|
+
fs.mkdirSync(d, { recursive: true });
|
|
74
|
+
copyDir(s, d, skip);
|
|
75
|
+
} else if (entry.isFile()) {
|
|
76
|
+
fs.copyFileSync(s, d);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function displayDir(rel) {
|
|
82
|
+
if (process.platform === 'win32') return '%USERPROFILE%\\' + rel.replace(/\//g, '\\');
|
|
83
|
+
return '~/' + rel;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function main() {
|
|
87
|
+
const args = process.argv.slice(2);
|
|
88
|
+
const isGlobal = args.includes('-g') || args.includes('--global');
|
|
89
|
+
const list = args.includes('--list') || args.includes('-l');
|
|
90
|
+
let explicitDir = null;
|
|
91
|
+
const di = args.indexOf('--dir');
|
|
92
|
+
if (di !== -1 && args[di + 1]) explicitDir = args[di + 1];
|
|
93
|
+
let agent = null;
|
|
94
|
+
const ai = args.indexOf('--agent');
|
|
95
|
+
if (ai !== -1 && args[ai + 1]) agent = String(args[ai + 1]).toLowerCase();
|
|
96
|
+
|
|
97
|
+
if (list) {
|
|
98
|
+
console.log('智能体 -> 默认技能目录(--agent <name> 装到第一个,用户级):');
|
|
99
|
+
for (const [key, v] of Object.entries(AGENT_DIRS)) {
|
|
100
|
+
const resolved = v.dirs.map(displayDir);
|
|
101
|
+
console.log(' ' + key.padEnd(10) + v.label.padEnd(18) + resolved.join('、'));
|
|
102
|
+
}
|
|
103
|
+
console.log('\n说明:Windows 用 %USERPROFILE%,Linux/macOS 用 ~;仅收录有官方默认目录的智能体。');
|
|
104
|
+
console.log('改了目录的请用 --dir <路径>,不要依赖默认位置;若设置了 CODEX_HOME / XDG_CONFIG_HOME,安装自动以该变量为准。');
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (explicitDir) { installTo(explicitDir); return; }
|
|
109
|
+
|
|
110
|
+
if (agent) {
|
|
111
|
+
const info = AGENT_DIRS[agent];
|
|
112
|
+
if (!info) {
|
|
113
|
+
console.log('未收录智能体: ' + agent + '。请用 --dir <路径> 指定技能目录。');
|
|
114
|
+
console.log('可用: ' + Object.keys(AGENT_DIRS).join(', '));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
installTo(resolveUserDir(info.dirs[0]));
|
|
118
|
+
console.log('完成。');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (isGlobal) {
|
|
123
|
+
const seen = new Set();
|
|
124
|
+
for (const v of Object.values(AGENT_DIRS)) {
|
|
125
|
+
for (const d of v.dirs) {
|
|
126
|
+
if (seen.has(d)) continue;
|
|
127
|
+
seen.add(d);
|
|
128
|
+
installTo(resolveUserDir(d));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
console.log('完成。');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const PROJECT_DIRS = [
|
|
136
|
+
'.claude/skills',
|
|
137
|
+
'.cursor/skills',
|
|
138
|
+
'.codex/skills',
|
|
139
|
+
'.config/goose/skills',
|
|
140
|
+
'.config/agents/skills',
|
|
141
|
+
'.opencode/skills',
|
|
142
|
+
'.codeium/windsurf/skills',
|
|
143
|
+
'.workbuddy/skills',
|
|
144
|
+
'.kiro/skills',
|
|
145
|
+
'.traecli/skills',
|
|
146
|
+
'.gemini/skills',
|
|
147
|
+
'.trae-cn/skills',
|
|
148
|
+
'.qwen/skills',
|
|
149
|
+
'.comate/skills',
|
|
150
|
+
'.codebuddy/skills',
|
|
151
|
+
'.kimi/skills',
|
|
152
|
+
'.agents/skills',
|
|
153
|
+
];
|
|
154
|
+
let installedAny = false;
|
|
155
|
+
for (const d of PROJECT_DIRS) {
|
|
156
|
+
if (fs.existsSync(d)) { installTo(d); installedAny = true; }
|
|
157
|
+
}
|
|
158
|
+
if (!installedAny) {
|
|
159
|
+
console.log('未检测到项目级智能体目录。可手动复制,或用 --agent <name> / -g 装到用户级。');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
main();
|