@fantasticit/sumi 0.5.0 → 0.6.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 (29) hide show
  1. package/node_modules/@sumi/create/dist/bin.d.ts +2 -0
  2. package/node_modules/@sumi/create/dist/bin.js +52 -0
  3. package/node_modules/@sumi/create/dist/bin.js.map +1 -0
  4. package/node_modules/@sumi/create/package.json +1 -1
  5. package/node_modules/@sumi/kernel/dist/scope.d.ts +2 -0
  6. package/node_modules/@sumi/kernel/dist/scope.js +5 -1
  7. package/node_modules/@sumi/kernel/dist/scope.js.map +1 -1
  8. package/node_modules/@sumi/kernel/package.json +2 -2
  9. package/node_modules/@sumi/plugin-sdk/package.json +1 -1
  10. package/node_modules/@sumi/plugins-core/README.md +107 -15
  11. package/node_modules/@sumi/plugins-core/dist/plugins/test-affected.js +392 -45
  12. package/node_modules/@sumi/plugins-core/dist/plugins/test-affected.js.map +1 -1
  13. package/node_modules/@sumi/plugins-core/dist/test-scope.d.ts +96 -0
  14. package/node_modules/@sumi/plugins-core/dist/test-scope.js +228 -0
  15. package/node_modules/@sumi/plugins-core/dist/test-scope.js.map +1 -0
  16. package/node_modules/@sumi/plugins-core/dist/vitest-runner.d.ts +1 -0
  17. package/node_modules/@sumi/plugins-core/dist/vitest-runner.js +126 -0
  18. package/node_modules/@sumi/plugins-core/dist/vitest-runner.js.map +1 -0
  19. package/node_modules/@sumi/plugins-core/package.json +2 -2
  20. package/node_modules/@sumi/plugins-governance/dist/commands/gate.js +10 -0
  21. package/node_modules/@sumi/plugins-governance/dist/commands/gate.js.map +1 -1
  22. package/node_modules/@sumi/plugins-governance/dist/hooks.d.ts +2 -0
  23. package/node_modules/@sumi/plugins-governance/dist/hooks.js +4 -0
  24. package/node_modules/@sumi/plugins-governance/dist/hooks.js.map +1 -0
  25. package/node_modules/@sumi/plugins-governance/package.json +2 -2
  26. package/node_modules/@sumi/plugins-openspec/package.json +2 -2
  27. package/node_modules/@sumi/plugins-precedent/package.json +3 -3
  28. package/node_modules/@sumi/plugins-review/package.json +3 -3
  29. package/package.json +10 -10
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync, spawnSync } from 'node:child_process';
3
+ import { existsSync, symlinkSync } from 'node:fs';
4
+ import { join, resolve } from 'node:path';
5
+ import { scaffold } from './scaffold.js';
6
+ /**
7
+ * create-ai-coding <目录> [--agents claude,codex,cursor] [--link <node_modules 路径>] [--no-install]
8
+ * 创建遵循三层结构的新项目:复制模板、初始化 git、安装依赖、生成 AI 工具适配与 git hook。
9
+ */
10
+ const args = process.argv.slice(2);
11
+ const flag = (name) => {
12
+ const i = args.indexOf(`--${name}`);
13
+ return i >= 0 ? args[i + 1] : undefined;
14
+ };
15
+ const target = args.find((a, i) => !a.startsWith('--') && !['--agents', '--link'].includes(args[i - 1] ?? ''));
16
+ if (!target) {
17
+ process.stderr.write('用法:create-ai-coding <目录> [--agents claude,codex,cursor] [--link <node_modules>] [--no-install]\n');
18
+ process.exit(3);
19
+ }
20
+ const dir = resolve(target);
21
+ try {
22
+ scaffold(dir, {
23
+ agents: flag('agents')
24
+ ?.split(',')
25
+ .map((a) => a.trim())
26
+ .filter(Boolean),
27
+ });
28
+ }
29
+ catch (error) {
30
+ process.stderr.write(`${error.message}\n`);
31
+ process.exit(1);
32
+ }
33
+ execFileSync('git', ['init', '-q', '-b', 'main'], { cwd: dir });
34
+ const link = flag('link');
35
+ if (link)
36
+ symlinkSync(resolve(link), join(dir, 'node_modules'));
37
+ else if (!args.includes('--no-install')) {
38
+ const r = spawnSync('pnpm', ['install'], { cwd: dir, stdio: 'inherit' });
39
+ if (r.status !== 0)
40
+ process.stderr.write('依赖安装失败,请稍后在项目中手动运行 pnpm install\n');
41
+ }
42
+ const ctl = join(dir, 'node_modules', '.bin', 'ctl');
43
+ if (existsSync(ctl))
44
+ spawnSync(ctl, ['sync-agents'], { cwd: dir, stdio: 'inherit' });
45
+ process.stdout.write([
46
+ `已创建 ${dir}`,
47
+ '下一步:',
48
+ ' npx ctl run check --all # 新项目应直接通过',
49
+ ' 首次推送时,门禁会要求确认全部 control 内容:由人在自己的终端运行它给出的 npx ctl approve <请求 id>',
50
+ '',
51
+ ].join('\n'));
52
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;GAGG;AACH,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,EAAE;IAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1C,CAAC,CAAC;AACF,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC/G,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kGAAkG,CAAC,CAAC;IACzH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AACD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC5B,IAAI,CAAC;IACH,QAAQ,CAAC,GAAG,EAAE;QACZ,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;YACpB,EAAE,KAAK,CAAC,GAAG,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC;KACnB,CAAC,CAAC;AACL,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,KAAe,CAAC,OAAO,IAAI,CAAC,CAAC;IACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AACD,YAAY,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAChE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;AAC1B,IAAI,IAAI;IAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;KAC3D,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;IACxC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;AAChF,CAAC;AACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACrD,IAAI,UAAU,CAAC,GAAG,CAAC;IAAE,SAAS,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AACrF,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB;IACE,OAAO,GAAG,EAAE;IACZ,MAAM;IACN,wCAAwC;IACxC,qEAAqE;IACrE,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sumi/create",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Sumi 脚手架与项目模板(由 sumi init 调用)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -10,6 +10,8 @@ export interface BaseInfo {
10
10
  /**
11
11
  * 确定基准:显式参数或配置的 ref 必须存在;否则取与上游的合并基础;
12
12
  * 没有上游时取 HEAD;连提交都没有时取空树。
13
+ * 显式参数原样使用(调用方给出的就是算好的基准);配置的 ref 是分支的比较目标,
14
+ * 取它与 HEAD 的合并基础,目标分支前进后未 rebase 的分支不会把目标上的新提交算作改动。
13
15
  */
