@ultime/codecraft 1.4.0 → 1.5.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 (62) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/CONTRIBUTING.md +3 -0
  3. package/README.md +41 -32
  4. package/SKILL.md +2 -2
  5. package/VERSION +1 -1
  6. package/adapters/README.md +3 -4
  7. package/codecraft.config.example.json +5 -1
  8. package/docs/00-constitution.md +2 -2
  9. package/docs/02-ai-contract.md +12 -1
  10. package/docs/04-gates.md +21 -6
  11. package/docs/07-ai-prompts.md +5 -6
  12. package/docs/08-audit-contract.md +141 -0
  13. package/evals/cases.json +110 -0
  14. package/evals/fixtures/a11-marker/packages/core/dist/tokens.css +4 -0
  15. package/evals/fixtures/a11-marker/packages/core/package.json +1 -0
  16. package/evals/fixtures/a11-marker/packages/core/src/index.ts +1 -0
  17. package/evals/fixtures/a17-boundaries/codecraft.config.json +5 -0
  18. package/evals/fixtures/a17-boundaries/src/pages/home.ts +1 -0
  19. package/evals/fixtures/a17-default/src/pages/home.ts +1 -0
  20. package/evals/fixtures/a17-generated-data/src/icons/icons.ts +2 -0
  21. package/evals/fixtures/a17-generated-data/src/pages/home.ts +3 -0
  22. package/evals/fixtures/a17-generated-header/src/pages/home.ts +5 -0
  23. package/evals/fixtures/a17-generated-header/src/types/project.ts +4 -0
  24. package/evals/fixtures/a17-local/src/pages/home.ts +4 -0
  25. package/evals/fixtures/a17-local/src/types/local.ts +3 -0
  26. package/evals/fixtures/a17-local/src/utils/format.ts +3 -0
  27. package/evals/fixtures/a2-declared/packages/core/package.json +6 -0
  28. package/evals/fixtures/a2-declared/packages/core/src/index.ts +3 -0
  29. package/evals/fixtures/a2-declared/packages/kit/package.json +1 -0
  30. package/evals/fixtures/a2-workspace/packages/core/package.json +1 -0
  31. package/evals/fixtures/a2-workspace/packages/core/src/index.ts +3 -0
  32. package/evals/fixtures/a2-workspace/packages/kit/package.json +1 -0
  33. package/evals/fixtures/a21-doc-paths/packages/ui/README.md +5 -0
  34. package/evals/fixtures/a21-doc-paths/packages/ui/package.json +1 -0
  35. package/evals/fixtures/a21-doc-paths/packages/ui/src/index.ts +1 -0
  36. package/evals/fixtures/a21-placeholders/.env +2 -0
  37. package/evals/fixtures/a21-placeholders/server/application.yml +9 -0
  38. package/evals/fixtures/a21-placeholders/src/pages/home.ts +1 -0
  39. package/evals/fixtures/a21-plaintext/application.yml +5 -0
  40. package/evals/fixtures/a21-plaintext/src/main/java/Ali.java +3 -0
  41. package/evals/fixtures/a21-plaintext/src/pages/home.ts +1 -0
  42. package/evals/fixtures/a6-clean/src/pages/handled.ts +8 -0
  43. package/evals/fixtures/a6-empty-catch/src/pages/empty.ts +3 -0
  44. package/evals/fixtures/ignore-active/codecraft.config.json +5 -0
  45. package/evals/fixtures/ignore-active/src/pages/home.ts +1 -0
  46. package/evals/fixtures/ignore-expired/codecraft.config.json +5 -0
  47. package/evals/fixtures/ignore-expired/src/pages/home.ts +1 -0
  48. package/evals/fixtures/library-a11/dist/tokens.css +3 -0
  49. package/evals/fixtures/library-a11/package.json +4 -0
  50. package/evals/fixtures/library-a11/src/index.ts +1 -0
  51. package/evals/fixtures/zero-files/package.json +4 -0
  52. package/evals/golden-tasks.md +6 -0
  53. package/evals/run.mjs +75 -0
  54. package/package.json +4 -2
  55. package/prompts/output.md +15 -4
  56. package/scenarios/audit-existing.md +15 -8
  57. package/src/check.mjs +290 -40
  58. package/src/cli.mjs +158 -8
  59. package/src/gates.mjs +28 -1
  60. package/src/plan.mjs +2 -0
  61. package/adapters/claude/SKILL.md +0 -42
  62. package/adapters/trae/SKILL.md +0 -42
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.0 - 2026-10-27
4
+
5
+ - 新增 `--exclude <glob>`(可重复):扫描级排除,用于 fixture / 第三方目录;报告头与 JSON 记录 exclude 模式。
6
+ - 新增 `npm run self-check`,CI 同步执行;仓库自检以 `--exclude 'evals/fixtures/**'` 达到 0 findings。
7
+ - 修正 README 与 FAQ 的扫描范围描述:A21 额外扫描配置与后端源码扩展名,结构规则仍只扫 JS/TS。
8
+ - pack 自动判定补齐 Vue CLI(`vue.config.*`)与单页 Web 入口(html + 框架依赖 + `src/main.*`),避免把 Vue / React 应用判成 `library`。
9
+ - 结构规则跳过压缩 / 构建产物(A21 不受影响),减少与源码重复的 A6 / A17 findings。
10
+ - A21 修正误报:`MYSQL_PWD="$VAR" cmd` 这类 shell 环境变量前缀不再算明文口令;引号值只取引号内内容。
11
+ - 扫描跳过 `.agents` / `.trae` / `.claude` / `.cursor` 等 agent 安装目录,避免把已安装 skill 的 fixture 当项目代码。
12
+ - 修复 A6 行号漂移:剥离注释时保留换行,空 catch 的行号与源码一致。
13
+ - A17 支持按文件头识别生成类型(`本文件由…生成` / `勿手改` / `@generated`),并解析相对路径与 `@/` `~/` `#/` 别名;生成的数据 / 资源模块不触发。
14
+ - A21 扩充:新增阿里云 `LTAI`、明文 `password` / `secret` / `apiKey` / `accessKey` 赋值扫描,覆盖 `.java` / `.kt` / `.properties` / `.xml` / `.env`;跳过环境变量、占位符与测试目录。
15
+ - 新增单元测试与 CLI eval(`a17-generated-header` / `a21-plaintext`)。
16
+ - 移除 `adapters/claude` / `adapters/trae` 等单 agent 入口;手动指针统一指向 `SKILL.md`,文档改用通用 `.agents` 表述。
17
+ - 新增 `docs/08-audit-contract.md`:逐条判定、证据门槛、静态边界、A1–A21 判定矩阵、一致性检查、P0–P3 与计划表。
18
+ - `prompts/output.md` 增加 A1–A21 全覆盖、证据 / 局限列、0 findings 声明与计数可复现要求。
19
+ - `docs/02-ai-contract.md` 与 `scenarios/audit-existing.md` 接入审计证据门槛。
20
+ - `SKILL.md` 路由与读法把审计指向 `08`;`README` 目录说明同步。
21
+ - 新增 A6 空 catch 静态检查(app / library)。
22
+ - A17 支持 `boundaries.external` / `boundaries.generated` 配置,覆盖约定外的生成类型路径。
23
+ - 新增 `--format sarif`(SARIF 2.1.0),可直接接 GitHub Code Scanning。
24
+ - 新增 `--changed` / `--since <ref>`:只报告变更 / 未跟踪文件中的 findings;底层仍全量扫描。
25
+ - 新增 GitHub Actions CI:`npm test` + `npm run eval` + `npm pack --dry-run`。
26
+ - 新增 `evals/run.mjs` + fixtures:覆盖 A6 / A17(含 boundaries)/ ignore / A11 / 0 文件 / SARIF。
27
+
3
28
  ## 1.4.0 - 2026-10-27
