@ultime/codecraft 1.0.2 → 1.1.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 +16 -0
- package/README.md +59 -36
- package/SKILL.md +43 -0
- package/VERSION +1 -1
- package/adapters/README.md +2 -0
- package/adapters/claude/SKILL.md +1 -1
- package/adapters/trae/SKILL.md +1 -1
- package/codecraft.config.example.json +2 -2
- package/docs/00-constitution.md +3 -3
- package/docs/01-family-cards.md +4 -4
- package/docs/02-ai-contract.md +6 -6
- package/docs/04-gates.md +4 -4
- package/docs/07-ai-prompts.md +16 -1
- package/evals/golden-tasks.md +8 -1
- package/package.json +9 -2
- package/src/cli.mjs +97 -1
- package/src/install.mjs +100 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.0 - 2026-10-27
|
|
4
|
+
|
|
5
|
+
- 新增根 `SKILL.md`,兼容 Agent Skills / `skills-npm`;安装 `@ultime/codecraft` 后可被自动发现。
|
|
6
|
+
- 新增 `codecraft install`:自动检测 Claude / Trae / Cursor,写入 `.agents/skills` 与对应目录;支持 `--agent` / `--global` / `--dest` / `--force` / `--dry-run`。
|
|
7
|
+
- README 增加三种安装方式:`skills-npm`、内置安装器、手动指针。
|
|
8
|
+
- `docs/07-ai-prompts.md` 与 adapters 补充安装入口。
|
|
9
|
+
|
|
10
|
+
## 1.0.3 - 2026-10-27
|
|
11
|
+
|
|
12
|
+
- 文档从 v0 草稿固化为 v1 稳定版。
|
|
13
|
+
- 示例门禁改为通用 typecheck / test / lint,不再出现项目专用命令。
|
|
14
|
+
- 适配器描述加入中文触发词,不读文档时也能更准确地触发。
|
|
15
|
+
- README 增加 5 分钟上手教程;Skills 集合 README 去除自用表述。
|
|
16
|
+
- CI 使用 Node 22,并在发布前检查版本是否已存在。
|
|
17
|
+
- 新增 CLI 测试:version / help / 未知命令 / `--ci` / init 参数校验。
|
|
18
|
+
|
|
3
19
|
## 1.0.2 - 2026-10-27
|
|
4
20
|
|
|
5
21
|
- 新增 `docs/07-ai-prompts.md`:可直接复制的 AI 提示词,覆盖审计 / 报告 / 新项目 / 评审 / 架构 / 模式 / 脚手架 / Design System。
|
package/README.md
CHANGED
|
@@ -19,47 +19,47 @@
|
|
|
19
19
|
|
|
20
20
|
规则正文只在 [`docs/`](./docs/);其它位置只放入口与指针,避免第二份真源。
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
> 第一次用:直接看 [安装](#安装) 和 [第一次使用](#第一次使用)。
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
## 安装
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
# 在 codecraft 目录内
|
|
28
|
-
node bin/codecraft.mjs check --root .
|
|
26
|
+
### 方式 A:npm + skills-npm(推荐,多项目 / 团队)
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
```bash
|
|
29
|
+
npm i -D @ultime/codecraft skills-npm
|
|
30
|
+
npx skills-npm setup
|
|
32
31
|
```
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
之后每次 `npm install` 都会把 `node_modules/@ultime/codecraft` 里的 skill 同步到 agent 目录:`.agents/skills/codecraft`,以及检测到的 Claude / Trae / Cursor 目录。需要 Node.js >= 22.20(`skills-npm` 的要求)。
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
### 方式 B:Codecraft 自带安装器(单次,无额外依赖)
|
|
37
36
|
|
|
38
37
|
```bash
|
|
39
|
-
npx @ultime/codecraft
|
|
40
|
-
npx @ultime/codecraft@latest check --root .
|
|
38
|
+
npx @ultime/codecraft install
|
|
41
39
|
```
|
|
42
40
|
|
|
43
|
-
|
|
41
|
+
自动检测当前项目的 agent,把 `SKILL.md`、`docs/`、`scenarios/`、`prompts/` 复制到 `.agents/skills/codecraft` 和对应 agent 目录(`.claude/skills`、`.trae/skills`、`.cursor/skills`)。
|
|
44
42
|
|
|
45
43
|
```bash
|
|
46
|
-
|
|
47
|
-
npx codecraft
|
|
44
|
+
npx @ultime/codecraft install --agent claude # 指定 agent,可逗号分隔
|
|
45
|
+
npx @ultime/codecraft install --global --agent claude # 装到用户目录
|
|
46
|
+
npx @ultime/codecraft install --dry-run # 只看计划
|
|
47
|
+
npx @ultime/codecraft install --force # 覆盖已有目录
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
### 方式 C:手动指针
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
npm pack
|
|
54
|
-
npm i -D /path/to/ultime-codecraft-<version>.tgz
|
|
55
|
-
npx codecraft check --root .
|
|
56
|
-
```
|
|
52
|
+
不复制文件,只在项目规则里留一行:
|
|
57
53
|
|
|
58
|
-
|
|
54
|
+
- Trae:`.trae/rules/codecraft.md`
|
|
55
|
+
- Claude:`CLAUDE.md` 或 `~/.claude/CLAUDE.md`
|
|
56
|
+
- 其他:`AGENTS.md`
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
```md
|
|
59
|
+
代码任务先读 <Codecraft 路径>/codecraft/adapters/trae/SKILL.md
|
|
60
|
+
```
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
平台入口:
|
|
63
63
|
|
|
64
64
|
| 平台 | 入口文件 |
|
|
65
65
|
|---|---|
|
|
@@ -67,21 +67,32 @@ npx codecraft check --root .
|
|
|
67
67
|
| Trae | [`adapters/trae/SKILL.md`](./adapters/trae/SKILL.md) |
|
|
68
68
|
| Claude | [`adapters/claude/SKILL.md`](./adapters/claude/SKILL.md) |
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
## 第一次使用
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
用 Codecraft 审计本项目,只读,不改文件。
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
只启用 skill、不说 Codecraft 时,agent 可能按普通项目分析处理,不保证走 Audit 模式。带上名字最稳。
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
- Claude:在 `~/.claude/CLAUDE.md` 或项目 `CLAUDE.md` 加同一行。
|
|
74
|
-
- 其他 agent:在项目 `AGENTS.md` 加同一行。
|
|
78
|
+
更多场景(只出报告、新项目、重构评审、架构设计、模式选型、脚手架、Design System)见 [docs/07-ai-prompts.md](./docs/07-ai-prompts.md)。
|
|
75
79
|
|
|
76
|
-
|
|
80
|
+
需要本地检查时再装 CLI:
|
|
77
81
|
|
|
78
|
-
|
|
82
|
+
```bash
|
|
83
|
+
npx @ultime/codecraft check --root .
|
|
84
|
+
npx codecraft check --root . # 已安装为项目依赖时
|
|
85
|
+
```
|
|
79
86
|
|
|
80
|
-
|
|
87
|
+
本地开发 / 未发布时用 tarball:
|
|
81
88
|
|
|
82
|
-
|
|
89
|
+
```bash
|
|
90
|
+
npm pack
|
|
91
|
+
npm i -D /path/to/ultime-codecraft-<version>.tgz
|
|
92
|
+
npx codecraft check --root .
|
|
93
|
+
```
|
|
83
94
|
|
|
84
|
-
##
|
|
95
|
+
## 模式
|
|
85
96
|
|
|
86
97
|
| 模式 | 是否改文件 | 对应命令 |
|
|
87
98
|
|---|---|---|
|
|
@@ -101,6 +112,7 @@ codecraft <command> [options]
|
|
|
101
112
|
| `audit` | 内置规则 + `codecraft.config.json` 里的 gates,出只读报告 |
|
|
102
113
|
| `plan` | 把 findings 转成只读升级计划;默认不跑 gates |
|
|
103
114
|
| `init` | 生成 app / library 骨架;默认 dry-run |
|
|
115
|
+
| `install` | 把 skill 安装到 agent skills 目录;默认写入,`--dry-run` 只看计划 |
|
|
104
116
|
| `version` | 输出版本号 |
|
|
105
117
|
|
|
106
118
|
### 常用
|
|
@@ -115,6 +127,9 @@ codecraft audit --config codecraft.config.json --fail-fast
|
|
|
115
127
|
codecraft plan --root . --with-gates
|
|
116
128
|
codecraft init --root . --name demo # dry-run
|
|
117
129
|
codecraft init --root . --name demo --apply # 写盘
|
|
130
|
+
codecraft install # 自动检测并安装
|
|
131
|
+
codecraft install --agent trae,claude --force
|
|
132
|
+
codecraft install --dry-run
|
|
118
133
|
```
|
|
119
134
|
|
|
120
135
|
### 参数
|
|
@@ -132,13 +147,18 @@ codecraft init --root . --name demo --apply # 写盘
|
|
|
132
147
|
| `--with-gates` | — | 关 | `plan` 执行 gates |
|
|
133
148
|
| `--name <name>` | 字符串 | — | `init` 的 app / package 名称;`--apply` 时必填 |
|
|
134
149
|
| `--apply` | — | 关 | `init` 写盘;已存在路径跳过,不覆盖 |
|
|
150
|
+
| `--agent <list>` | `auto` / `claude` / `trae` / `cursor` / `generic` | `auto` | `install` 目标,可逗号分隔 |
|
|
151
|
+
| `--global` | — | 关 | `install` 写入用户目录 |
|
|
152
|
+
| `--dest <path>` | 目录 | — | `install` 的显式目标 |
|
|
153
|
+
| `--force` | — | 关 | `install` 覆盖已有 codecraft 目录 |
|
|
154
|
+
| `--dry-run` | — | 关 | `install` 只输出计划,不写盘 |
|
|
135
155
|
|
|
136
156
|
### 退出码
|
|
137
157
|
|
|
138
158
|
| 码 | 含义 |
|
|
139
159
|
|---|---|
|
|
140
160
|
| `0` | 通过;warning 不阻断 |
|
|
141
|
-
| `1` | 有 error findings
|
|
161
|
+
| `1` | 有 error findings、install 失败,或有 gate 失败 |
|
|
142
162
|
| `2` | 用法错误、root 不存在、配置非法 |
|
|
143
163
|
|
|
144
164
|
### 输出
|
|
@@ -174,7 +194,7 @@ A4(单一收口)属于结构判断,由 review 与项目门禁负责,不
|
|
|
174
194
|
"pack": "auto",
|
|
175
195
|
"gates": [
|
|
176
196
|
{ "name": "typecheck", "run": "pnpm typecheck", "timeoutMs": 120000 },
|
|
177
|
-
{ "name": "
|
|
197
|
+
{ "name": "test", "run": "pnpm test", "timeoutMs": 120000 }
|
|
178
198
|
]
|
|
179
199
|
}
|
|
180
200
|
```
|
|
@@ -188,14 +208,16 @@ A4(单一收口)属于结构判断,由 review 与项目门禁负责,不
|
|
|
188
208
|
## 目录
|
|
189
209
|
|
|
190
210
|
```text
|
|
211
|
+
SKILL.md 标准 agent skill 入口(skills-npm / install 使用)
|
|
191
212
|
docs/ 宪法、族卡、AI 契约、风格总图、模式、架构、AI 提示词、门禁
|
|
192
213
|
scenarios/ 新项目 / 旧项目审计 / 只出报告 / 重构评审
|
|
193
|
-
adapters/ generic / Trae / Claude
|
|
214
|
+
adapters/ generic / Trae / Claude 手动指针
|
|
194
215
|
prompts/ 输出格式
|
|
195
|
-
src/ + bin/ CLI
|
|
216
|
+
src/ + bin/ CLI(含 install)
|
|
196
217
|
tests/ node:test 用例
|
|
197
218
|
templates/ init --apply 的 app / library 骨架
|
|
198
219
|
evals/ golden tasks(人工回归)
|
|
220
|
+
ROADMAP.md 后续版本计划与交接说明
|
|
199
221
|
```
|
|
200
222
|
|
|
201
223
|
## 版本与稳定承诺
|
|
@@ -203,6 +225,7 @@ evals/ golden tasks(人工回归)
|
|
|
203
225
|
- semver;当前版本见 [VERSION](./VERSION)。
|
|
204
226
|
- 规则 ID `A1–A21` 稳定;增删规则属于 minor 以上的变更。
|
|
205
227
|
- 报告始终携带版本号;跨版本对比以 JSON 为准。
|
|
228
|
+
- 后续计划:[ROADMAP.md](https://github.com/ultime-space/skills/blob/main/codecraft/ROADMAP.md)。
|
|
206
229
|
|
|
207
230
|
## 边界
|
|
208
231
|
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: codecraft
|
|
3
|
+
description: 语言无关的代码规范(Codecraft)。用于项目代码审计与分析、架构设计、重构评审、代码规范检查和脚手架。Language-agnostic code standard for auditing, reviewing, designing, and scaffolding code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Codecraft(代码手艺)
|
|
7
|
+
|
|
8
|
+
## 先读
|
|
9
|
+
|
|
10
|
+
1. 项目 `AGENTS.md` / `rules/`
|
|
11
|
+
2. `docs/00-constitution.md`
|
|
12
|
+
3. 只读相关族卡:`docs/01-family-cards.md`
|
|
13
|
+
4. 设计架构时:`docs/06-architecture.md`
|
|
14
|
+
5. 需要选型时:`docs/05-patterns.md`
|
|
15
|
+
6. 选一个场景:`scenarios/`
|
|
16
|
+
7. 按 `docs/02-ai-contract.md` 执行
|
|
17
|
+
8. 按 `prompts/output.md` 输出
|
|
18
|
+
9. 不知道怎么说时:`docs/07-ai-prompts.md`
|
|
19
|
+
|
|
20
|
+
## 模式
|
|
21
|
+
|
|
22
|
+
- **Audit(审计)**:只读,出报告。
|
|
23
|
+
- **Plan(计划)**:只读,出架构 / 升级计划。
|
|
24
|
+
- **Apply(执行)**:改代码 + 跑门禁。
|
|
25
|
+
|
|
26
|
+
## 工作流
|
|
27
|
+
|
|
28
|
+
1. 判定任务属于哪个场景。
|
|
29
|
+
2. 只读相关族卡,不要一次加载全部。
|
|
30
|
+
3. 先出计划;Apply 前确认范围。
|
|
31
|
+
4. 跑项目验证命令;不能跑要说明原因。
|
|
32
|
+
5. 按 `prompts/output.md` 输出。
|
|
33
|
+
|
|
34
|
+
## 禁止
|
|
35
|
+
|
|
36
|
+
- Audit / Plan 模式改文件。
|
|
37
|
+
- 把业务逻辑放进 Transport 或 Page。
|
|
38
|
+
- 内部代码 import `external/` 或生成类型。
|
|
39
|
+
- 手改生成物。
|
|
40
|
+
- 写敏感信息;发现即停止、脱敏、提示轮换。
|
|
41
|
+
- 安全红线登记例外。
|
|
42
|
+
|
|
43
|
+
规则正文只在 `docs/`;本文件只做入口。
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0
|
|
1
|
+
1.1.0
|
package/adapters/README.md
CHANGED
|
@@ -9,4 +9,6 @@ Core 是 `docs/` + `scenarios/` + `scripts/`;adapters 只做入口,不复制
|
|
|
9
9
|
|
|
10
10
|
规则:adapter 只写“读什么、按什么流程、输出什么”,规则正文留在 `docs/`。
|
|
11
11
|
|
|
12
|
+
包根的 [`SKILL.md`](../SKILL.md) 是标准 agent skill 入口(`skills-npm` / `codecraft install` 使用);本目录的平台文件用于手动指针接入。两者二选一,不要同时维护两套正文。
|
|
13
|
+
|
|
12
14
|
使用者提示词(怎么对 AI 说):[`../docs/07-ai-prompts.md`](../docs/07-ai-prompts.md)。
|
package/adapters/claude/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: codecraft
|
|
3
|
-
description: Language-agnostic code standard for
|
|
3
|
+
description: 语言无关的代码规范(Codecraft)。用于项目代码审计与分析、架构设计、重构评审、代码规范检查和脚手架。Language-agnostic code standard for auditing, reviewing, designing, and scaffolding code.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Codecraft(代码手艺)
|
package/adapters/trae/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: codecraft
|
|
3
|
-
description: Language-agnostic code standard for
|
|
3
|
+
description: 语言无关的代码规范(Codecraft)。用于项目代码审计与分析、架构设计、重构评审、代码规范检查和脚手架。Language-agnostic code standard for auditing, reviewing, designing, and scaffolding code.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Codecraft(代码手艺)
|
package/docs/00-constitution.md
CHANGED
package/docs/01-family-cards.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# 代码族卡
|
|
1
|
+
# 代码族卡 v1(11 个环节)
|
|
2
2
|
|
|
3
|
-
> 2026-10-
|
|
4
|
-
> 用途:把《代码宪法
|
|
3
|
+
> 2026-10-27 · v1 稳定版。
|
|
4
|
+
> 用途:把《代码宪法 v1》落到每个代码族(环节);不同族可以不同形状,族内必须同形。
|
|
5
5
|
> 术语:English(中文)。
|
|
6
6
|
|
|
7
7
|
## 0. 卡模板
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
- UI 类型(`XxxProps / XxxEmits`)放组件目录或 `types/<domain>`。
|
|
73
73
|
- **项目决策**:`shared` 不是强制层;后端非 TS 时用 external + Wrapper;只有一个消费者时不建 shared。
|
|
74
74
|
- **特殊**:`shared/types/` 不能变成杂物间;跨应用业务类型用 `packages/domain-<x>`。
|
|
75
|
-
- **命名**:按《代码宪法
|
|
75
|
+
- **命名**:按《代码宪法 v1》§3.1(外部保持原名;通用中性;业务后缀角色;不用 `I` / `model_xxx`);本卡不重复全表。
|
|
76
76
|
- **依赖**:General ← Business;Business 不 import External;UI 只消费 Business / General。
|
|
77
77
|
- **契约**:外部类型只被 Wrapper import;页面 / 组件 / 行为层只用内部类型。
|
|
78
78
|
- **状态与错误**:类型里不允许不可能组合;互斥状态用联合类型。
|
package/docs/02-ai-contract.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
# AI 生成契约
|
|
1
|
+
# AI 生成契约 v1
|
|
2
2
|
|
|
3
|
-
> 2026-10-
|
|
4
|
-
> 用途:所有模型 / agent 生成或修改代码前先读;与《代码宪法
|
|
3
|
+
> 2026-10-27 · v1 稳定版。
|
|
4
|
+
> 用途:所有模型 / agent 生成或修改代码前先读;与《代码宪法 v1》《代码族卡 v1》配套。
|
|
5
5
|
> 术语:English(中文)。
|
|
6
6
|
|
|
7
7
|
## 1. 先读
|
|
8
8
|
|
|
9
|
-
1. 《代码宪法
|
|
10
|
-
2. 相关《代码族卡
|
|
9
|
+
1. 《代码宪法 v1》
|
|
10
|
+
2. 相关《代码族卡 v1》
|
|
11
11
|
3. 设计架构时:`06-architecture.md`(档位 / 七步法 / 边界 / ADR)
|
|
12
12
|
4. 需要选型时:`05-patterns.md`(按力选,不按名字选)
|
|
13
13
|
5. 项目覆盖:`AGENTS.md` / `rules/` / `README`
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
- 禁止手改生成物。
|
|
24
24
|
- 禁止空 catch / 静默失败。
|
|
25
25
|
- 禁止跨族复制而不登记母版与分叉点。
|
|
26
|
-
- 禁止复制项目门禁(如
|
|
26
|
+
- 禁止复制项目门禁(如 typecheck / lint / test);只通过 config 调用。
|
|
27
27
|
- 禁止在 Plan 模式改文件;只输出计划。
|
|
28
28
|
- 禁止把密码 / 密钥 / 令牌 / AK/SK / 连接串 / 客户隐私写进代码、文档、示例或提示词;发现即脱敏并提醒。
|
|
29
29
|
- 禁止外部文档引用内部文档 / 内部路径 / 内部主机名。
|
package/docs/04-gates.md
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
| 层 | 负责 | 例子 | 是否内置 |
|
|
8
8
|
|---|---|---|---|
|
|
9
|
-
| **Universal(通用)** | Codecraft | A2 /
|
|
10
|
-
| **Business(业务)** | 项目 | typecheck
|
|
9
|
+
| **Universal(通用)** | Codecraft | A2 / A11 / A17、密钥扫描、文档路径 | 是 |
|
|
10
|
+
| **Business(业务)** | 项目 | typecheck、单测、lint、契约测试、视觉回归、迁移检查 | 否,通过 config 调用 |
|
|
11
11
|
|
|
12
12
|
原则:**通用规则内置,业务门禁编排。** 不复制项目门禁,避免第二套实现。
|
|
13
13
|
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"pack": "auto",
|
|
30
30
|
"gates": [
|
|
31
31
|
{ "name": "typecheck", "run": "pnpm typecheck", "timeoutMs": 120000 },
|
|
32
|
-
{ "name": "
|
|
32
|
+
{ "name": "test", "run": "pnpm test", "timeoutMs": 120000 }
|
|
33
33
|
]
|
|
34
34
|
}
|
|
35
35
|
```
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
|---|---|---|
|
|
45
45
|
| **App** | A17 / A21(A4 人工评审) | typecheck、单测、e2e、视觉回归 |
|
|
46
46
|
| **Library** | A2 / A11 / A21 | build、单测、exports 检查、依赖对账 |
|
|
47
|
-
| **Design System** | A2 / A11 / A21 |
|
|
47
|
+
| **Design System** | A2 / A11 / A21 | 构建、契约快照、视觉回归、a11y |
|
|
48
48
|
| **Docs** | A21 | 死链、三线头、交付白名单 |
|
|
49
49
|
|
|
50
50
|
### 4.1 内置规则
|
package/docs/07-ai-prompts.md
CHANGED
|
@@ -6,7 +6,22 @@
|
|
|
6
6
|
|
|
7
7
|
## 1. 先让 AI 找到 Codecraft
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
最快的方式:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @ultime/codecraft install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
或走 npm 同步:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm i -D @ultime/codecraft skills-npm
|
|
19
|
+
npx skills-npm setup
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
装好后项目里会有 `.agents/skills/codecraft/SKILL.md`(以及检测到的 agent 目录)。
|
|
23
|
+
|
|
24
|
+
也可以手动在 agent 入口里留一条指针,不要复制规则:
|
|
10
25
|
|
|
11
26
|
- Trae:项目 `.trae/rules/codecraft.md`
|
|
12
27
|
- Claude:`CLAUDE.md`
|
package/evals/golden-tasks.md
CHANGED
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
|
|
98
98
|
- 输入:`packages/` 下的 UI 包,README 引用了内部 `docs/开发计划/...`,`dist/tokens.css` 缺标记。
|
|
99
99
|
- 模式:Audit(`--pack design-system`)。
|
|
100
|
-
- 期望:命中 A11 / A21
|
|
100
|
+
- 期望:命中 A11 / A21;不重复实现项目的 typecheck / lint / test 门禁;给出改为自洽文档的最小改法。
|
|
101
101
|
- 失败信号:只报 library 规则;把内部文档路径当正常引用;建议复制项目门禁。
|
|
102
102
|
|
|
103
103
|
## 15. 密钥扫描
|
|
@@ -107,6 +107,13 @@
|
|
|
107
107
|
- 期望:命中 A21;只报文件与行号,不回显密钥;提示轮换。
|
|
108
108
|
- 失败信号:漏报;把密钥原文打印到报告;把普通变量名误报为密钥。
|
|
109
109
|
|
|
110
|
+
## 16. 安装到 agent
|
|
111
|
+
|
|
112
|
+
- 输入:空项目,无 agent 配置目录。
|
|
113
|
+
- 命令:`codecraft install --root . --agent generic`;再执行一次;最后 `--force`。
|
|
114
|
+
- 期望:生成 `.agents/skills/codecraft/SKILL.md`、`docs/`、`scenarios/`、`prompts/`;第二次 skip;`--force` 覆盖。
|
|
115
|
+
- 失败信号:复制到错误目录;覆盖用户已有内容;`SKILL.md` 引用断链。
|
|
116
|
+
|
|
110
117
|
## 评分
|
|
111
118
|
|
|
112
119
|
- 每条任务:pass / fail。
|
package/package.json
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ultime/codecraft",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Language-agnostic code standard as an installable skill package.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
7
7
|
"code-standard",
|
|
8
8
|
"lint",
|
|
9
|
-
"skill"
|
|
9
|
+
"skill",
|
|
10
|
+
"audit",
|
|
11
|
+
"architecture",
|
|
12
|
+
"review",
|
|
13
|
+
"scaffold",
|
|
14
|
+
"agent-skills"
|
|
10
15
|
],
|
|
16
|
+
"author": "UltimeLam",
|
|
11
17
|
"license": "MIT",
|
|
12
18
|
"repository": {
|
|
13
19
|
"type": "git",
|
|
@@ -25,6 +31,7 @@
|
|
|
25
31
|
"codecraft": "bin/codecraft.mjs"
|
|
26
32
|
},
|
|
27
33
|
"files": [
|
|
34
|
+
"SKILL.md",
|
|
28
35
|
"bin",
|
|
29
36
|
"src",
|
|
30
37
|
"docs",
|
package/src/cli.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import { check } from './check.mjs'
|
|
|
4
4
|
import { loadConfig, runGates } from './gates.mjs'
|
|
5
5
|
import { buildPlan, summarizePlan } from './plan.mjs'
|
|
6
6
|
import { applyInitPlan, buildInitPlan } from './init.mjs'
|
|
7
|
+
import { applyInstallPlan, buildInstallPlan, parseAgents } from './install.mjs'
|
|
7
8
|
|
|
8
9
|
const PACKAGE = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
|
|
9
10
|
const VERSION = PACKAGE.version
|
|
@@ -15,12 +16,18 @@ Commands:
|
|
|
15
16
|
audit check + configured gates; read-only report
|
|
16
17
|
plan Read-only upgrade plan from findings
|
|
17
18
|
init Scaffold an app or package (dry-run unless --apply)
|
|
19
|
+
install Install the skill into agent skills directories
|
|
18
20
|
version Print version
|
|
19
21
|
|
|
20
22
|
Options:
|
|
21
23
|
--root <path> Project root (default: cwd)
|
|
22
24
|
--pack app|library|design-system|auto Rule pack (default: auto)
|
|
23
25
|
--config <path> Config file (default: codecraft.config.json)
|
|
26
|
+
--agent auto|claude|trae|cursor|generic Install target, comma-separated (default: auto)
|
|
27
|
+
--global Install into the home directory
|
|
28
|
+
--dest <path> Explicit destination (relative to root / home)
|
|
29
|
+
--force Replace an existing codecraft skill directory
|
|
30
|
+
--dry-run Show the install plan without writing
|
|
24
31
|
--no-gates Skip gates in audit / plan
|
|
25
32
|
--with-gates Run configured gates in plan
|
|
26
33
|
--fail-fast Stop gates after the first failure
|
|
@@ -51,7 +58,7 @@ export function main(argv) {
|
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
const command = args.command || 'check'
|
|
54
|
-
if (!['check', 'audit', 'plan', 'init'].includes(command)) {
|
|
61
|
+
if (!['check', 'audit', 'plan', 'init', 'install'].includes(command)) {
|
|
55
62
|
console.error(`codecraft: unknown command "${command}"`)
|
|
56
63
|
return 2
|
|
57
64
|
}
|
|
@@ -62,6 +69,42 @@ export function main(argv) {
|
|
|
62
69
|
return 2
|
|
63
70
|
}
|
|
64
71
|
|
|
72
|
+
if (command === 'install') {
|
|
73
|
+
let agents
|
|
74
|
+
try {
|
|
75
|
+
agents = parseAgents(args.agent)
|
|
76
|
+
} catch (error) {
|
|
77
|
+
console.error(`codecraft: ${error.message}`)
|
|
78
|
+
return 2
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
const plan = buildInstallPlan(root, { agents, global: args.global, dest: args.dest })
|
|
82
|
+
const applied = args.dryRun ? null : applyInstallPlan(plan, { force: args.force })
|
|
83
|
+
const meta = {
|
|
84
|
+
version: VERSION,
|
|
85
|
+
mode: 'install',
|
|
86
|
+
root,
|
|
87
|
+
scope: args.global ? 'global' : 'project',
|
|
88
|
+
agent: args.agent,
|
|
89
|
+
dest: args.dest || null,
|
|
90
|
+
dryRun: args.dryRun,
|
|
91
|
+
targets: plan.length,
|
|
92
|
+
created: applied?.created.length ?? 0,
|
|
93
|
+
replaced: applied?.replaced.length ?? 0,
|
|
94
|
+
skipped: applied?.skipped.length ?? 0,
|
|
95
|
+
}
|
|
96
|
+
if (args.format === 'json') {
|
|
97
|
+
console.log(JSON.stringify({ ...meta, plan, applied }, null, 2))
|
|
98
|
+
} else {
|
|
99
|
+
console.log(formatInstall(meta, plan, applied))
|
|
100
|
+
}
|
|
101
|
+
return plan.length ? 0 : 1
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error(`codecraft: ${error.message}`)
|
|
104
|
+
return 1
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
65
108
|
let config
|
|
66
109
|
try {
|
|
67
110
|
config = loadConfig(root, args.config)
|
|
@@ -180,6 +223,11 @@ function parseArgs(argv) {
|
|
|
180
223
|
failFast: false,
|
|
181
224
|
name: '',
|
|
182
225
|
apply: false,
|
|
226
|
+
agent: 'auto',
|
|
227
|
+
global: false,
|
|
228
|
+
dest: '',
|
|
229
|
+
force: false,
|
|
230
|
+
dryRun: false,
|
|
183
231
|
format: 'md',
|
|
184
232
|
severity: 'warn',
|
|
185
233
|
ci: false,
|
|
@@ -196,7 +244,12 @@ function parseArgs(argv) {
|
|
|
196
244
|
else if (arg === '--with-gates') args.withGates = true
|
|
197
245
|
else if (arg === '--fail-fast') args.failFast = true
|
|
198
246
|
else if (arg === '--apply') args.apply = true
|
|
247
|
+
else if (arg === '--global') args.global = true
|
|
248
|
+
else if (arg === '--force') args.force = true
|
|
249
|
+
else if (arg === '--dry-run') args.dryRun = true
|
|
199
250
|
else if (arg === '--name') args.name = argv[++i] ?? ''
|
|
251
|
+
else if (arg === '--agent') args.agent = argv[++i] ?? 'auto'
|
|
252
|
+
else if (arg === '--dest') args.dest = argv[++i] ?? ''
|
|
200
253
|
else if (arg === '--root') args.root = argv[++i] ?? '.'
|
|
201
254
|
else if (arg === '--pack') args.pack = argv[++i] ?? 'auto'
|
|
202
255
|
else if (arg === '--config') args.config = argv[++i] ?? ''
|
|
@@ -329,6 +382,49 @@ function formatInit(meta, plan, applied) {
|
|
|
329
382
|
return lines.filter((line, index) => !(line === '' && lines[index - 1] === '')).join('\n')
|
|
330
383
|
}
|
|
331
384
|
|
|
385
|
+
function formatInstall(meta, plan, applied) {
|
|
386
|
+
const lines = [
|
|
387
|
+
'# Codecraft Install',
|
|
388
|
+
'',
|
|
389
|
+
`- Version: ${meta.version}`,
|
|
390
|
+
`- Mode: install`,
|
|
391
|
+
`- Scope: ${meta.scope}`,
|
|
392
|
+
`- Agent: ${meta.agent}`,
|
|
393
|
+
`- Root: ${meta.root}`,
|
|
394
|
+
`- Dest: ${meta.dest ?? '(auto)'}`,
|
|
395
|
+
`- Dry run: ${meta.dryRun}`,
|
|
396
|
+
`- Targets: ${meta.targets}`,
|
|
397
|
+
]
|
|
398
|
+
|
|
399
|
+
if (applied) {
|
|
400
|
+
lines.push(
|
|
401
|
+
`- Created: ${meta.created}`,
|
|
402
|
+
`- Replaced: ${meta.replaced}`,
|
|
403
|
+
`- Skipped: ${meta.skipped}`,
|
|
404
|
+
)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (!plan.length) {
|
|
408
|
+
lines.push('', '未找到可安装的目标;请用 `--agent` 指定,或先创建 agent 配置目录。')
|
|
409
|
+
} else {
|
|
410
|
+
lines.push('', '## Plan', '', '| Agent | Target | Action |', '|---|---|---|')
|
|
411
|
+
for (const entry of plan) {
|
|
412
|
+
lines.push(`| ${entry.agent} | ${entry.target} | ${entry.action} |`)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
lines.push(
|
|
417
|
+
'',
|
|
418
|
+
'## Next',
|
|
419
|
+
'',
|
|
420
|
+
meta.dryRun
|
|
421
|
+
? '- Re-run without `--dry-run` to write the skill.'
|
|
422
|
+
: '- Restart the agent or reload skills;然后说:`用 Codecraft 审计本项目,只读,不改文件。`',
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
return lines.join('\n')
|
|
426
|
+
}
|
|
427
|
+
|
|
332
428
|
function header(meta) {
|
|
333
429
|
return [
|
|
334
430
|
`# Codecraft ${title(meta.mode)}`,
|
package/src/install.mjs
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
|
|
6
|
+
const PACKAGE_ROOT = fileURLToPath(new URL('..', import.meta.url))
|
|
7
|
+
const SKILL_FILES = ['SKILL.md']
|
|
8
|
+
const SKILL_DIRS = ['docs', 'scenarios', 'prompts']
|
|
9
|
+
|
|
10
|
+
const AGENT_DIRS = {
|
|
11
|
+
claude: '.claude/skills',
|
|
12
|
+
trae: '.trae/skills',
|
|
13
|
+
cursor: '.cursor/skills',
|
|
14
|
+
generic: '.agents/skills',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const AGENT_MARKERS = {
|
|
18
|
+
claude: ['.claude', 'CLAUDE.md'],
|
|
19
|
+
trae: ['.trae'],
|
|
20
|
+
cursor: ['.cursor'],
|
|
21
|
+
generic: ['.agents'],
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const AGENTS = Object.keys(AGENT_DIRS)
|
|
25
|
+
|
|
26
|
+
export function parseAgents(value) {
|
|
27
|
+
if (!value || value === 'auto') return []
|
|
28
|
+
const agents = [...new Set(value.split(',').map((item) => item.trim()).filter(Boolean))]
|
|
29
|
+
const invalid = agents.filter((agent) => !AGENTS.includes(agent))
|
|
30
|
+
if (invalid.length) {
|
|
31
|
+
throw new Error(`unknown agent: ${invalid.join(', ')}(可选:auto, ${AGENTS.join(', ')})`)
|
|
32
|
+
}
|
|
33
|
+
return agents
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function buildInstallPlan(root, options = {}) {
|
|
37
|
+
const base = options.global ? os.homedir() : path.resolve(root)
|
|
38
|
+
const explicit = options.agents ?? []
|
|
39
|
+
const invalid = explicit.filter((agent) => !AGENTS.includes(agent))
|
|
40
|
+
if (invalid.length) {
|
|
41
|
+
throw new Error(`unknown agent: ${invalid.join(', ')}(可选:${AGENTS.join(', ')})`)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const agents = explicit.length ? explicit : detectAgents(base, options.global)
|
|
45
|
+
const destinations = options.dest
|
|
46
|
+
? [{ agent: 'custom', dir: path.resolve(base, options.dest) }]
|
|
47
|
+
: agents.map((agent) => ({ agent, dir: path.join(base, AGENT_DIRS[agent]) }))
|
|
48
|
+
|
|
49
|
+
assertSource()
|
|
50
|
+
|
|
51
|
+
return destinations.map(({ agent, dir }) => {
|
|
52
|
+
const target = path.join(dir, 'codecraft')
|
|
53
|
+
const exists = fs.existsSync(target)
|
|
54
|
+
return { agent, target, exists, action: exists ? 'exists' : 'create' }
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function applyInstallPlan(plan, options = {}) {
|
|
59
|
+
const created = []
|
|
60
|
+
const skipped = []
|
|
61
|
+
const replaced = []
|
|
62
|
+
|
|
63
|
+
for (const entry of plan) {
|
|
64
|
+
if (entry.exists && !options.force) {
|
|
65
|
+
skipped.push(entry.target)
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
if (entry.exists) {
|
|
69
|
+
fs.rmSync(entry.target, { recursive: true, force: true })
|
|
70
|
+
replaced.push(entry.target)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fs.mkdirSync(entry.target, { recursive: true })
|
|
74
|
+
for (const file of SKILL_FILES) {
|
|
75
|
+
fs.copyFileSync(path.join(PACKAGE_ROOT, file), path.join(entry.target, file))
|
|
76
|
+
}
|
|
77
|
+
for (const dir of SKILL_DIRS) {
|
|
78
|
+
fs.cpSync(path.join(PACKAGE_ROOT, dir), path.join(entry.target, dir), { recursive: true })
|
|
79
|
+
}
|
|
80
|
+
created.push(entry.target)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { created, skipped, replaced }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function detectAgents(base, global) {
|
|
87
|
+
const found = AGENTS.filter((agent) =>
|
|
88
|
+
AGENT_MARKERS[agent].some((marker) => fs.existsSync(path.join(base, marker))),
|
|
89
|
+
)
|
|
90
|
+
if (global) return found.length ? found : ['generic']
|
|
91
|
+
return [...new Set([...found, 'generic'])]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function assertSource() {
|
|
95
|
+
for (const file of SKILL_FILES) {
|
|
96
|
+
if (!fs.existsSync(path.join(PACKAGE_ROOT, file))) {
|
|
97
|
+
throw new Error(`skill source is incomplete: missing ${file}`)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|