14
16
  export declare function resolveBase(root: string, config: SumiConfig, override?: string): BaseInfo;
15
17
  /** 工作区中纳入摘要与检查的文件:已跟踪且存在的文件 + 未跟踪且未被忽略的文件,排除运行目录。 */
@@ -31,6 +31,8 @@ export function assertGitRepo(root) {
31
31
  /**
32
32
  * 确定基准:显式参数或配置的 ref 必须存在;否则取与上游的合并基础;
33
33
  * 没有上游时取 HEAD;连提交都没有时取空树。
34
+ * 显式参数原样使用(调用方给出的就是算好的基准);配置的 ref 是分支的比较目标,
35
+ * 取它与 HEAD 的合并基础,目标分支前进后未 rebase 的分支不会把目标上的新提交算作改动。
34
36
  */
35
37
  export function resolveBase(root, config, override) {
36
38
  const ref = override ?? config.base;
@@ -38,7 +40,9 @@ export function resolveBase(root, config, override) {
38
40
  const oid = tryGit(root, ['rev-parse', '--verify', '--quiet', `${ref}^{commit}`]);
39
41
  if (!oid)
40
42
  throw new KernelError(`基准 ${ref} 不存在。可用 --base <ref> 或在项目配置中设置 base`);
41
- return { oid };
43
+ if (override)
44
+ return { oid };
45
+ return { oid: tryGit(root, ['merge-base', 'HEAD', oid]) ?? oid };
42
46
  }
43
47
  const head = tryGit(root, ['rev-parse', '--verify', '--quiet', 'HEAD']);
44
48
  if (!head)
@@ -1 +1 @@
1
- {"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sumi/kernel",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "策略中立的编排内核",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -13,7 +13,7 @@
13
13
  "./package.json": "./package.json"
14
14
  },
15
15
  "dependencies": {
16
- "@sumi/plugin-sdk": "0.5.0",
16
+ "@sumi/plugin-sdk": "0.6.0",
17
17
  "yaml": "2.9.1",
18
18
  "picomatch": "4.0.7"
19
19
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sumi/plugin-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "插件协议类型与 SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -2,37 +2,129 @@
2
2
 
3
3
  通用检查插件包:格式、lint、类型检查、受影响的测试、覆盖率、层边界、control 文档执行者检查、AI 工具适配漂移、指标棘轮,以及包装已有脚本的 `core/exec`;另注册纳管命令 `adopt` 与基线命令 `baseline`。
4
4
 
5
- 插件不自带工具。prettier、eslint、tsc、vitest、c8 由项目安装,插件按下面的顺序查找:先找步骤 `with.binDir` 指定的目录,再从仓库根向上找 `node_modules/.bin`。找不到工具时步骤结论为 `skipped`,并提示安装。修复命令只从当前目录向上查找 `node_modules/.bin`,不读 `binDir`。
5
+ 插件不自带工具。prettier、eslint、tsc、vitest、c8 由项目安装,插件按下面的顺序查找:先找步骤 `with.binDir` 指定的目录,再从仓库根向上找 `node_modules/.bin`(core/test-affected 例外:从项目目录解析 `vitest/node`,不读 `binDir`)。找不到工具时步骤结论为 `skipped`,并提示安装(core/test-affected 只在单仓模式下如此,见下文)。清单中的 `needs` 是声明性的,说明插件依赖的工具,内核不据此检查。修复命令只从当前目录向上查找 `node_modules/.bin`,不读 `binDir`。
6
6
 
7
7
  ## 插件
8
8
 
9
9
  所有插件的 kind 都是 `check`,清单(`sumi-plugins.yaml`)中都没有声明 `triggers`。除 `core/coverage` 外也都没有声明 `minTier`。
10
10
 
11
- | id | 作用 | kind | 档位 | `with` 配置项 | 指标 | needs | fix |
12
- | --------------------- | -------------------------------------------------------------------------- | ----- | ------------------ | ---------------------------------------------------- | ---------------------------------------- | ------------------------------ | ------------------ |
13
- | `core/format` | `prettier --list-different` 只读检查 | check | — | `binDir` | — | bin: prettier | `prettier --write` |
14
- | `core/lint` | ESLint(项目配置);error 为 finding,warning 计入指标 | check | — | `binDir` | `warnings`(lower-is-better) | bin: eslint | `eslint --fix` |
15
- | `core/typecheck` | 对各工程运行 `tsc --noEmit`,始终全量 | check | — | `binDir`、`projects`(默认 `[tsconfig.json]`) | — | bin: tsc;files: tsconfig.json | — |
16
- | `core/test-affected` | 改动范围用 `vitest related`,全量用 `vitest run`;为注入的测试义务逐项回执 | check | — | `binDir` | — | bin: vitest | — |
17
- | `core/coverage` | 全量运行测试,上报行覆盖率 | check | `minTier: runtime` | `binDir`、`include`、`exclude`、`tool`、`subprocess` | `coverage`(higher-is-better,容差 0.1) | bin: vitest | — |
18
- | `core/layer-boundary` | 每个文件归属某个区域或中立区;business 不得导入 control/precedent | check | — | — | — | — | — |
19
- | `core/control-docs` | 入口文档限长;规范性语句必须引用存在的执行者 | check | — | `maxLines`、`keywords`、`paths`、`exclude` | `exemptions`(lower-is-better) | — | — |
20
- | `core/exec` | 运行已有命令,按退出码与输出给出结果 | check | — | `argv`、`passFiles`、`pattern` | — | — | — |
21
- | `core/agent-drift` | 调用 `sumi update --check --json`,报告 AI 工具适配与 hook 的漂移 | check | — | — | — | — | — |
22
- | `core/ratchet` | 本次运行的指标与基线比较,不得变差 | check | — | `budgets` | — | — | — |
11
+ | id | 作用 | kind | 档位 | `with` 配置项 | 指标 | needs | fix |
12
+ | --------------------- | -------------------------------------------------------------------------------------------------------------------- | ----- | ------------------ | ----------------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------ | ------------------ |
13
+ | `core/format` | `prettier --list-different` 只读检查 | check | — | `binDir` | — | bin: prettier | `prettier --write` |
14
+ | `core/lint` | ESLint(项目配置);error 为 finding,warning 计入指标 | check | — | `binDir` | `warnings`(lower-is-better) | bin: eslint | `eslint --fix` |
15
+ | `core/typecheck` | 对各工程运行 `tsc --noEmit`,始终全量 | check | — | `binDir`、`projects`(默认 `[tsconfig.json]`) | — | bin: tsc;files: tsconfig.json | — |
16
+ | `core/test-affected` | 经 vitest Node API 只运行与改动相关的测试,追不到的改动全部运行;可按 workspace 包逐包选择;为注入的测试义务逐项回执 | check | — | `ignore`、`workspaces`、`wholePackages`、`sourceGuards`、`rootTest`、`attribute`、`noPropagate` | — | bin: vitest | — |
17
+ | `core/coverage` | 全量运行测试,上报行覆盖率 | check | `minTier: runtime` | `binDir`、`include`、`exclude`、`tool`、`subprocess` | `coverage`(higher-is-better,容差 0.1) | bin: vitest | — |
18
+ | `core/layer-boundary` | 每个文件归属某个区域或中立区;business 不得导入 control/precedent | check | — | — | — | — | — |
19
+ | `core/control-docs` | 入口文档限长;规范性语句必须引用存在的执行者 | check | — | `maxLines`、`keywords`、`paths`、`exclude` | `exemptions`(lower-is-better) | — | — |
20
+ | `core/exec` | 运行已有命令,按退出码与输出给出结果 | check | — | `argv`、`passFiles`、`pattern` | — | — | — |
21
+ | `core/agent-drift` | 调用 `sumi update --check --json`,报告 AI 工具适配与 hook 的漂移 | check | — | — | — | — | — |
22
+ | `core/ratchet` | 本次运行的指标与基线比较,不得变差 | check | — | `budgets` | — | — | — |
23
23
 
24
24
  修复命令由 `sumi fix <step-id>` 执行,参数是该步骤检查过的文件;没有文件时处理整个仓库(`.`)。
25
25
 
26
26
  ### 各插件细节
27
27
 
28
28
  - **core/format、core/lint**:只检查内核给出的文件列表(全量时为全仓减去排除路径),不让工具自己扫描。lint 只看 JS/TS 扩展名的文件;eslint 9 及以上加 `--no-warn-ignored`。改动范围运行时,lint 用 `git show <base>:<文件>` 取出基准版本,按"规则 + 消息"统计告警的**新增量**(`added`)。全量运行时只上报绝对值。
29
- - **长文件列表**:core/format、core/lint 及其修复命令会按保守的跨平台命令长度预算分批调用项目工具。lint 合并每批 JSON 报告,format 合并每批不合规文件;任何一批无法启动、输出不可解析或单个参数超限时,整体不会报告成功。`core/exec passFiles` 包装的是任意项目命令,Sumi 无法推断它能否安全重复执行及如何合并输出,因此不会自动分批:Windows 上命令行超出 CreateProcess 上限,或超出 cmd.exe 上限且命令非零退出时,步骤为 `blocked` 并说明原因,需要处理超长列表时,由该命令通过 `SUMI_BASE` 自行计算范围或使用项目工具支持的响应文件机制。core/test-affected 与 `sumi fix` 运行的是同一个测试工具或修复命令,按同一预算分批,合并各批结果。
29
+ - **长文件列表**:core/format、core/lint 及其修复命令会按保守的跨平台命令长度预算分批调用项目工具。lint 合并每批 JSON 报告,format 合并每批不合规文件;任何一批无法启动、输出不可解析或单个参数超限时,整体不会报告成功。`core/exec passFiles` 包装的是任意项目命令,Sumi 无法推断它能否安全重复执行及如何合并输出,因此不会自动分批:Windows 上命令行超出 CreateProcess 上限,或超出 cmd.exe 上限且命令非零退出时,步骤为 `blocked` 并说明原因,需要处理超长列表时,由该命令通过 `SUMI_BASE` 自行计算范围或使用项目工具支持的响应文件机制。`sumi fix` 运行的修复命令按同一预算分批。core/test-affected 不经命令行传文件,见下文。
30
30
  - **core/typecheck**:解析 `文件(行,列): error TSxxxx: 消息` 形式的输出。tsc 退出码非 0 但没有解析出错误时,结论为 `blocked`。
31
- - **core/test-affected**:规划器注入的具名测试义务(`target.file`、`target.name`)按实际执行结果回执,取值为 `passed`、`failed`、`skipped`、`not-executed` 之一。被跳过、待办或未执行都不算 passed。
31
+ - **core/test-affected**:选择范围见下文。规划器注入的具名测试义务(`target.file`、`target.name`)按实际执行结果回执,取值为 `passed`、`failed`、`skipped`、`not-executed` 之一。被跳过、待办或未执行都不算 passed。只有经运行器执行的测试才有逐条结果;以 `<包管理器> run test` 运行的包(workspace 模式下 `test` 脚本不是 `vitest run`)没有逐条结果,目标在这些包中的义务回执为 `not-executed`。
32
32
  - **core/coverage**:默认用 vitest 的 v8 覆盖率(需要项目安装 `@vitest/coverage-v8`,否则结论为 `skipped`)。`tool: c8` 时还会用 `NODE_V8_COVERAGE` 收集子进程中执行的代码:`subprocess` 指定要统计的构建产物 glob,经 c8 映射回源码后,与测试进程内的覆盖按行取并集。`include` / `exclude` 限定统计范围。
33
33
  - **core/layer-boundary**:从项目配置读取 `zones`、`neutral`,检查三类问题:未归属任何区域的文件(`unowned-file`);business 区用相对路径导入 control 区或 precedent 区的模块(`business-imports-control`);control 区或 precedent 区中被 `.gitignore` 忽略的文件(`ignored-control-file`,`node_modules` 除外)。
34
34
  - **core/control-docs**:默认扫描 `AGENTS.md` 与 `control/**/*.md`,`AGENTS.md` 的上限默认为 100 行。默认关键词为 `MUST`、`SHALL`、`必须`、`禁止`、`不得`。代码块、引用行和空行不扫描。带 `[non-normative]` 的行不扫描,并计入豁免指标;被 `with.exclude` 排除的文件数也计入豁免指标。插件认四类执行者引用:`[plugin:<id>]`(本次运行加载的插件)、`[step:<id>]`(`control/flows/*.flow.yaml` 中的步骤 id)、`[prec:<id>]`(`precedents/registry.yaml`)、`[rubric:<集合>#<条目>]`(`control/rubrics/<集合>.yaml`)。规范性语句没有引用时报 `no-enforcer`,引用的目标不存在时报 `broken-reference`。这项检查只证明规则声明了执行者,不证明执行者在语义上正确。
35
35
 
36
+ ## core/test-affected:受影响的测试
37
+
38
+ 插件以子进程(当前 Node)在项目目录启动包内的运行器 `dist/vitest-runner.js`,运行器从项目解析 `vitest/node`,用 Node API 求出相关测试后运行,等同 `vitest related --run`(全部运行时等同 `vitest run`),并与 vitest CLI 一样设置 `NODE_ENV`(未设置时为 `test`)、`TEST=true`、`VITEST=true`。改动文件、报告与选中数都经证据目录中的文件传递(第一次运行为 `vitest.input.json`、`vitest.json`、`vitest.result.json`,之后的运行加序号 `vitest-<n>.*`,日志为 `vitest.log`),不经命令行,不受 Windows 命令行长度限制,也不会把同一个测试运行多次。
39
+
40
+ 运行器要求项目的 vitest 不低于 3.0(`getRelevantTestSpecifications` 自 3.0 起提供);缺少 `createVitest` 或 `getRelevantTestSpecifications` 时结论为 `blocked`,summary 提示所需版本。单仓模式下从仓库根解析不到 vitest 时结论为 `skipped`;workspace 模式不会因此 `skipped`,解析不到 vitest 的包改为以包管理器运行 `test` 脚本。运行器异常退出(退出码不是 0、1 或回退用的 3)或没有产出报告时结论为 `blocked`。
41
+
42
+ vitest related 只沿 import 图追踪。以下改动它追不到或不会整体重跑,插件改为全部运行,并在 summary 中写明原因:
43
+
44
+ - 配置文件:`package.json`、`tsconfig*.json`、`vite.config.*`、`vitest.config.*`(含带后缀的变体)、`vitest.workspace.*`、`vitest.projects.*`;运行器还会读出 vitest(及各 project)实际使用的配置文件及其导入的文件(vite 的 `configFileDependencies`)、`setupFiles` 与 `globalSetup` 及它们导入的本地文件,改动命中时同样全部运行。Windows 上这些路径按大小写不敏感比较。
45
+ - 删除的文件:内核的文件列表只含存在的文件,插件用 `git diff --diff-filter=D` 相对基准自行计算。
46
+ - 非 JS/TS 文件(`?raw`、fs 读取的数据文件等)。被 `with.ignore` 匹配的文件不计入,默认 `['**/*.md']`:测试以 fs 或 `?raw` 读取 `.md` fixture 时,这些 fixture 的改动不会触发任何测试,应配置 `ignore` 只忽略文档(如 `['*.md', 'docs/**']`),不匹配 fixture。
47
+
48
+ 运行器无法求出相关测试(例如某个测试文件无法解析)时回退为全部运行。测试失败生成 `test-failed` finding;测试文件本身加载失败时按文件报告。
49
+
50
+ | 配置项 | 作用 |
51
+ | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
+ | `ignore` | 不影响测试的文件 glob(相对仓库根),默认 `['**/*.md']`;给出时替换默认值。workspace 模式可写成 `{ default: [...], packages: { 包名: [...] } }` 按包覆盖(见下) |
53
+ | `workspaces` | 为 `true` 时按 workspace 包逐包选择(见下);默认关闭,不自动检测 |
54
+ | `wholePackages` | workspace 模式:只要成为候选就整包运行的包,包名列表,或 `{ 包名: 原因 }`(原因写入 summary) |
55
+ | `sourceGuards` | workspace 模式:`{ 包名: [相对包目录的测试路径] }`,本包有源码改动时追加到 related 输入,用于以 fs 或 `?raw` 读取源码做断言、import 图追不到的守卫测试 |
56
+ | `rootTest` | workspace 模式:为 `false` 时根 `test` 脚本不参与(根 test 只是 `pnpm -r run test` 之类的汇总时);默认 `true` |
57
+ | `attribute` | workspace 模式:把包外改动归属到包的项目命令 argv(数组,工作目录为仓库根),协议见下 |
58
+ | `noPropagate` | workspace 模式:包名列表,这些包的改动不带出下游候选(只用于不被下游运行时引用的包,如只被 lint 使用的 eslint 插件包),自身仍按规则判定 |
59
+
60
+ ### workspace 模式
61
+
62
+ 包从 `pnpm-workspace.yaml` 的 `packages` 读出,没有该文件时读 `package.json` 的 `workspaces`(数组或 `packages` 字段)。只支持 `dir` 与 `dir/*` 两种写法;含 `**`、`!` 等其他写法,或一个包也没有匹配到(如 `pnpm-workspace.yaml` 没有 `packages`)时,回退为在仓库根整体运行根 `test` 脚本(根 `package.json` 不存在或没有 `test` 脚本时为 `blocked`)。包之间的依赖取各包 `package.json` 中 `dependencies`、`devDependencies`、`peerDependencies`、`optionalDependencies` 里的 workspace 包名。
63
+
64
+ 1. 改动按路径归属到包(嵌套时取最深的包)。有相关改动不属于任何包(如根配置、锁文件、根目录下的源码与测试)且未经 `attribute` 归属时,每个有 `test` 脚本的包整包运行,根 `package.json` 有 `test` 脚本时也整体运行一次根 `test` 脚本(全量运行时同样如此);根没有 `test` 脚本时 summary 注明包外改动未运行根测试。框架不分析锁文件,需要更细的归属由项目经 `attribute` 提供(见下文扩展点)。
65
+ 2. 候选包为有改动的包及其传递下游(广度遍历,环依赖安全)。
66
+ 3. 每个候选包依次判定:没有 `test` 脚本 → 跳过;`test` 脚本不是 `vitest run` → 整包;在 `wholePackages` 中 → 整包;本包有配置、删除或非 JS/TS 改动 → 整包;上游有此类改动 → 整包;否则在包目录运行 related,输入为本包与上游改动文件的绝对路径,本包有源码改动时追加 `sourceGuards`。仅作为下游且 related 没有选中测试时记为跳过。
67
+ 4. 整包运行:`test` 脚本是 `vitest run` 时由运行器在包目录全部运行(保留逐条测试结果);否则以项目包管理器(`packageManager` 字段,其次按锁文件判断,默认 npm)在包目录运行 `<包管理器> run test`,失败时生成一条定位到该包 `package.json` 的 finding。
68
+ 5. 仓库根的测试(根 `package.json` 有 `test` 脚本、只有包内改动时):根 `test` 脚本是 `vitest run` 时,在仓库根以全部包内改动文件运行一次 related,覆盖“根 vitest 配置用 `projects`/`include` 扫描子包、子包不写 `test` 脚本”的写法与引用包源码的根级测试(如 `tests/*.test.ts`);包内改动含配置、删除或非 JS/TS 文件时改为整体运行根 `test` 脚本;根 related 没有选中测试不算失败。根 `test` 脚本不是 `vitest run`(带参数、多份配置、`pnpm -r test` 等)时无法按文件选择,整体运行根 `test` 脚本。根测试按其本身语义运行:它若也覆盖子包(如 `pnpm -r test`,或根 vitest 配置扫描子包测试),这些测试会与子包的运行重复,宁可多跑。
69
+
70
+ ### workspace 模式的扩展点
71
+
72
+ 以下配置让项目注入自己的事实与归属规则,未配置时行为与上文一致。
73
+
74
+ - **`rootTest: false`**:根 `test` 脚本任何情况下都不运行。包外改动由 `attribute` 归属,未配置 `attribute` 时全部包整包运行。读不出包(不支持的写法、没有匹配到任何包)时结论为 `blocked`,不回退根测试。只改了没有 `test` 脚本的包时,这些改动不再由根测试兜底。
75
+ - **`attribute`**:存在不属于任何包的相关改动(被 `ignore` 匹配的除外)且不是全量运行时,在仓库根运行该命令。命令的输入与输出记入证据 `attribute.log`。返回的包按配置改动对待:整包运行,并带动其下游整包;没有返回的包不因包外改动运行。根 `test` 仍按 `rootTest` 整体运行一次(包外改动可能影响根自己的测试)。
76
+ - stdin:`{ "repoRoot": "/abs/repo", "base": "<基准提交或 null>", "files": [{ "path": "pnpm-lock.yaml", "deleted": false }, { "path": "patches/old.patch", "deleted": true }], "packages": [{ "name": "@app/ui", "dir": "packages/ui", "manifest": "packages/ui/package.json" }] }`。`files` 为包外改动,`path` 相对仓库根,删除的文件 `deleted` 为 `true`(此时工作区中已没有该文件,需要内容时用 `git show <base>:<path>`);`dir`、`manifest` 相对仓库根。
77
+ - stdout:`{ "packages": ["@app/ui"], "reasons": ["patches/foo.patch 修补 foo,被 @app/ui 依赖"] }`,`reasons` 写入 summary。无法归属时返回 `{ "packages": [], "reasons": ["锁文件结构变化"], "all": true }`,全部运行。返回空的 `packages` 表示这些改动不影响任何包,summary 写为“包外改动不影响任何包(reasons)”。
78
+ - fail-closed:命令无法启动、超时(120 秒)、非零退出、输出不是 JSON 或格式不符、返回未知包名,或配置不是非空命令数组时,全部运行并在 summary 说明原因。
79
+ - argv 应直接运行脚本,如 `[node, control/scripts/attribute-outside.mjs]`;不要经 `pnpm exec`、`npx`、`sh -c` 等间接启动:超时只能终止直接启动的进程,间接启动时孙进程可能继续运行并拖住步骤。
80
+ - **`noPropagate`**:这些包的改动(含被归属的包外改动)不带出下游候选,也不计入其他候选包的上游改动。只用于不被下游运行时引用的包(如只被 lint 使用的 eslint 插件):它的 `package.json` 改动(依赖、导出变化)同样不会带出下游,被下游 import 的包不应列入。
81
+ - **`ignore` 按包覆盖**:`{ default: ['**/*.md'], packages: { '@app/docs': [] } }`。`default` 相对仓库根,省略时为 `['**/*.md']`;`packages` 中的包对其包内文件以该列表替换 `default`,glob 相对包目录。上例中 `@app/docs` 的 `.md` 改动按非 JS/TS 改动整包运行,其他包的 `.md` 仍被忽略。单仓模式只使用 `default`,配置了 `packages` 时 summary 提示其被忽略。
82
+ - **配置校验**:`ignore` 写错(不是字符串数组或 `{ default, packages }` 对象、`default` 或 `packages` 的值不是字符串数组、含其他键、`packages` 的包名不存在于 workspace),或 `sourceGuards` 的值不是字符串数组时,结论为 `blocked` 并在 summary 指明非法项,不会丢弃非法项或退回默认忽略(那样可能漏测)。`wholePackages`、`sourceGuards`、`noPropagate` 写了不存在的包名,或 `sourceGuards` 的路径不存在时,只在 summary 中以“配置提示”给出(只会多跑或无影响,不阻塞)。
83
+
84
+ 不提供整包运行的并发配置:各包按顺序运行,vitest 自身已并行执行测试文件;需要控制并发时在包的 `test` 脚本内设置。
85
+
86
+ 各包的模式与原因写入 summary 与证据 `modes.json`,所有包的结果汇总为一个步骤结果,具名测试义务按全部报告回执。
87
+
88
+ related 只沿源码的 import 图追踪。下游经 `main`、`exports` 指向的构建产物(如 `dist/`)消费上游时,上游源码改动追不到下游的测试,应把这类下游列入 `wholePackages`。
89
+
90
+ ```yaml
91
+ - use: core/test-affected
92
+ with:
93
+ workspaces: true
94
+ wholePackages: { '@app/cli': globalSetup 先构建产物 }
95
+ sourceGuards: { '@app/sdk': [test/source-guards.test.ts] }
96
+ ```
97
+
98
+ 大型 monorepo 的写法示例(根 `test` 为 `pnpm -r run test`):
99
+
100
+ ```yaml
101
+ - use: core/test-affected
102
+ with:
103
+ workspaces: true
104
+ rootTest: false
105
+ attribute: [node, control/scripts/attribute-outside.mjs]
106
+ noPropagate: ['@app/eslint-plugin']
107
+ ignore: { packages: { '@app/docs': [] } }
108
+ ```
109
+
110
+ 归属命令示例(按根 `package.json` 的改动粗略归属,其余改动无法归属):
111
+
112
+ ```js
113
+ // control/scripts/attribute-outside.mjs
114
+ let input = '';
115
+ process.stdin
116
+ .on('data', (d) => (input += d))
117
+ .on('end', () => {
118
+ const { files, packages } = JSON.parse(input);
119
+ if (files.every((f) => f.path === 'package.json' && !f.deleted)) {
120
+ const ui = packages.find((p) => p.name === '@app/ui');
121
+ process.stdout.write(JSON.stringify({ packages: ui ? [ui.name] : [], reasons: ['根 package.json 只影响 @app/ui'] }));
122
+ } else {
123
+ process.stdout.write(JSON.stringify({ packages: [], reasons: [`无法归属 ${files.map((f) => f.path).join('、')}`], all: true }));
124
+ }
125
+ });
126
+ ```
127
+
36
128
  ## core/exec:包装已有脚本
37
129
 
38
130
  `core/exec` 运行 `with.argv` 给出的命令,工作目录为仓库根。退出码为 0 时结论为 `pass`,非 0 为 `fail`,命令无法启动时为 `blocked`。完整输出写入证据 `output.log`。