4
29
 
5
30
  - 仓库改为 `skills/codecraft` 标准集合布局,可被 `skills` CLI 直接发现。
package/CONTRIBUTING.md CHANGED
@@ -20,6 +20,8 @@
20
20
 
21
21
  ```bash
22
22
  npm test
23
+ npm run eval
24
+ npm run self-check
23
25
  npm pack --dry-run
24
26
  node bin/codecraft.mjs check --root <项目>
25
27
  ```
@@ -35,4 +37,5 @@ node bin/codecraft.mjs check --root <项目>
35
37
  - **minor**:新能力——CLI 选项、检查规则、适配器、模板、向后兼容的配置字段。
36
38
  - **patch**:修复、文档、提示词、测试、CI,或无行为变化的内部调整。
37
39
  - `2.0` 不设时间表;没有破坏性变更就不进 major。
40
+ - v1 内容收口未完成前不发版;内容变更先累积在 `CHANGELOG.md` 的 Unreleased。
38
41
  - 发布前同时改 `VERSION`、`package.json`、`CHANGELOG.md`,并跑 `npm test` 与 `npm pack --dry-run`。
package/README.md CHANGED
@@ -62,23 +62,16 @@ npx skills-npm setup
62
62
 
63
63
  ### 方式 C:手动指针
64
64
 
65
- 不复制文件,只在项目规则里留一行:
65
+ 不复制文件,只在通用入口里留一行:
66
66
 
67
- - 通用:`AGENTS.md`
68
- - Claude:`CLAUDE.md` 或 `~/.claude/CLAUDE.md`
69
- - Trae:`.trae/rules/codecraft.md`
67
+ - 通用:`AGENTS.md`(推荐)
68
+ - 其它 agent:使用该 agent 自己的入口文件,内容相同
70
69
 
71
70
  ```md
72
- 代码任务先读 <Codecraft 仓库路径>/skills/codecraft/adapters/trae/SKILL.md
71
+ 代码任务先读 <Codecraft 路径>/skills/codecraft/SKILL.md
73
72
  ```
74
73
 
75
- 平台入口:
76
-
77
- | 平台 | 入口文件 |
78
- |---|---|
79
- | 通用(读 `AGENTS.md`) | [`adapters/generic/AGENTS.md`](./adapters/generic/AGENTS.md) |
80
- | Claude | [`adapters/claude/SKILL.md`](./adapters/claude/SKILL.md) |
81
- | Trae | [`adapters/trae/SKILL.md`](./adapters/trae/SKILL.md) |
74
+ 入口示例:[`adapters/generic/AGENTS.md`](./adapters/generic/AGENTS.md)。其它 agent 不需要单独适配文件,统一指向 `SKILL.md`,避免维护多份正文。
82
75
 
83
76
  ## 第一次使用
84
77
 
@@ -134,6 +127,8 @@ codecraft check --root .
134
127
  codecraft check --pack library --root ../../packages/core
135
128
  codecraft check --pack design-system
136
129
  codecraft check --format json --ci
130
+ codecraft check --changed --ci # 只看变更 / 未跟踪文件
131
+ codecraft check --since origin/main --ci # PR 内变更
137
132
  codecraft audit --severity error
138
133
  codecraft audit --config codecraft.config.json --fail-fast
139
134
  codecraft plan --root . --with-gates
@@ -148,7 +143,10 @@ codecraft init --root . --name demo --apply # 写盘
148
143
  | `--root <path>` | 目录 | `.` | 被检查的项目根 |
149
144
  | `--pack <name>` | `app` / `library` / `design-system` / `auto` | `auto` | 规则包;CLI 优先于 config |
150
145
  | `--config <path>` | 文件 | `codecraft.config.json` | 相对 `--root` |
151
- | `--format <fmt>` | `md` / `json` | `md` | 输出格式 |
146
+ | `--changed` | — | 关 | 只报告变更 / 未跟踪文件中的 findings |
147
+ | `--since <ref>` | git ref | — | 只报告自该 ref 以来变动文件中的 findings |
148
+ | `--exclude <glob>` | 路径 / glob | — | 扫描时跳过;可重复。用于 fixture、第三方目录等不应参与检查的路径 |
149
+ | `--format <fmt>` | `md` / `json` / `sarif` | `md` | 输出格式 |
152
150
  | `--severity <level>` | `warn` / `error` | `warn` | findings 的严重级别 |
153
151
  | `--ci` | — | 关 | 等价于 `--severity error` |
154
152
  | `--fail-fast` | — | 关 | gates 遇到第一个失败即停止 |
