@yottameta/yotta-code-quality 0.3.3 → 0.4.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/CHANGELOG.md +15 -1
- package/README.md +32 -38
- package/README.zh-CN.md +35 -42
- package/SKILL.md +3 -1
- package/bin/install.js +168 -86
- package/package.json +4 -1
- package/references/faq.md +50 -0
- package/references/walkthroughs.md +30 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
|
+
## v0.4.0 (2026-09-08)
|
|
2
|
+
|
|
3
|
+
**评测驱动完善**:新增 FAQ 与复杂场景走查,安装器错误处理与测试补齐。
|
|
4
|
+
|
|
5
|
+
- 新增 references/faq.md 与 references/walkthroughs.md。
|
|
6
|
+
- 安装器支持 --help、参数校验、统一退出码与人话错误提示。
|
|
7
|
+
- 新增安装器测试,覆盖未知智能体、缺参、成功安装与产物形态。
|
|
8
|
+
|
|
1
9
|
# 更新日志
|
|
2
10
|
|
|
11
|
+
## v0.3.4 (2026-08-29)
|
|
12
|
+
|
|
13
|
+
- 安装方式统一为四方式(对齐发布规范 §3.3.1):方式一 `npx -y @yottameta/yotta-code-quality --agent <name>` / `--dir <dir>`(推荐,走 npm 源);方式二 `git clone https://github.com/YottaMeta/yotta-code-quality.git`;方式三 GitHub Download ZIP;方式四 `bash install.sh --agent/--dir/--list`。移除 `npx skills` 与 `-g` 推荐;中英双 README 安装节同步。
|
|
14
|
+
- 版本对齐:package.json / SKILL.md / CHANGELOG / 引擎 VERSION / 测试断言 / README 锚点 = 0.3.4。
|
|
15
|
+
- 无功能变更(仅文档与版本同步)。
|
|
16
|
+
|
|
3
17
|
## v0.3.3 (2026-08-28)
|
|
4
18
|
|
|
5
|
-
中英双语 README
|
|
19
|
+
中英双语 README 对齐:
|
|
6
20
|
|
|
7
21
|
- **README.md 改为英文**:作为 GitHub / npm / ClawHub 首页的英文门面(翻译 + 精简,覆盖定位 / 核心价值 / 工作流程 / 风险矩阵 / 目录结构 / 安装 / 使用 / 升级卸载 / FAQ / 来源与许可全流程)。
|
|
8
22
|
- **新增 README.zh-CN.md**:原中文完整主文档整体平移,顶部加语言切换链接。
|
package/README.md
CHANGED
|
@@ -144,50 +144,39 @@ yotta-code-quality/
|
|
|
144
144
|
|
|
145
145
|
## Install
|
|
146
146
|
|
|
147
|
-
Pick any
|
|
147
|
+
Pick any of the four methods below; the order is the recommended priority. Skill files always come from **npm** (GitHub can be slow without a proxy; npm supports mirrors).
|
|
148
148
|
|
|
149
|
-
### Method 1: npm
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
npx -y @yottameta/yotta-code-quality --
|
|
149
|
+
### Method 1: npm one-liner (recommended)
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
# Optional China mirror: npm config set registry https://registry.npmmirror.com
|
|
153
|
+
npx -y @yottameta/yotta-code-quality --agent <agent-name> # install to the agent's default user-level skills dir
|
|
154
|
+
npx -y @yottameta/yotta-code-quality --dir <your-skills-dir> # point to the skills dir itself (e.g. ~/.codex/skills)
|
|
154
155
|
```
|
|
155
|
-
> Not in the preset list? Use --dir to point at the agent's skills directory, or manual copy (method 3). --list shows each agent's default directory. You can also npm pack @yottameta/yotta-code-quality and unpack it to install via method 2 / 3.
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
157
|
+
- `--agent <name>` installs to that agent's default user-level directory; `--list` shows each agent's default directory.
|
|
158
|
+
- `--dir <path>` installs to the given directory; for agents not in the preset list, point `--dir` at their skills directory.
|
|
159
|
+
- If the mirror has not synced the new package (404): add `--registry=https://registry.npmjs.org/` (a proxy may be needed in China), or wait for the mirror cache.
|
|
160
|
+
|
|
161
|
+
### Method 2: git clone (developers / git available)
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
git clone https://github.com/YottaMeta/yotta-code-quality.git <your-skills-dir>/yotta-code-quality
|
|
163
165
|
```
|
|
164
|
-
> Covers 17 agent families including Trae / Qwen / Comate / CodeBuddy / Kimi. Windows users: works with Git Bash; otherwise use method 3.
|
|
165
166
|
|
|
166
|
-
### Method 3: manual
|
|
167
|
-
Copy the whole `yotta-code-quality` folder into the target agent's skills directory. Common locations (user level; Windows uses %USERPROFILE%, Linux/macOS uses ~):
|
|
167
|
+
### Method 3: GitHub Download ZIP (manual / no git)
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|---|---|---|
|
|
171
|
-
| Codex | %USERPROFILE%\.codex\skills\yotta-code-quality\ | .codex\skills\ |
|
|
172
|
-
| Claude Code | %USERPROFILE%\.claude\skills\yotta-code-quality\ | .claude\skills\ |
|
|
173
|
-
| Cursor | %USERPROFILE%\.cursor\skills\yotta-code-quality\ | .cursor\skills\ |
|
|
174
|
-
| Windsurf | %USERPROFILE%\.codeium\windsurf\skills\yotta-code-quality\ | .windsurf\skills\ |
|
|
175
|
-
| opencode | %USERPROFILE%\.config\opencode\skills\yotta-code-quality\ | .opencode\skills\ |
|
|
176
|
-
| Gemini | %USERPROFILE%\.gemini\skills\yotta-code-quality\ | .gemini\skills\ |
|
|
177
|
-
| Goose | %USERPROFILE%\.config\goose\skills\yotta-code-quality\ | .goose\skills\ |
|
|
178
|
-
| Amp | %USERPROFILE%\.config\agents\skills\yotta-code-quality\ | .agents\skills\ |
|
|
179
|
-
| Kiro | %USERPROFILE%\.kiro\skills\yotta-code-quality\ | .kiro\skills\ |
|
|
180
|
-
| WorkBuddy | %USERPROFILE%\.workbuddy\skills\yotta-code-quality\ | .workbuddy\skills\ |
|
|
181
|
-
| Trae Code CLI | %USERPROFILE%\.traecli\skills\yotta-code-quality\ | .traecli\skills\ |
|
|
182
|
-
| Trae IDE (CN) | %USERPROFILE%\.trae-cn\skills\yotta-code-quality\ | .trae\skills\ |
|
|
183
|
-
| Qwen Code | %USERPROFILE%\.qwen\skills\yotta-code-quality\ | .qwen\skills\ |
|
|
184
|
-
| Comate | %USERPROFILE%\.comate\skills\yotta-code-quality\ | .comate\skills\ |
|
|
185
|
-
| CodeBuddy | %USERPROFILE%\.codebuddy\skills\yotta-code-quality\ | .codebuddy\skills\ |
|
|
186
|
-
| Kimi | %USERPROFILE%\.kimi\skills\yotta-code-quality\ | .kimi\skills\ |
|
|
187
|
-
| Generic AGENTS.md | %USERPROFILE%\.agents\skills\yotta-code-quality\ | .agents\skills\ |
|
|
188
|
-
|
|
189
|
-
> If Codex's CODEX_HOME is set, it overrides the default; the same applies to opencode's XDG_CONFIG_HOME. .agents\skills is not a universal directory — only OpenCode / Cursor / Cline / Amp / Kimi / Gemini CLI / GitHub Copilot etc. read it; **Claude Code and Codex do not read it by default**. When unsure, use --dir or let the agent install it.
|
|
169
|
+
On the GitHub repository `YottaMeta/yotta-code-quality`, click **Code → Download ZIP**, unzip it and put the `yotta-code-quality` folder into the agent's skills directory.
|
|
190
170
|
|
|
171
|
+
### Method 4: install.sh (multi-agent one-liner script)
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
bash install.sh --agent <name> # install to the agent's default user-level directory
|
|
175
|
+
bash install.sh --dir <path> # install to the given directory
|
|
176
|
+
bash install.sh --list # list agents -> default directories
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
> Method 1 uses the npm registry (npmmirror / npmjs) and does not depend on GitHub; Methods 2/3 use GitHub and may fail without a proxy in China.
|
|
191
180
|
## Usage
|
|
192
181
|
|
|
193
182
|
Say "review this PR", "结对评审" or "发版前扫一眼" in conversation, or call `/yotta-code-quality` directly. Optional flags are listed above.
|
|
@@ -216,7 +205,7 @@ Agent: PR mode → .code-quality.yaml config → auto scope → 7 steps in pr-re
|
|
|
216
205
|
|
|
217
206
|
## Upgrade / uninstall
|
|
218
207
|
|
|
219
|
-
- **Upgrade**:
|
|
208
|
+
- **Upgrade**: reinstall the latest version to overwrite — rerun the install command you used (e.g. `npx -y @yottameta/yotta-code-quality --agent <name>` or `bash install.sh --agent <name>`). Old files in the skill directory are replaced; other project files are untouched.
|
|
220
209
|
- **Uninstall**: delete the `yotta-code-quality/` folder under the target agent's skills directory.
|
|
221
210
|
- **No side effects**: the skill writes nothing outside the project; the optional trend file (`.code-quality-history.json`) is only generated when you enable `history: true`, at the repo root.
|
|
222
211
|
|
|
@@ -238,6 +227,11 @@ Agent: PR mode → .code-quality.yaml config → auto scope → 7 steps in pr-re
|
|
|
238
227
|
|
|
239
228
|
See [CHANGELOG.md](./CHANGELOG.md).
|
|
240
229
|
|
|
230
|
+
## 参考文档
|
|
231
|
+
|
|
232
|
+
- 常见问题:`references/faq.md`
|
|
233
|
+
- 复杂场景走查:`references/walkthroughs.md`
|
|
234
|
+
|
|
241
235
|
## License
|
|
242
236
|
|
|
243
237
|
[MIT](./LICENSE) © hyhmrright (original methodology) + YottaMeta (this packaging). "Yuanzhi" / "yotta-code-quality" and the YottaMeta family names (yotta-* prefix) are YottaMeta brand identifiers; derived works must not reuse them, see [NOTICE](./NOTICE).
|
package/README.zh-CN.md
CHANGED
|
@@ -157,51 +157,39 @@ yotta-code-quality/
|
|
|
157
157
|
|
|
158
158
|
## 安装
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
以下四种方式任选,顺序即推荐优先级;技能文件一律从 **npm** 获取(GitHub 无代理较慢,npm 支持镜像)。
|
|
161
161
|
|
|
162
|
-
### 方式一:npm
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
npx -y @yottameta/yotta-code-quality --
|
|
162
|
+
### 方式一:npm 一行装(推荐)
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
# 可选国内加速:npm config set registry https://registry.npmmirror.com
|
|
166
|
+
npx -y @yottameta/yotta-code-quality --agent <智能体名称> # 装到指定智能体默认用户级技能目录
|
|
167
|
+
npx -y @yottameta/yotta-code-quality --dir <智能体的技能目录> # 指到技能目录本身(如 ~/.codex/skills)
|
|
167
168
|
```
|
|
168
|
-
> 智能体不在预置列表?用 `--dir` 指定它的 skills 目录,或手动复制(方式三)。`--list` 可查看各智能体对应的默认目录。想手动拿文件也可 `npm pack @yottameta/yotta-code-quality` 解包后按方式二/三安装。
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
- `--agent <name>` 自动装到该智能体默认用户级目录;`--list` 可查看各智能体默认目录。
|
|
171
|
+
- `--dir <路径>` 装到指定的技能目录;未收录的智能体用 `--dir` 指到它的技能目录。
|
|
172
|
+
- npmmirror 未同步新包(404):加 `--registry=https://registry.npmjs.org/`(国内需代理),或稍等镜像缓存。
|
|
173
|
+
|
|
174
|
+
### 方式二:git clone(开发者 / 有 git 环境)
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
git clone https://github.com/YottaMeta/yotta-code-quality.git <智能体的技能目录>/yotta-code-quality
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### 方式三:GitHub 下载压缩包(手动 / 无 git 环境)
|
|
181
|
+
|
|
182
|
+
在 GitHub 仓库 `YottaMeta/yotta-code-quality` 点 **Code → Download ZIP**,解压后把 `yotta-code-quality` 文件夹放进智能体技能目录。
|
|
183
|
+
|
|
184
|
+
### 方式四:install.sh(多智能体一键脚本)
|
|
185
|
+
|
|
186
|
+
```text
|
|
187
|
+
bash install.sh --agent <name> # 装到指定智能体默认用户级目录
|
|
188
|
+
bash install.sh --dir <path> # 装到指定目录
|
|
189
|
+
bash install.sh --list # 列出智能体 -> 默认目录
|
|
177
190
|
```
|
|
178
|
-
> Windows 用户:装有 Git Bash 即可用;否则用方式三手动复制。
|
|
179
|
-
|
|
180
|
-
### 方式三:手动复制
|
|
181
|
-
把整个 `yotta-code-quality` 文件夹复制到目标智能体的 skills 目录。常见位置(用户级;Windows 用 `%USERPROFILE%`,Linux/macOS 用 `~`):
|
|
182
|
-
|
|
183
|
-
| 智能体 | 用户级目录 | 项目级目录 |
|
|
184
|
-
|---|---|---|
|
|
185
|
-
| Codex | `%USERPROFILE%\.codex\skills\yotta-code-quality\` | `.codex\skills\` |
|
|
186
|
-
| Claude Code | `%USERPROFILE%\.claude\skills\yotta-code-quality\` | `.claude\skills\` |
|
|
187
|
-
| Cursor | `%USERPROFILE%\.cursor\skills\yotta-code-quality\` | `.cursor\skills\` |
|
|
188
|
-
| Windsurf | `%USERPROFILE%\.codeium\windsurf\skills\yotta-code-quality\` | `.windsurf\skills\` |
|
|
189
|
-
| opencode | `%USERPROFILE%\.config\opencode\skills\yotta-code-quality\` | `.opencode\skills\` |
|
|
190
|
-
| Gemini | `%USERPROFILE%\.gemini\skills\yotta-code-quality\` | `.gemini\skills\` |
|
|
191
|
-
| Goose | `%USERPROFILE%\.config\goose\skills\yotta-code-quality\` | `.goose\skills\` |
|
|
192
|
-
| Amp | `%USERPROFILE%\.config\agents\skills\yotta-code-quality\` | `.agents\skills\` |
|
|
193
|
-
| Kiro | `%USERPROFILE%\.kiro\skills\yotta-code-quality\` | `.kiro\skills\` |
|
|
194
|
-
| WorkBuddy | `%USERPROFILE%\.workbuddy\skills\yotta-code-quality\` | `.workbuddy\skills\` |
|
|
195
|
-
| Trae Code CLI | `%USERPROFILE%\.traecli\skills\yotta-code-quality\` | `.traecli\skills\` |
|
|
196
|
-
| Trae IDE(国内) | `%USERPROFILE%\.trae-cn\skills\yotta-code-quality\` | `.trae\skills\` |
|
|
197
|
-
| Qwen Code | `%USERPROFILE%\.qwen\skills\yotta-code-quality\` | `.qwen\skills\` |
|
|
198
|
-
| Comate | `%USERPROFILE%\.comate\skills\yotta-code-quality\` | `.comate\skills\` |
|
|
199
|
-
| CodeBuddy | `%USERPROFILE%\.codebuddy\skills\yotta-code-quality\` | `.codebuddy\skills\` |
|
|
200
|
-
| Kimi | `%USERPROFILE%\.kimi\skills\yotta-code-quality\` | `.kimi\skills\` |
|
|
201
|
-
| 通用 AGENTS.md | `%USERPROFILE%\.agents\skills\yotta-code-quality\` | `.agents\skills\` |
|
|
202
|
-
|
|
203
|
-
> Codex 默认目录若设置了环境变量 `CODEX_HOME`,以该变量为准;opencode 若设置 `XDG_CONFIG_HOME` 同理。`.agents\skills` 并非通用目录,仅 OpenCode / Cursor / Cline / Amp / Kimi / Gemini CLI / GitHub Copilot 等会读取,**Claude Code 与 Codex 默认不读**。不确定时用 `--dir` 指定,或让该智能体自行安装。
|
|
204
191
|
|
|
192
|
+
> 方式一走 npm 源(npmmirror / npmjs),不依赖 GitHub;方式二 / 三走 GitHub,国内无代理可能失败。
|
|
205
193
|
## 使用
|
|
206
194
|
|
|
207
195
|
对话中说「review this PR」「结对评审」「发版前扫一眼」,或直接调用 `/yotta-code-quality`。可选参数见上文「可选参数」。
|
|
@@ -230,7 +218,7 @@ bash install.sh --dir /path/to/skills
|
|
|
230
218
|
|
|
231
219
|
## 升级与卸载
|
|
232
220
|
|
|
233
|
-
-
|
|
221
|
+
- **升级**:重新安装最新版覆盖即可——重跑你用的安装命令(如 `npx -y @yottameta/yotta-code-quality --agent <name>` 或 `bash install.sh --agent <name>`)。技能目录内旧文件会被替换;不影响项目中其他文件。
|
|
234
222
|
- **卸载**:删除目标智能体 skills 目录下的 `yotta-code-quality/` 文件夹即可。
|
|
235
223
|
- **无副作用**:技能不写项目外文件;可选的历史/趋势文件(`.code-quality-history.json`)只在你开启 `history: true` 时生成,位于仓库根。
|
|
236
224
|
|
|
@@ -246,4 +234,9 @@ bash install.sh --dir /path/to/skills
|
|
|
246
234
|
## 来源与许可
|
|
247
235
|
|
|
248
236
|
- **方法论**蒸馏自 12 本经典软件工程著作及开源社区质量审查实践(MIT);原始方法论版权归 hyhmrright,本技能在其基础上重写为单一自包含、跨智能体通用的版本,并增补 R7 / UX1 / 按需加载会话契约。
|
|
249
|
-
- **许可:** MIT —— 详见 `LICENSE`(版权人:hyhmrright(原始方法论)+ YottaMeta(本打包))。
|
|
237
|
+
- **许可:** MIT —— 详见 `LICENSE`(版权人:hyhmrright(原始方法论)+ YottaMeta(本打包))。
|
|
238
|
+
|
|
239
|
+
## 参考文档
|
|
240
|
+
|
|
241
|
+
- references/faq.md
|
|
242
|
+
- references/walkthroughs.md
|
package/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ description: >-
|
|
|
9
9
|
「结对评审」/「发版前扫一眼」/ yotta-code-quality.
|
|
10
10
|
Do NOT trigger for: greenfield "how do I write X" with no code, pure syntax questions,
|
|
11
11
|
or tool/framework questions with no shared code.
|
|
12
|
-
version: 0.
|
|
12
|
+
version: 0.4.0
|
|
13
13
|
license: MIT
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -128,3 +128,5 @@ Scoring math and report template: **`references/common.md` only** (do not duplic
|
|
|
128
128
|
| `references/examples.md` | Tone calibration |
|
|
129
129
|
| `references/AGENTS-template.md` | Optional repo drop-in |
|
|
130
130
|
| `references/hooks.json` | Optional dangerous-command hook |
|
|
131
|
+
| `references/faq.md` | Common questions and troubleshooting |
|
|
132
|
+
| `references/walkthroughs.md` | Complex review walkthroughs |
|
package/bin/install.js
CHANGED
|
@@ -1,51 +1,97 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* yotta-code-quality
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* npx -y @yottameta/yotta-code-quality --
|
|
7
|
-
* npx -y @yottameta/yotta-code-quality
|
|
8
|
-
* npx -y @yottameta/yotta-code-quality
|
|
9
|
-
* npx -y @yottameta/yotta-code-quality
|
|
3
|
+
* @yottameta/yotta-code-quality cross-platform installer.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* npx -y @yottameta/yotta-code-quality --agent <name>
|
|
7
|
+
* npx -y @yottameta/yotta-code-quality --dir <path>
|
|
8
|
+
* npx -y @yottameta/yotta-code-quality -g
|
|
9
|
+
* npx -y @yottameta/yotta-code-quality
|
|
10
|
+
* npx -y @yottameta/yotta-code-quality --list
|
|
10
11
|
*/
|
|
11
12
|
'use strict';
|
|
13
|
+
|
|
12
14
|
const fs = require('fs');
|
|
13
15
|
const path = require('path');
|
|
14
16
|
const os = require('os');
|
|
15
17
|
|
|
16
18
|
const SKILL_NAME = 'yotta-code-quality';
|
|
17
19
|
const PKG_ROOT = path.join(__dirname, '..');
|
|
20
|
+
const COPY_SKIP = new Set(['package.json', 'bin', 'node_modules', '.git', '.github', 'test']);
|
|
18
21
|
|
|
19
|
-
// 智能体 -> 用户级默认技能目录(dirs 按优先级排列;--agent 装到第一个)
|
|
20
|
-
// 依据官方文档:.agents/skills 并非通用目录,被 OpenCode / Cursor / Cline / Amp /
|
|
21
|
-
// Kimi / Gemini CLI / GitHub Copilot 等读取;Claude Code 与 Codex 默认不读 .agents。
|
|
22
22
|
const AGENT_DIRS = {
|
|
23
23
|
claude: { label: 'Claude Code', dirs: ['.claude/skills'] },
|
|
24
24
|
cursor: { label: 'Cursor', dirs: ['.cursor/skills', '.agents/skills'] },
|
|
25
|
-
codex: { label: 'Codex', dirs: ['.codex/skills'] },
|
|
25
|
+
codex: { label: 'Codex', dirs: ['.codex/skills'] },
|
|
26
26
|
gemini: { label: 'Gemini CLI', dirs: ['.gemini/skills', '.agents/skills'] },
|
|
27
27
|
goose: { label: 'Goose', dirs: ['.config/goose/skills', '.agents/skills'] },
|
|
28
28
|
amp: { label: 'Amp', dirs: ['.config/agents/skills', '.agents/skills'] },
|
|
29
|
-
opencode: { label: 'OpenCode', dirs: ['.config/opencode/skills'] },
|
|
29
|
+
opencode: { label: 'OpenCode', dirs: ['.config/opencode/skills'] },
|
|
30
30
|
windsurf: { label: 'Windsurf', dirs: ['.codeium/windsurf/skills'] },
|
|
31
31
|
workbuddy: { label: 'WorkBuddy', dirs: ['.workbuddy/skills'] },
|
|
32
32
|
kiro: { label: 'Kiro', dirs: ['.kiro/skills'] },
|
|
33
33
|
trae: { label: 'Trae Code CLI', dirs: ['.traecli/skills'] },
|
|
34
|
-
'trae-cn': { label: 'Trae IDE
|
|
34
|
+
'trae-cn': { label: 'Trae IDE', dirs: ['.trae-cn/skills'] },
|
|
35
35
|
qwen: { label: 'Qwen Code', dirs: ['.qwen/skills'] },
|
|
36
|
-
comate: { label: 'Comate
|
|
36
|
+
comate: { label: 'Comate', dirs: ['.comate/skills'] },
|
|
37
37
|
codebuddy: { label: 'CodeBuddy Code', dirs: ['.codebuddy/skills'] },
|
|
38
38
|
kimi: { label: 'Kimi Code CLI', dirs: ['.kimi/skills'] },
|
|
39
|
-
agents: { label: '
|
|
39
|
+
agents: { label: 'Generic AGENTS.md', dirs: ['.agents/skills'] },
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
class UsageError extends Error {}
|
|
43
|
+
class TargetError extends Error {}
|
|
44
|
+
class InstallError extends Error {}
|
|
45
|
+
|
|
46
|
+
function usage() {
|
|
47
|
+
console.log('yotta-code-quality installer');
|
|
48
|
+
console.log('');
|
|
49
|
+
console.log('Usage:');
|
|
50
|
+
console.log(' npx -y @yottameta/yotta-code-quality --agent <name> Install to an agent default directory');
|
|
51
|
+
console.log(' npx -y @yottameta/yotta-code-quality --dir <path> Install to a custom directory');
|
|
52
|
+
console.log(' npx -y @yottameta/yotta-code-quality -g Install to all known agent directories');
|
|
53
|
+
console.log(' npx -y @yottameta/yotta-code-quality Auto-detect project-level directories');
|
|
54
|
+
console.log(' npx -y @yottameta/yotta-code-quality --list List supported agent directories');
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log('Options:');
|
|
57
|
+
console.log(' --agent <name> Agent key, see --list');
|
|
58
|
+
console.log(' --dir <path> Custom skills directory');
|
|
59
|
+
console.log(' -g, --global Install to all known user-level directories');
|
|
60
|
+
console.log(' --list, -l List supported agents');
|
|
61
|
+
console.log(' -h, --help Show this help');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function parseArgs(argv) {
|
|
65
|
+
const opts = { help: false, list: false, global: false, dir: null, agent: null };
|
|
66
|
+
for (let i = 0; i < argv.length; i++) {
|
|
67
|
+
const arg = argv[i];
|
|
68
|
+
if (arg === '--help' || arg === '-h') opts.help = true;
|
|
69
|
+
else if (arg === '--list' || arg === '-l') opts.list = true;
|
|
70
|
+
else if (arg === '--global' || arg === '-g') opts.global = true;
|
|
71
|
+
else if (arg === '--dir') {
|
|
72
|
+
const value = argv[++i];
|
|
73
|
+
if (!value) throw new UsageError('--dir requires a non-empty path');
|
|
74
|
+
opts.dir = value;
|
|
75
|
+
} else if (arg === '--agent') {
|
|
76
|
+
const value = argv[++i];
|
|
77
|
+
if (!value) throw new UsageError('--agent requires a non-empty name');
|
|
78
|
+
opts.agent = value.toLowerCase();
|
|
79
|
+
} else {
|
|
80
|
+
throw new UsageError('Unknown argument: ' + arg);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!opts.help) {
|
|
84
|
+
const selected = [opts.dir, opts.agent, opts.global].filter(Boolean).length;
|
|
85
|
+
if (selected > 1) throw new UsageError('Use only one of --dir, --agent, or -g');
|
|
86
|
+
}
|
|
87
|
+
return opts;
|
|
88
|
+
}
|
|
89
|
+
|
|
43
90
|
function codexUserDir() {
|
|
44
91
|
const base = process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
|
|
45
92
|
return path.join(base, 'skills');
|
|
46
93
|
}
|
|
47
94
|
|
|
48
|
-
// OpenCode 用户级目录特判:优先 $XDG_CONFIG_HOME/opencode/skills,否则 ~/.config/opencode/skills
|
|
49
95
|
function opencodeUserDir() {
|
|
50
96
|
const base = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config');
|
|
51
97
|
return path.join(base, 'opencode', 'skills');
|
|
@@ -57,82 +103,65 @@ function resolveUserDir(rel) {
|
|
|
57
103
|
return path.join(os.homedir(), rel);
|
|
58
104
|
}
|
|
59
105
|
|
|
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
106
|
function displayDir(rel) {
|
|
82
107
|
if (process.platform === 'win32') return '%USERPROFILE%\\' + rel.replace(/\//g, '\\');
|
|
83
108
|
return '~/' + rel;
|
|
84
109
|
}
|
|
85
110
|
|
|
86
|
-
function
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
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;
|
|
111
|
+
function printList() {
|
|
112
|
+
console.log('Agent -> default skill directory:');
|
|
113
|
+
for (const [key, value] of Object.entries(AGENT_DIRS)) {
|
|
114
|
+
console.log(' ' + key.padEnd(12) + value.label.padEnd(20) + value.dirs.map(displayDir).join(', '));
|
|
106
115
|
}
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log('Use --dir <path> for agents not listed. CODEX_HOME and XDG_CONFIG_HOME are respected.');
|
|
118
|
+
}
|
|
107
119
|
|
|
108
|
-
|
|
120
|
+
function assertSafeTarget(target) {
|
|
121
|
+
const rel = path.relative(PKG_ROOT, target);
|
|
122
|
+
if (rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel))) {
|
|
123
|
+
throw new UsageError('Target directory must be outside the skill source directory');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
109
126
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
127
|
+
function copyDir(src, dst, skip) {
|
|
128
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
129
|
+
if (skip.has(entry.name)) continue;
|
|
130
|
+
const from = path.join(src, entry.name);
|
|
131
|
+
const to = path.join(dst, entry.name);
|
|
132
|
+
try {
|
|
133
|
+
if (entry.isDirectory()) {
|
|
134
|
+
fs.mkdirSync(to, { recursive: true });
|
|
135
|
+
copyDir(from, to, skip);
|
|
136
|
+
} else if (entry.isFile()) {
|
|
137
|
+
fs.copyFileSync(from, to);
|
|
138
|
+
}
|
|
139
|
+
} catch (err) {
|
|
140
|
+
throw new InstallError('Failed to copy ' + from + ' -> ' + to + ': ' + err.message);
|
|
116
141
|
}
|
|
117
|
-
installTo(resolveUserDir(info.dirs[0]));
|
|
118
|
-
console.log('完成。');
|
|
119
|
-
return;
|
|
120
142
|
}
|
|
143
|
+
}
|
|
121
144
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
145
|
+
function installTo(dest) {
|
|
146
|
+
if (!dest || typeof dest !== 'string') throw new UsageError('Destination directory is required');
|
|
147
|
+
const target = path.resolve(dest, SKILL_NAME);
|
|
148
|
+
assertSafeTarget(target);
|
|
149
|
+
try {
|
|
150
|
+
fs.mkdirSync(target, { recursive: true });
|
|
151
|
+
copyDir(PKG_ROOT, target, COPY_SKIP);
|
|
152
|
+
if (!fs.existsSync(path.join(target, 'SKILL.md'))) {
|
|
153
|
+
throw new InstallError('Installed directory is missing SKILL.md');
|
|
130
154
|
}
|
|
131
|
-
|
|
132
|
-
|
|
155
|
+
} catch (err) {
|
|
156
|
+
if (err instanceof UsageError || err instanceof InstallError) throw err;
|
|
157
|
+
throw new InstallError('Cannot install to ' + target + ': ' + err.message);
|
|
133
158
|
}
|
|
159
|
+
console.log('installed -> ' + target);
|
|
160
|
+
return target;
|
|
161
|
+
}
|
|
134
162
|
|
|
135
|
-
|
|
163
|
+
function projectDirs() {
|
|
164
|
+
return [
|
|
136
165
|
'.claude/skills',
|
|
137
166
|
'.cursor/skills',
|
|
138
167
|
'.codex/skills',
|
|
@@ -150,14 +179,67 @@ function main() {
|
|
|
150
179
|
'.codebuddy/skills',
|
|
151
180
|
'.kimi/skills',
|
|
152
181
|
'.agents/skills',
|
|
153
|
-
];
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
182
|
+
].filter((dir) => fs.existsSync(dir));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function run() {
|
|
186
|
+
const opts = parseArgs(process.argv.slice(2));
|
|
187
|
+
if (opts.help) { usage(); return; }
|
|
188
|
+
if (opts.list) { printList(); return; }
|
|
189
|
+
|
|
190
|
+
if (opts.dir) { installTo(opts.dir); return; }
|
|
191
|
+
|
|
192
|
+
if (opts.agent) {
|
|
193
|
+
const info = AGENT_DIRS[opts.agent];
|
|
194
|
+
if (!info) {
|
|
195
|
+
throw new UsageError('Unknown agent: ' + opts.agent + '. Available: ' + Object.keys(AGENT_DIRS).join(', ') + '. Use --dir for a custom directory.');
|
|
196
|
+
}
|
|
197
|
+
installTo(resolveUserDir(info.dirs[0]));
|
|
198
|
+
return;
|
|
157
199
|
}
|
|
158
|
-
|
|
159
|
-
|
|
200
|
+
|
|
201
|
+
if (opts.global) {
|
|
202
|
+
const seen = new Set();
|
|
203
|
+
let count = 0;
|
|
204
|
+
for (const value of Object.values(AGENT_DIRS)) {
|
|
205
|
+
for (const dir of value.dirs) {
|
|
206
|
+
if (seen.has(dir)) continue;
|
|
207
|
+
seen.add(dir);
|
|
208
|
+
installTo(resolveUserDir(dir));
|
|
209
|
+
count++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
console.log('Installed to ' + count + ' directories.');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const dirs = projectDirs();
|
|
217
|
+
if (!dirs.length) {
|
|
218
|
+
throw new TargetError('No project-level agent directory detected. Use --agent <name> or --dir <path>.');
|
|
219
|
+
}
|
|
220
|
+
for (const dir of dirs) installTo(dir);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function main() {
|
|
224
|
+
try {
|
|
225
|
+
run();
|
|
226
|
+
} catch (err) {
|
|
227
|
+
if (err instanceof UsageError) {
|
|
228
|
+
console.error('Usage error: ' + err.message);
|
|
229
|
+
usage();
|
|
230
|
+
process.exitCode = 2;
|
|
231
|
+
} else if (err instanceof TargetError) {
|
|
232
|
+
console.error('Target error: ' + err.message);
|
|
233
|
+
process.exitCode = 4;
|
|
234
|
+
} else if (err instanceof InstallError) {
|
|
235
|
+
console.error('Install failed: ' + err.message);
|
|
236
|
+
console.error('Fix: check directory permissions and free space, then retry. Use --dir to choose another directory.');
|
|
237
|
+
process.exitCode = 1;
|
|
238
|
+
} else {
|
|
239
|
+
console.error('Unexpected error: ' + (err && err.message ? err.message : String(err)));
|
|
240
|
+
process.exitCode = 1;
|
|
241
|
+
}
|
|
160
242
|
}
|
|
161
243
|
}
|
|
162
244
|
|
|
163
|
-
main();
|
|
245
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yottameta/yotta-code-quality",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Pair-style code quality reviewer: twelve book-grounded decay risks (R1-R6, T1-T6) plus release-safety and first-paint UX checks; Iron Law findings (Symptom -> Source -> Consequence -> Remedy) and 0-100 Health Score.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -31,5 +31,8 @@
|
|
|
31
31
|
},
|
|
32
32
|
"bin": {
|
|
33
33
|
"yotta-code-quality": "bin/install.js"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"test": "node --test \"test/*.test.js\""
|
|
34
37
|
}
|
|
35
38
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# 元质常见问题
|
|
2
|
+
|
|
3
|
+
## 速查索引
|
|
4
|
+
|
|
5
|
+
- **触发**:什么时候用 · 每次都读全部文档吗
|
|
6
|
+
- **评审**:评分怎么算 · 大 PR 怎么办 · 没有测试怎么办
|
|
7
|
+
- **集成**:CI / hook 怎么接
|
|
8
|
+
- **边界**:和编译器 / 测试的关系 · 输出格式
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. 什么时候应该触发?
|
|
13
|
+
|
|
14
|
+
用户要求 review、检查代码质量、判断是否可合并、识别技术债、评估测试质量,或在发布前做质量门时触发。
|
|
15
|
+
|
|
16
|
+
## 2. 每次都要读全部参考文档吗?
|
|
17
|
+
|
|
18
|
+
不需要。先读 `SKILL.md`,按模式加载:日常 review 读 `pr-review-guide.md` 与 `common.md`;需要风险定义时读 `decay-risks.md` / `test-decay-risks.md`;发布或 UX 专项再读 `editorial-extensions.md`。
|
|
19
|
+
|
|
20
|
+
## 3. 健康分怎么算?
|
|
21
|
+
|
|
22
|
+
按发现数量与严重度加权,具体公式和报告模板在 `references/common.md`。分数用于趋势比较,不替代人工判断。
|
|
23
|
+
|
|
24
|
+
## 4. 发现必须按什么格式写?
|
|
25
|
+
|
|
26
|
+
使用 Iron Law 四段:Symptom → Source → Consequence → Remedy。缺少任一段应补齐后再输出。
|
|
27
|
+
|
|
28
|
+
## 5. 大 PR 怎么处理?
|
|
29
|
+
|
|
30
|
+
先分层:入口 / 配置 / 数据流 / 测试 / 文档。优先 R2(正确性),再看 R1 / R3 / R4;只对高风险路径展开全文,不在低风险格式化改动上消耗篇幅。
|
|
31
|
+
|
|
32
|
+
## 6. 没有测试的项目怎么评审?
|
|
33
|
+
|
|
34
|
+
明确标注“测试信号缺失”,并把它作为发现输出;不要假设测试通过。可建议最小回归清单。
|
|
35
|
+
|
|
36
|
+
## 7. 可以接入 CI 或 hook 吗?
|
|
37
|
+
|
|
38
|
+
可以。`references/hooks.json` 提供危险命令拦截示例,`references/AGENTS-template.md` 可作为仓库规则模板。接入前先在本地试运行。
|
|
39
|
+
|
|
40
|
+
## 8. 发现太多时怎么排序?
|
|
41
|
+
|
|
42
|
+
按 Blocker > Major > Warning > Suggestion。同级里先输出影响正确性和发布安全的发现。
|
|
43
|
+
|
|
44
|
+
## 9. 它会替代编译器或测试吗?
|
|
45
|
+
|
|
46
|
+
不会。元质负责评审决策与风险解释;编译、测试、运行验证仍由对应工具完成。
|
|
47
|
+
|
|
48
|
+
## 10. 输出可以直接贴到 PR 吗?
|
|
49
|
+
|
|
50
|
+
可以。按 `references/common.md` 的模板输出,包含健康分、发现清单与复核建议。
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# 元质复杂场景走查
|
|
2
|
+
|
|
3
|
+
## 走查 1:小改动发布评审
|
|
4
|
+
|
|
5
|
+
输入:一个 40 行的服务层改动,修改错误处理并新增一个参数。
|
|
6
|
+
|
|
7
|
+
1. 先读 diff 与调用点,确认入口和影响面。
|
|
8
|
+
2. 按 R2 检查错误分支是否改变语义。
|
|
9
|
+
3. 按 R3 检查新增参数是否有默认值与调用方兼容。
|
|
10
|
+
4. 按 T1/T3 检查测试是否覆盖新错误分支。
|
|
11
|
+
5. 输出 2-3 条高价值发现,附 Iron Law 四段与健康分。
|
|
12
|
+
|
|
13
|
+
## 走查 2:大型 PR 分层评审
|
|
14
|
+
|
|
15
|
+
输入:一个 2000 行重构 PR。
|
|
16
|
+
|
|
17
|
+
1. 只看文件清单与依赖图,先分出入口、领域、基础设施、测试。
|
|
18
|
+
2. 对高风险模块做全文评审,低风险机械改动只抽样。
|
|
19
|
+
3. 优先检查 R4(耦合)、R5(结构)、R6(命名)。
|
|
20
|
+
4. 输出分层结论和必须人工复核的路径。
|
|
21
|
+
5. 标注“未全文评审”的范围,不假装全覆盖。
|
|
22
|
+
|
|
23
|
+
## 走查 3:首屏 UX 专项
|
|
24
|
+
|
|
25
|
+
输入:一个新页面,功能可用但首屏偏慢。
|
|
26
|
+
|
|
27
|
+
1. 按 UX1 检查首屏关键路径。
|
|
28
|
+
2. 识别阻塞渲染的脚本、字体和图片。
|
|
29
|
+
3. 按 R7 检查是否存在不必要的复杂度。
|
|
30
|
+
4. 输出可验证的优化建议,如“延迟加载非首屏模块”“压缩首屏图片”。
|