@@ -168,26 +166,30 @@ codecraft init --root . --name demo --apply # 写盘
168
166
  ### 输出
169
167
 
170
168
  - 默认 Markdown:头部元信息 + Findings 表 + Gates 表。
171
- - `--format json`:包含 `version` / `mode` / `pack` / `rules` / `findings` / `plan` / `gates` / `summary`,用于 CI、趋势和两次运行 diff。
169
+ - `--format json`:包含 `version` / `mode` / `pack` / `rules` / `exclude` / `findings` / `plan` / `gates` / `summary`,用于 CI、趋势和两次运行 diff。
170
+ - `--format sarif`:SARIF 2.1.0,可直接上传 GitHub Code Scanning。
171
+ - `--changed` / `--since` 只过滤 findings,底层仍做全量扫描;JSON 的 `scope` 为 `changed`,`changed` 为变更文件数。
172
172
  - 报告始终带版本号与规则 ID;`plan` 明确声明「No files were changed by this command.」。
173
173
 
174
174
  ## Rule Packs
175
175
 
176
176
  | Pack | 内置规则 | 检查范围 |
177
177
  |---|---|---|
178
- | `app` | A17 / A21 | `pages / components / behavior` 不 import `external/` / `generated/`;密钥扫描 |
179
- | `library` | A2 / A11 / A21 | 包不 import app、相对路径不逃逸、workspace 依赖必须声明;生成物必须有“勿手改 / 派生”标记;密钥扫描 |
180
- | `design-system` | A2 / A11 / A21 | library 规则 + 包内公开文档不得引用内部 `docs/` |
178
+ | `app` | A6 / A17 / A21 | 空 catch;`pages / components / behavior` 不 import `external/` / `generated/`(含生成文件头与 `boundaries` 配置);密钥扫描 |
179
+ | `library` | A2 / A6 / A11 / A21 | 包不 import app、相对路径不逃逸、workspace 依赖必须声明;空 catch;生成物必须有“勿手改 / 派生”标记;密钥扫描 |
180
+ | `design-system` | A2 / A6 / A11 / A21 | library 规则 + 包内公开文档不得引用内部 `docs/` |
181
181
 
182
182
  `--pack auto` 的判定顺序(基于 JS/TS 生态的目录与 `package.json`):
183
183
 
184
- 1. 有 `apps/` 或 `src/pages` → `app`
185
- 2. 有 `packages/` 或根 `package.json` → `library`
186
- 3. 其余 → `app`
184
+ 1. 有 `apps/`、`src/pages` / `pages` / `app` / `src/app`,或 Nuxt / Taro / uni-app / Vue CLI(`vue.config.*`)标记 → `app`
185
+ 2. 单页 Web 入口三件套:`index.html`(根或 `public/`)+ 框架依赖(`vue` / `react` / `svelte` 等)+ `src/main.*` / `src/index.*` → `app`
186
+ 3. 一级子目录命中上述任一标记(workspace 内嵌应用)→ `app`
187
+ 4. 有 `packages/`、`src/` 或根 `package.json` → `library`
188
+ 5. 其余 → `app`
187
189
 
188
- `design-system` 不参与自动判定,必须显式指定。
190
+ `design-system` 不参与自动判定,必须显式指定。带 demo 页的库若被误判为 `app`,用 `--pack library` 覆盖。
189
191
 
190
- A4(单一收口)属于结构判断,由 review 与项目门禁负责,不由静态扫描替代。
192
+ A4(单一收口)、A5(互斥布尔 / 非法状态)、A8(派生状态)属于结构或状态判断,由 review 与项目门禁负责,不由静态扫描替代。
191
193
 
192
194
  ## 配置
193
195
 
@@ -207,13 +209,18 @@ A4(单一收口)属于结构判断,由 review 与项目门禁负责,不
207
209
  "reason": "legacy page; migrate in 2026-Q4",
208
210
  "expires": "2026-12-31"
209
211
  }
210
- ]
212
+ ],
213
+ "boundaries": {
214
+ "external": ["@/types/external"],
215
+ "generated": ["@/types/project"]
216
+ }
211
217
  }
212
218
  ```
213
219
 
214
220
  - `pack`:`app` / `library` / `design-system` / `auto`。
215
221
  - `gates`:数组;每项必须有一个非空的 `run` 字符串,可选 `name`、`timeoutMs`(默认 `120000`)。
216
222
  - `ignore`:例外登记(A12)。每项必须有 `rule` / `file` / `reason`,`expires` 可选(`YYYY-MM-DD`);`file` 支持 `*` / `**` / `?`。安全规则 `A21` 不可豁免。
223
+ - `boundaries`:A17 的补充路径。生成类型优先按文件头自动识别;`external` / `generated` 填 import 前缀或 glob,用于头部没有标记、或路径不在约定内的项目。
217
224
  - 命中的 findings 不参与退出码,但仍出现在报告的 `Ignored` 表与 JSON 的 `ignored`;过期的条目不生效,列在 `Expired Exceptions`。
218
225
  - gate 在 `--root` 下通过 shell 执行,注入 `CI=1`;失败时报告尾部 40 行 / 4000 字符。
219
226
  - `check` 不跑 gates;`audit` 默认跑;`plan` 只在 `--with-gates` 时跑。
@@ -222,16 +229,15 @@ A4(单一收口)属于结构判断,由 review 与项目门禁负责,不
222
229
  ## 目录
223
230
 
224
231
  ```text
225
- SKILL.md 标准 agent skill 入口(skills-npm / install 使用)
226
- docs/ 宪法、族卡、AI 契约、风格总图、模式、架构、AI 提示词、门禁
232
+ SKILL.md 标准 agent skill 入口(skills add / skills-npm 使用)
233
+ docs/ 宪法、族卡、AI 契约、审计契约、风格总图、模式、架构、AI 提示词、门禁
227
234
  scenarios/ 新项目 / 旧项目审计 / 只出报告 / 重构评审
228
- adapters/ generic / Trae / Claude 手动指针
235
+ adapters/ generic 手动指针(其它 agent 统一指向 SKILL.md)
229
236
  prompts/ 输出格式
230
237
  src/ + bin/ CLI(check / audit / plan / init)
231
238
  tests/ node:test 用例
232
239
  templates/ init --apply 的 app / library 骨架
233
- evals/ golden tasks(人工回归)
234
- ROADMAP.md 后续版本计划与交接说明
240
+ evals/ CLI eval fixtures + golden tasks(人工回归)
235
241
  ```
236
242
 
237
243
  ## 版本与稳定承诺
@@ -243,7 +249,7 @@ ROADMAP.md 后续版本计划与交接说明
243
249
  - 不按「感觉重要」升 major;`2.0` 不设时间表。
244
250
  - 规则 ID `A1–A21` 稳定;增删规则属于 minor 以上的变更。
245
251
  - 报告始终携带版本号;跨版本对比以 JSON 为准。
246
- - 后续计划:[ROADMAP.md](https://github.com/ultime-space/skills/blob/main/skills/codecraft/ROADMAP.md)。
252
+ - 版本历史见 [CHANGELOG.md](./CHANGELOG.md);计划不在仓库内维护。
247
253
 
248
254
  ## FAQ
249
255
 
@@ -252,13 +258,16 @@ ROADMAP.md 后续版本计划与交接说明
252
258
  - **怎么装到指定 agent?** `npx skills add ultime-space/skills --skill codecraft`;交互选 agent,或用 `-a <agent>` 非交互。安装路径由 `skills` CLI 维护,本 skill 不枚举。
253
259
  - **`check` / `audit` / `plan` 有什么区别?** `check` 只跑内置规则;`audit` 额外跑 config 里的 gates;`plan` 只读,把 findings 转成计划,默认不跑 gates。
254
260
  - **为什么不自动跑 typecheck / test?** 门禁由项目提供,Codecraft 只编排,避免第二套实现。
255
- - **monorepo 为什么被判成 app / library?** 有 `pages/`、`app/`、`manifest.json + pages.json`、Taro / uni-app 依赖或嵌套应用时按 `app`;有 `packages/` 或 `src/` 时按 `library`;仍不确定就显式传 `--pack`。
256
- - **支持哪些文件?** 只扫 JS/TS 相关扩展名与 `package.json`;其它语言不覆盖。
261
+ - **monorepo 为什么被判成 app / library?** 有 `pages/`、`app/`、`manifest.json + pages.json`、Taro / uni-app / Vue CLI 标记、单页 Web 入口或嵌套应用时按 `app`;有 `packages/` 或 `src/` 时按 `library`;仍不确定就显式传 `--pack`。
262
+ - **支持哪些文件?** A2 / A6 / A11 / A17 扫描 JS/TS 相关扩展名与 `package.json`;A21 额外扫描配置与后端源码(`.yml` / `.yaml` / `.env` / `.properties` / `.xml` / `.java` / `.kt` 等)里的明文密钥。其它语言仍不在检查范围。
257
263
 
258
264
  ## 边界
259
265
 
260
266
  - 静态检查是文本级:能覆盖高置信模式,可能漏报或误报;最终以项目门禁与 review 为准。
261
- - 机检只扫描 JS/TS 相关文件(`.ts` / `.tsx` / `.js` / `.jsx` / `.mjs` / `.cjs` / `.vue` / `.svelte`)与 `package.json`,其它语言不覆盖。
267
+ - 结构规则(A2 / A6 / A11 / A17)只扫描 JS/TS 相关文件(`.ts` / `.tsx` / `.js` / `.jsx` / `.mjs` / `.cjs` / `.vue` / `.svelte`)与 `package.json`;A21 额外扫描配置与后端源码扩展名(见上),但只做密钥 / 内部路径模式匹配,不做语言级分析。
268
+ - 压缩 / 构建产物(≤3 行且存在 >1000 字符的单行)不参与 A2 / A6 / A11 / A17,避免与源码重复报同一问题;A21 仍会扫描它们。
269
+ - `.agents` / `.trae` / `.claude` / `.cursor` 等 agent 安装目录不扫描,避免把已安装 skill 的 fixture 当项目代码。
270
+ - `--exclude` 是扫描级排除,不产生 findings;它不能替代 `ignore`(后者用于登记已发现问题的例外,且 A21 不可豁免)。
262
271
  - 不内置任何业务规则、框架约定或公司内部门禁。
263
272
  - 不读取、不上传代码;所有检查在本地完成。
264
273
 
package/SKILL.md CHANGED
@@ -22,7 +22,7 @@ description: 面向 JS/TS 的代码规范与架构设计(Codecraft)。默认
22
22
 
23
23
  | 任务 | 先读 | 产出 |
24
24
  |---|---|---|
25
- | 审计 / 评审现有代码 | 宪法 + 相关族卡 | 报告(只读) |
25
+ | 审计 / 评审现有代码 | 宪法 + `docs/08-audit-contract.md` + 相关族卡 | 报告(只读) |
26
26
  | 设计架构 / 拆边界 | `docs/06-architecture.md` + 宪法 | 计划 / ADR(只读) |
27
27
  | 新项目 / 脚手架 | `06` + `scenarios/new-project.md` | 骨架计划;必要时 `init` |
28
28
  | 选型(模式 / 库) | `docs/05-patterns.md` | 选型与代价 |
@@ -36,7 +36,7 @@ description: 面向 JS/TS 的代码规范与架构设计(Codecraft)。默认
36
36
  4. 只读相关族卡:`docs/01-family-cards.md`(前端项目才读 Page / Component)
37
37
  5. 需要选型时:`docs/05-patterns.md`
38
38
  6. 选一个场景:`scenarios/`
39
- 7. 按 `docs/02-ai-contract.md` 执行
39
+ 7. 按 `docs/02-ai-contract.md` 执行;审计还必须读 `docs/08-audit-contract.md`
40
40
  8. 按 `prompts/output.md` 输出
41
41
  9. 不知道怎么说时:`docs/07-ai-prompts.md`
42
42
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 1.4.0
1
+ 1.5.0
@@ -3,12 +3,11 @@
3
3
  Core 是 `docs/` + `scenarios/` + `scripts/`;adapters 只做入口,不复制规则。
4
4
 
5
5
  - `generic/AGENTS.md`:任何读 `AGENTS.md` 的 agent
6
- - `trae/SKILL.md`:Trae skill
7
- - `claude/SKILL.md`:Claude skill
8
- - 未来:Cursor / Copilot / Gemini 等
6
+
7
+ 其它 agent 使用自己的入口文件,统一指向包根 [`SKILL.md`](../SKILL.md);不为单一 agent 维护专属文件。
9
8
 
10
9
  规则:adapter 只写“读什么、按什么流程、输出什么”,规则正文留在 `docs/`。
11
10
 
12
- 包根的 [`SKILL.md`](../SKILL.md) 是标准 agent skill 入口(`skills add` / `skills-npm` 使用);本目录的平台文件用于手动指针接入。两者二选一,不要同时维护两套正文。
11
+ 包根的 [`SKILL.md`](../SKILL.md) 是标准 agent skill 入口(`skills add` / `skills-npm` 使用);本目录只保留通用手动指针。
13
12
 
14
13
  使用者提示词(怎么对 AI 说):[`../docs/07-ai-prompts.md`](../docs/07-ai-prompts.md)。
@@ -19,5 +19,9 @@
19
19
  "reason": "legacy page; migrate in 2026-Q4",
20
20
  "expires": "2026-12-31"
21
21
  }
22
- ]
22
+ ],
23
+ "boundaries": {
24
+ "external": ["@/types/external"],
25
+ "generated": ["@/types/project"]
26
+ }
23
27
  }
@@ -312,8 +312,8 @@ repo/
312
312
 
313
313
  ## 6. 机检现状
314
314
 
315
- - 已内置(`codecraft check`):A2 / A11 / A17 / A21(静态、文本级)。
316
- - 需要项目门禁或人工评审:A3 / A4(收口判断)/ A5–A9(类型与结构)/ A12–A20。
315
+ - 已内置(`codecraft check`):A2 / A6(空 catch)/ A11 / A17 / A21(静态、文本级)。
316
+ - 需要项目门禁或人工评审:A3 / A4(收口判断)/ A5 / A7–A9(类型与结构)/ A12–A20。
317
317
  - 静态扫描只覆盖高置信模式;漏报由项目门禁补,误报按 A12 登记例外。
318
318
 
319
319
  ## 7. 待定
@@ -56,7 +56,18 @@
56
56
  4. **风险 / 不确定**
57
57
  5. **后续**:owner + 到期
58
58
 
59
- ## 6. Review Checklist(评审清单)
59
+ Audit 报告还必须满足 `docs/08-audit-contract.md`。
60
+
61
+ ## 6. 审计证据门槛
62
+
63
+ - A1–A21 全覆盖;不适用写 `na`。
64
+ - 每条 `pass` 必须给文件行号或可复现命令;只有静态检查通过时写 `pass(静态)`。
65
+ - `0 findings` 只能写成「静态检查未命中」,不能写成规则通过;必须写明 A17 / A21 等覆盖盲区。
66
+ - 计数必须带检索式;不能复现的数字不写。
67
+ - 出结论前做一致性检查:A4 / A8 / A11 / A17 / A21 与证据矛盾时降级。
68
+ - 优先级按 P0–P3;计划每阶段可回滚、有验收。
69
+
70
+ ## 7. Review Checklist(评审清单)
60
71
 
61
72
  - [ ] 族形正确(Page / Behavior / Transport;Node 后端跳过 Page / Component)
62
73
  - [ ] 依赖向内
package/docs/04-gates.md CHANGED
@@ -34,22 +34,27 @@
34
34
  ],
35
35
  "ignore": [
36
36
  { "rule": "A17", "file": "src/pages/legacy/**", "reason": "legacy page", "expires": "2026-12-31" }
37
- ]
37
+ ],
38
+ "boundaries": {
39
+ "external": ["@/types/external"],
40
+ "generated": ["@/types/project"]
41
+ }
38
42
  }
39
43
  ```
40
44
 
41
45
  - `pack`:`app` / `library` / `design-system` / `auto`;CLI `--pack` 优先。
42
46
  - `gates`:数组;每项必须有 `run`,可选 `name` / `timeoutMs`。
43
47
  - `ignore`:例外登记(A12);`rule` / `file` / `reason` 必填,`expires` 可选。过期条目不生效,报告中单列;安全规则 `A21` 不可豁免。
48
+ - `boundaries`:A17 的补充路径;生成类型优先按文件头识别,`external` / `generated` 填 import 前缀或 glob,覆盖头部无标记或路径不在约定内的项目。
44
49
  - 配置文件默认 `codecraft.config.json`;可用 `--config` 指定。
45
50
 
46
51
  ## 4. 按项目类型选门禁
47
52
 
48
53
  | 项目类型 | 通用 | 业务 |
49
54
  |---|---|---|
50
- | **App** | A17 / A21(A4 人工评审) | typecheck、单测、e2e、视觉回归 |
51
- | **Library** | A2 / A11 / A21 | build、单测、exports 检查、依赖对账 |
52
- | **Design System** | A2 / A11 / A21 | 构建、契约快照、视觉回归、a11y |
55
+ | **App** | A6 / A17 / A21(A4 人工评审) | typecheck、单测、e2e、视觉回归 |
56
+ | **Library** | A2 / A6 / A11 / A21 | build、单测、exports 检查、依赖对账 |
57
+ | **Design System** | A2 / A6 / A11 / A21 | 构建、契约快照、视觉回归、a11y |
53
58
  | **Docs** | A21 | 死链、三线头、交付白名单 |
54
59
 
55
60
  ### 4.1 内置规则
@@ -57,13 +62,23 @@
57
62
  | Rule | Pack | 检查 |
58
63
  |---|---|---|
59
64
  | A2 | library / design-system | 包不 import apps;相对路径不逃逸;workspace 依赖必须声明 |
65
+ | A6 | all | 空 catch / 静默失败 |
60
66
  | A11 | library / design-system | 生成物必须有“勿手改 / 派生”标记 |
61
- | A17 | app | `pages / components / behavior` 不 import `external/` / `generated/` |
62
- | A21 | all | 高置信密钥模式(私钥 / AWS / GitHub / Slack / API key) |
67
+ | A17 | app | `pages / components / behavior` 不 import `external/` / `generated/`;生成类型按文件头(`本文件由…生成` / `勿手改` / `@generated`)自动识别;自定义路径用 `boundaries` 补充 |
68
+ | A21 | all | 高置信密钥模式(私钥 / AWS / 阿里云 `LTAI` / GitHub / Slack / API key);配置与后端源码中的明文 `password` / `secret` / `apiKey` / `accessKey` 赋值;环境变量引用与占位符不报 |
63
69
  | A21 | design-system | 包内公开文档(README / USAGE / CHANGELOG / contract)不引用内部 `docs/` |
64
70
 
65
71
  A4(单一收口)是结构判断,仍由 review / 项目门禁负责,不由静态扫描替代。
66
72
 
73
+ ### 4.2 CI 用法
74
+
75
+ ```bash
76
+ codecraft check --changed --ci # PR 只拦变更文件
77
+ codecraft check --changed --format sarif > codecraft.sarif
78
+ ```
79
+
80
+ `--changed` / `--since` 只过滤 findings;底层仍做全量扫描。SARIF 可直接上传 GitHub Code Scanning。
81
+
67
82
  ## 5. 执行顺序
68
83
 
69
84
  1. 快速静态(内置规则、lint);
@@ -24,17 +24,16 @@ npx skills-npm setup
24
24
 
25
25
  装好后项目里会有 `.agents/skills/codecraft/SKILL.md`(以及检测到的 agent 目录)。
26
26
 
27
- 也可以手动在 agent 入口里留一条指针,不要复制规则:
27
+ 也可以手动在通用入口里留一条指针,不要复制规则:
28
28
 
29
- - 通用:`AGENTS.md`
30
- - Claude:`CLAUDE.md`
31
- - Trae:项目 `.trae/rules/codecraft.md`
29
+ - 通用:`AGENTS.md`(推荐)
30
+ - 其它 agent:使用该 agent 自己的入口文件,内容相同
32
31
 
33
32
  ```md
34
- 代码任务先读 <Codecraft 仓库路径>/skills/codecraft/adapters/<平台>/...
33
+ 代码任务先读 <Codecraft 路径>/skills/codecraft/SKILL.md
35
34
  ```
36
35
 
37
- 平台对应:Trae → `adapters/trae/SKILL.md`,Claude → `adapters/claude/SKILL.md`,其他 → `adapters/generic/AGENTS.md`。
36
+ 入口示例:`adapters/generic/AGENTS.md`。其它 agent 不需要单独适配文件,统一指向 `SKILL.md`。
38
37
 
39
38
  ## 2. 最小开场
40
39
 
@@ -0,0 +1,141 @@
1
+ # 审计输出契约 v1
2
+
3
+ > 2026-10-27 · v1
4
+ > 用途:约束 Audit 模式的判定、证据、局限与一致性,防止把“静态检查 0 findings”写成“全部通过”。
5
+ > 范围:JS/TS 项目,默认前端;Node 后端只复用结构与安全类判定。
6
+ > 关系:流程见 `docs/02-ai-contract.md`;格式见 `prompts/output.md`;规则正文见 `docs/00-constitution.md` 与 `docs/01-family-cards.md`。
7
+
8
+ ## 1. 必填结构
9
+
10
+ Audit 报告必须包含:
11
+
12
+ 1. **范围与方法**:仓库 / 分支 / 目录、只读声明、执行的命令、未执行项与原因。
13
+ 2. **逐条判定**:A1–A21 全覆盖;不适用写 `na` 并说明原因。
14
+ 3. **差距 / 风险**:按优先级分组,每条带证据。
15
+ 4. **计划**:阶段、内容、可回滚、验收。
16
+ 5. **验证**:命令 + 结果;不能跑要写原因。
17
+ 6. **局限**:静态检查覆盖不到的部分,尤其是 A17 / A21。
18
+
19
+ 逐条判定表固定为:
20
+
21
+ ```md
22
+ | ID | 判定 | 证据 | 局限 |
23
+ |---|---|---|---|
24
+ | A4 | warn | `useList.ts` 6 处、页面 20+ 处 `code === 200` | 未覆盖运行时错误分支 |
25
+ ```
26
+
27
+ ## 2. 判定口径
28
+
29
+ | 判定 | 含义 |
30
+ |---|---|
31
+ | `pass` | 有证据覆盖该规则,且没有相反证据 |
32
+ | `pass(静态)` | 只有静态检查通过;必须写清检查范围,不能替代人工抽样 |
33
+ | `warn` | 存在相反证据、覆盖不完整,或只有部分满足 |
34
+ | `fail` | 明确违反,且会造成安全、数据或契约风险;按 P0 处理 |
35
+ | `na` | 该规则不适用;必须写原因 |
36
+
37
+ 证据要求:
38
+
39
+ - 文件级:`path/to/file.ts:line`;不要只写目录。
40
+ - 命令级:写出命令与结果;计数必须带可复现的检索式。
41
+ - 禁止「看起来一致」「整体规范」这类无证据结论。
42
+ - 一个规则有多个子项时,逐项给证据;不能用一个子项代表全部。
43
+
44
+ ## 3. 静态检查边界
45
+
46
+ 内置检查是**抽样工具**,不是审计结论:
47
+
48
+ - **A17**:按三条线索识别生成类型:路径含 `external/` / `generated/`、文件头有只读声明(`本文件由…生成` / `勿手改` / `@generated`)、`boundaries.external` / `boundaries.generated` 配置。只解析相对路径与 `@/` `~/` `#/` 别名;解析不到或头部无标记时仍是盲区,必须人工检查。
49
+ - 生成的数据 / 资源模块(如图标表)不算类型契约,不触发 A17。
50
+ - 约定:生成 / 外部类型放在 `external/` 或 `generated/` 下;迁移前按人工检查,不能因 0 findings 判 `pass`。
51
+ - **A2 / A11**:只覆盖包结构、生成物标记等文本模式;没有类型图、没有运行时验证。
52
+ - **A21**:高置信 token 模式(私钥 / AWS / 阿里云 `LTAI` / GitHub / Slack / API key)+ 配置与 Java / Kotlin 源码中的明文强口令 / 密钥字段;跳过环境变量、占位符与测试目录。没有命中不等于不存在,必须写明扫描范围。
53
+ - **A4 / A5 / A8 / A12 / A13 / A19**:靠人工阅读,不做静态扫描。A4 需要语义判断;A5 需要状态可达性、A8 需要数据流分析,文本级扫描实测误报高;不能因为 CLI 0 findings 就给 `pass`。
54
+
55
+ 因此:
56
+
57
+ - 报告必须写「`codecraft check` 的结果与覆盖范围」。
58
+ - 用了 `--exclude` 时必须列出排除路径;否则计数不可复现。
59
+ - `0 findings` 只能写成「静态检查未命中」,不能写成「规则通过」。
60
+ - 审计结论的置信度分为 High / Medium / Low:
61
+ - High:静态 + 人工抽样 + 关键路径验证
62
+ - Medium:静态 + 人工抽样
63
+ - Low:仅静态检查
64
+
65
+ ## 4. A1–A21 判定矩阵
66
+
67
+ | ID | 判定方式 | `pass` 条件 | 常见误判 |
68
+ |---|---|---|---|
69
+ | A1 | 人工抽样(结构检索辅助) | 同族实例使用同一模板 / 插槽;抽样覆盖主要分支 | 只看到统一 Wrapper,忽略内部结构分叉 |
70
+ | A2 | 静态依赖 + 人工 | 无反向依赖、无跨层 import | 只看 core 的 import,漏掉传输层 import 状态 |
71
+ | A3 | 人工 | 传输层不解释业务 code、不承担 UI 反馈 | 401 收口一处就判通过 |
72
+ | A4 | 人工 + 计数 | 每种关注点只有一个收口;无散落的同类判断 | 认证 / 提示各一处,但业务码判断散落 30+ 处 |
73
+ | A5 | 静态 + 人工 | 非法状态不可表示;联合类型 / 穷尽分支 | 有类型但大量 `any` / 多布尔并存 |
74
+ | A6 | 人工 + 静态(空 catch) | 错误是值;无静默失败;调用方必须处理 | 成功元组里 err 恒为 `undefined`,业务失败仍走成功分支 |
75
+ | A7 | 人工 | 可枚举变化用表;加 case 只加一行 | 有表但仍有并行 if / switch |
76
+ | A8 | 人工 | 派生状态不落库 / 不重复存储 | 有 computed,同时把结果再存一份 |
77
+ | A9 | 人工 | 注释只写意图 / 契约 / 边界 / 反例 | 注释复述代码,或规范文档本身漂移 |
78
+ | A10 | 人工 + 配置 | 例外有理由 / 主人 / 到期;安全不可豁免 | 只写“历史原因”,没有到期 |
79
+ | A11 | 静态(标记)+ CI 比对 | 生成物有只读标记,且再生成 diff 为空 | 只有“勿手改”头,没有再生成比对 |
80
+ | A12 | 人工 | 复制有母版、版本、分叉点、升级路径 | 多处副本,未指明母版 |
81
+ | A13 | 人工 | 每一层都能一眼定位源头 | `utils/` 成为域名 / 传输 / 海报的混合桶 |
82
+ | A14 | 人工 | 抽象有真实消费方与触发条件 | 以“以后可能用”为由提前抽象 |
83
+ | A15 | 流程 / 输出检查 | 变更说明含改了什么 / 为什么 / 怎么验 / 风险 | 用 A15 去评价代码结构 |
84
+ | A16 | 人工 + 搜索 | 命名标层、可搜索、组合可读 | 单项目内一致,但跨端 / 跨团队歧义 |
85
+ | A17 | 静态(路径 / 文件头 / 配置)+ 人工 | 内部不 import 外部类型;外部契约在包装层转换 | 别名解析不到或头部无标记就判通过;把生成数据模块当成类型契约 |
86
+ | A18 | 人工 | 有档位;默认 L0;按触发升级 | 所有能力默认开启 |
87
+ | A19 | 人工 + 契约测试 | public contract 固定;有可替换性验证 | 边界口头清楚,但没有契约测试 |
88
+ | A20 | 人工 | 记录环节 / 职责 / 契约,不把库当层 | 用框架名代替架构层 |
89
+ | A21 | 静态扫描 + 人工 | 无密钥 / 内部路径外泄;交付白名单一致 | 模式扫描 0 命中就判全局通过;把运行时变量名当明文密钥 |
90
+
91
+ ## 5. 一致性检查
92
+
93
+ 出结论前,必须做一次交叉检查;发现矛盾就降级:
94
+
95
+ | 场景 | 要求 |
96
+ |---|---|
97
+ | A4 判 `pass`,但存在多处 `code === 200` / 重复错误处理 | 改为 `warn`;单一收口未成立 |
98
+ | A11 判 `pass`,但没有再生成比对 / CI diff | 最多 `warn`;只能写“生成物有只读标记” |
99
+ | A8 判 `pass`,但派生状态被落库 / 重复存储 | 改为 `warn`,或写明可接受理由与主人 |
100
+ | A21 判 `pass`,但只做了模式扫描 | 写 `pass(有限)` 或 `warn`;列扫描范围 |
101
+ | A17 判 `pass`,但存在生成类型直用 | 改为 `warn`;路径不在 `external/` 也算 |
102
+ | A12 判 `pass`,但同族存在多份副本 | 改为 `warn`;必须指明母版 |
103
+ | A3 判 `pass`,但传输层直接弹 Toast / 跳转 | 改为 `warn`;传输层不应承担 UI 反馈 |
104
+
105
+ ## 6. 优先级
106
+
107
+ | 级别 | 定义 | 例子 |
108
+ |---|---|---|
109
+ | P0 | 安全、数据丢失、不可回滚 | 密钥泄漏、越权、破坏性迁移 |
110
+ | P1 | 架构 / 契约 / 文档真源错误 | 分层失效、规范写错事实、门禁缺失 |
111
+ | P2 | 可维护性 / 重复实现 | 业务错误码散落、上传目录三份真源 |
112
+ | P3 | 测试、清理、体验 | 纯函数无单测、命名不统一 |
113
+
114
+ 同一份报告里,P1 不能多于结论总数的一半而不说明取舍;否则先合并根因。
115
+
116
+ ## 7. 计划表
117
+
118
+ ```md
119
+ | 阶段 | 内容 | 可回滚 | 验收 |
120
+ |---|---|---|---|
121
+ | 0 | 文档纠偏 | 纯文档,单 commit 可回退 | 描述与检索结果一致 |
122
+ | 1 | 门禁补齐 | 移除 config / hook 即恢复 | 故意引入类型错误会被拦 |
123
+ ```
124
+
125
+ 要求:
126
+
127
+ - 每阶段可独立回滚,不用“重来一遍”。
128
+ - 验收必须是可执行命令或可检索结果,不写“感觉完成”。
129
+ - 不写时间估算;写依赖与顺序。
130
+ - 重构阶段先补基线(typecheck / 单测 / 契约测试),再改行为。
131
+
132
+ ## 8. 交付前自检
133
+
134
+ - [ ] A1–A21 全部出现,或写明 `na`
135
+ - [ ] 每条 `pass` / `warn` 都有文件行号或命令
136
+ - [ ] 所有计数都能用文中命令复现
137
+ - [ ] 已做一致性检查,A4 / A8 / A11 / A17 / A21 没有被高估
138
+ - [ ] 已写明静态检查覆盖不到的部分
139
+ - [ ] 没有密钥、内部路径、客户隐私
140
+ - [ ] Audit 只读;未改代码、未起服务
141
+ - [ ] 计划每阶段可回滚、有验收
@@ -0,0 +1,110 @@
1
+ [
2
+ {
3
+ "name": "a17-default",
4
+ "root": "a17-default",
5
+ "args": ["--pack", "app", "--format", "json"],
6
+ "expect": { "exit": 0, "findings": { "A17": 1 } }
7
+ },
8
+ {
9
+ "name": "a17-boundaries",
10
+ "root": "a17-boundaries",
11
+ "args": ["--pack", "app", "--format", "json"],
12
+ "expect": { "exit": 0, "findings": { "A17": 1 } }
13
+ },
14
+ {
15
+ "name": "a6-empty-catch",
16
+ "root": "a6-empty-catch",
17
+ "args": ["--pack", "app", "--format", "json"],
18
+ "expect": { "exit": 0, "findings": { "A6": 1 } }
19
+ },
20
+ {
21
+ "name": "ignore-active",
22
+ "root": "ignore-active",
23
+ "args": ["--pack", "app", "--format", "json"],
24
+ "expect": { "exit": 0, "findings": {}, "ignored": 1 }
25
+ },
26
+ {
27
+ "name": "ignore-expired",
28
+ "root": "ignore-expired",
29
+ "args": ["--pack", "app", "--format", "json", "--ci"],
30
+ "expect": { "exit": 1, "findings": { "A17": 1 }, "expired": 1 }
31
+ },
32
+ {
33
+ "name": "library-a11",
34
+ "root": "library-a11",
35
+ "args": ["--pack", "library", "--format", "json"],
36
+ "expect": { "exit": 0, "findings": { "A11": 1 } }
37
+ },
38
+ {
39
+ "name": "zero-files",
40
+ "root": "zero-files",
41
+ "args": ["--pack", "library", "--format", "json"],
42
+ "expect": { "exit": 2, "findings": {}, "warnings": 1 }
43
+ },
44
+ {
45
+ "name": "a17-generated-header",
46
+ "root": "a17-generated-header",
47
+ "args": ["--pack", "app", "--format", "json"],
48
+ "expect": { "exit": 0, "findings": { "A17": 1 } }
49
+ },
50
+ {
51
+ "name": "a21-plaintext",
52
+ "root": "a21-plaintext",
53
+ "args": ["--pack", "app", "--format", "json"],
54
+ "expect": { "exit": 0, "findings": { "A21": 2 } }
55
+ },
56
+ {
57
+ "name": "a2-workspace",
58
+ "root": "a2-workspace",
59
+ "args": ["--pack", "library", "--format", "json"],
60
+ "expect": { "exit": 0, "findings": { "A2": 1 } }
61
+ },
62
+ {
63
+ "name": "a2-declared",
64
+ "root": "a2-declared",
65
+ "args": ["--pack", "library", "--format", "json"],
66
+ "expect": { "exit": 0, "findings": {} }
67
+ },
68
+ {
69
+ "name": "a6-clean",
70
+ "root": "a6-clean",
71
+ "args": ["--pack", "app", "--format", "json"],
72
+ "expect": { "exit": 0, "findings": {} }
73
+ },
74
+ {
75
+ "name": "a11-marker",
76
+ "root": "a11-marker",
77
+ "args": ["--pack", "library", "--format", "json"],
78
+ "expect": { "exit": 0, "findings": {} }
79
+ },
80
+ {
81
+ "name": "a17-local",
82
+ "root": "a17-local",
83
+ "args": ["--pack", "app", "--format", "json"],
84
+ "expect": { "exit": 0, "findings": {} }
85
+ },
86
+ {
87
+ "name": "a17-generated-data",
88
+ "root": "a17-generated-data",
89
+ "args": ["--pack", "app", "--format", "json"],
90
+ "expect": { "exit": 0, "findings": {} }
91
+ },
92
+ {
93
+ "name": "a21-placeholders",
94
+ "root": "a21-placeholders",
95
+ "args": ["--pack", "app", "--format", "json"],
96
+ "expect": { "exit": 0, "findings": {} }
97
+ },
98
+ {
99
+ "name": "a21-doc-paths",
100
+ "root": "a21-doc-paths",
101
+ "args": ["--pack", "design-system", "--format", "json"],
102
+ "expect": { "exit": 0, "findings": { "A21": 2 } }
103
+ },
104
+ {
105
+ "name": "sarif",
106
+ "root": "a17-default",
107
+ "args": ["--pack", "app", "--format", "sarif"],
108
+ "expect": { "exit": 0, "sarif": { "version": "2.1.0", "rule": "A17" } }
109
+ }
110
+ ]
@@ -0,0 +1,4 @@
1
+ /* 生成物 · 勿手改:由 core build 产出 */
2
+ :root {
3
+ --color-fg: #111;
4
+ }
@@ -0,0 +1 @@
1
+ { "name": "@x/core" }
@@ -0,0 +1 @@
1
+ export const version = '1.0.0'