@godv61/dsh-task-engine 0.23.0 → 0.23.2

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 (53) hide show
  1. package/.p0-test.mjs +739 -734
  2. package/.workflow-test.mjs +290 -0
  3. package/README.md +77 -181
  4. package/defaults/eng.json +10 -10
  5. package/docs/CHANGELOG.md +192 -0
  6. package/docs/README.md +29 -0
  7. package/docs/assets/workflow-banner.svg +29 -0
  8. package/docs/configuration.md +49 -0
  9. package/docs/development.md +53 -0
  10. package/docs/faq.md +47 -0
  11. package/docs/getting-started.md +51 -0
  12. package/docs/manual.html +18 -11
  13. package/docs/release-0.23.0.md +3 -5
  14. package/docs/release-0.23.1.md +58 -0
  15. package/docs/release-0.23.2.md +21 -0
  16. package/docs/resource-install.md +55 -11
  17. package/docs/roadmap.md +33 -0
  18. package/docs/testing/0.23.1//346/265/213/350/257/225/346/212/245/345/221/212.md +34 -0
  19. package/docs/testing/0.23.1//350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/346/230/216/347/273/206.md +41 -0
  20. package/docs/testing/0.23.2/R02/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +56 -0
  21. package/docs/testing/0.23.2/R03/344/270/232/345/212/241/346/265/213/350/257/225/346/230/216/347/273/206.md +38 -0
  22. package/docs/testing/0.23.2//346/265/213/350/257/225/346/212/245/345/221/212.md +65 -0
  23. package/docs/testing/0.23.2//350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/346/230/216/347/273/206.md +43 -0
  24. package/docs/workflow-regression.md +36 -0
  25. package/hooks/commit-msg +4 -4
  26. package/lib/client.js +7 -6
  27. package/lib/client.js.map +2 -2
  28. package/lib/controller.js +5 -15
  29. package/lib/controller.js.map +1 -1
  30. package/lib/custom-flow.d.ts +212 -0
  31. package/lib/custom-flow.js +50 -0
  32. package/lib/custom-flow.js.map +1 -0
  33. package/lib/dev-task.js +202 -40
  34. package/lib/dev-task.js.map +1 -1
  35. package/lib/engine.d.ts +17 -1
  36. package/lib/engine.js +5 -0
  37. package/lib/engine.js.map +1 -1
  38. package/lib/shipped-skills.js +2 -1
  39. package/lib/shipped-skills.js.map +1 -1
  40. package/lib/skill-audit.d.ts +16 -0
  41. package/lib/skill-audit.js +60 -0
  42. package/lib/skill-audit.js.map +1 -0
  43. package/lib/workflows.js +4 -4
  44. package/lib/workflows.js.map +1 -1
  45. package/package.json +4 -3
  46. package/rules/commit-conventions.md +2 -2
  47. package/skills/code-commit/SKILL.md +13 -13
  48. package/skills/code-implement/SKILL.md +24 -23
  49. package/skills/code-review/SKILL.md +13 -13
  50. package/skills/code-verify/SKILL.md +19 -12
  51. package/skills/eng-delivery/SKILL.md +38 -34
  52. package/skills/requirement-analysis/SKILL.md +16 -16
  53. package/skills/solution-design/SKILL.md +19 -16
@@ -0,0 +1,41 @@
1
+ # 0.23.1 自动化测试明细
2
+
3
+ 执行日期:2026-09-16。命令:`node --test --test-reporter=tap .resource-test.mjs .workflow-test.mjs`。
4
+
5
+ 结果:33项全部通过(资源18项、流程15项),失败0、跳过0。以下耗时来自该次TAP日志,单位毫秒。P0的126项逐条断言另由安装包黑盒运行并通过,不合并计算为本表用例。
6
+
7
+ | 序号 | 用例 | 状态 | 耗时(ms) | 失败原因 |
8
+ | --- | --- | --- | ---: | --- |
9
+ | 1 | preview has no filesystem side effects and reports exact bytes | 通过 | 14.1514 | — |
10
+ | 2 | confirmed install preserves binary assets and refuses duplicates | 通过 | 10.1495 | — |
11
+ | 3 | changed content and changed installation target invalidate preview | 通过 | 3.697 | — |
12
+ | 4 | path traversal, Windows ADS and reserved names are rejected | 通过 | 1.2775 | — |
13
+ | 5 | case-colliding filenames are rejected | 通过 | 1.307 | — |
14
+ | 6 | bundled names and ambiguous containers are rejected | 通过 | 1.1597 | — |
15
+ | 7 | single-file rule accepts UTF-8 BOM and CRLF; empty rules are refused | 通过 | 4.3463 | — |
16
+ | 8 | file and directory prefix conflicts fail during preview | 通过 | 1.1838 | — |
17
+ | 9 | failed installation removes only its own incomplete directory | 通过 | 10.333 | — |
18
+ | 10 | host directory scanner resolves one container child and excludes caches | 通过 | 5.7372 | — |
19
+ | 11 | host scanner rejects symlink or junction source paths | 通过 | 2.4564 | — |
20
+ | 12 | deep directories and oversized files fail before installation | 通过 | 32.4539 | — |
21
+ | 13 | invalid UTF-8, encoding and absent source directories report errors | 通过 | 1.8314 | — |
22
+ | 14 | registered host workspace wins over client spelling; unknown paths fail | 通过 | 2.952 | — |
23
+ | 15 | legacy host retains its explicit workspace policy | 通过 | 0.3168 | — |
24
+ | 16 | host registry failures are not downgraded to legacy permissions | 通过 | 0.1657 | — |
25
+ | 17 | ledger shows absent storage as empty and propagates access errors | 通过 | 21.1636 | — |
26
+ | 18 | ledger rejects malformed records instead of pretending there are no tasks | 通过 | 0.3444 | — |
27
+ | 19 | 审查通过后更新状态并激活下一项,保留已完成项的审计 | 通过 | 9.621 | — |
28
+ | 20 | 追加修复项可按 id 保留旧标题,拒绝已完成项改名后静默丢审核 | 通过 | 2.9022 | — |
29
+ | 21 | 派发立即反映进行中,重派不复用旧审核且保持单一进行项 | 通过 | 2.2759 | — |
30
+ | 22 | 无任务 id 的 status 发现当前工作区任务并支持分支过滤 | 通过 | 0.904 | — |
31
+ | 23 | 状态明确区分内置节点门禁与附加技能命令回执,避免重复验证 | 通过 | 2.5274 | — |
32
+ | 24 | status 披露当前阶段记录字段和缺项,字段误用不写入且可按提示恢复 | 通过 | 2.3448 | — |
33
+ | 25 | 记录字段来自冻结流程,精简流程不硬编码标准字段,无记录阶段返回空列表 | 通过 | 3.7337 | — |
34
+ | 26 | 可选内置技能回执不会因范围变更升级成额外流转门禁 | 通过 | 1.993 | — |
35
+ | 27 | 验证使用会话策略与取消信号,并明确返回失败及沙箱信息 | 通过 | 0.9705 | — |
36
+ | 28 | 只声明已测试、或加载失败,均不能冒充执行绑定技能 | 通过 | 1.2714 | — |
37
+ | 29 | 绑定技能失败阻止完成;成功后仍须提交真实 Git 回执 | 通过 | 4.7971 | — |
38
+ | 30 | 验证后修改代码会使旧回执失效,必须重新验证 | 通过 | 1.7267 | — |
39
+ | 31 | status 提交提示与真实门禁一致,分别披露过期验证和附加技能回执且不改台账 | 通过 | 4.7468 | — |
40
+ | 32 | 同名技能与规则在项目和个人目录各自保留管理入口 | 通过 | 19.3435 | — |
41
+ | 33 | 安装包的七个内置技能实际注册且可在资源目录发现 | 通过 | 2.9187 | — |
@@ -0,0 +1,56 @@
1
+ # 自动化测试逐项记录
2
+
3
+ 来源:r02-business-tests.log;共 50 项。
4
+
5
+ | ID | 用例 | 结果 | 耗时 ms |
6
+ | --- | --- | --- | ---: |
7
+ | 1 | aggregate / 主验收用例:按批次累计并按 batchId 升序输出,总计正确 | 通过 | 1.7221 |
8
+ | 2 | aggregate / 空数组合法:batches 为空且 totals 全为 0 | 通过 | 0.3127 |
9
+ | 3 | aggregate / 零值合法:inspected 与 defective 为 0 时 defectRate 为 0 | 通过 | 0.2572 |
10
+ | 4 | aggregate / defective 为 0 而 inspected 大于 0 时 defectRate 为 0 | 通过 | 0.2215 |
11
+ | 5 | aggregate / batchId 去除前后空格后归并同一批次并累计 | 通过 | 0.1655 |
12
+ | 6 | aggregate / batches 按 batchId 字符串升序(码元序,与本地化无关) | 通过 | 0.2373 |
13
+ | 7 | aggregate / totals 为各批次之和,且 totals.defectRate 由总计重新计算 | 通过 | 0.1854 |
14
+ | 8 | aggregate / 根不是数组时抛出 ValidationError | 通过 | 0.5797 |
15
+ | 9 | defectRateOf / inspected 为 0 时返回 0 | 通过 | 0.2674 |
16
+ | 10 | defectRateOf / 按百分数计算并四舍五入到至多两位小数 | 通过 | 0.247 |
17
+ | 11 | defectRateOf / 所有取值的百分数结果都至多两位小数 | 通过 | 2.3668 |
18
+ | 12 | validateRecord / 返回归一化后的记录(batchId 已去除前后空格) | 通过 | 0.3104 |
19
+ | 13 | validateRecord / 记录不是对象 → 抛出带具体原因的 ValidationError | 通过 | 0.2946 |
20
+ | 14 | validateRecord / 记录是数组或 null → 抛出带具体原因的 ValidationError | 通过 | 0.0734 |
21
+ | 15 | validateRecord / batchId 缺失 → 抛出带具体原因的 ValidationError | 通过 | 0.0679 |
22
+ | 16 | validateRecord / batchId 不是字符串 → 抛出带具体原因的 ValidationError | 通过 | 0.1043 |
23
+ | 17 | validateRecord / batchId 为空字符串 → 抛出带具体原因的 ValidationError | 通过 | 0.0562 |
24
+ | 18 | validateRecord / batchId 为纯空白 → 抛出带具体原因的 ValidationError | 通过 | 0.0991 |
25
+ | 19 | validateRecord / inspected 为字符串数字 → 抛出带具体原因的 ValidationError | 通过 | 0.063 |
26
+ | 20 | validateRecord / inspected 为小数 → 抛出带具体原因的 ValidationError | 通过 | 1.6018 |
27
+ | 21 | validateRecord / inspected 为负数 → 抛出带具体原因的 ValidationError | 通过 | 0.2323 |
28
+ | 22 | validateRecord / defective 为字符串数字 → 抛出带具体原因的 ValidationError | 通过 | 0.0926 |
29
+ | 23 | validateRecord / defective 为小数 → 抛出带具体原因的 ValidationError | 通过 | 0.0762 |
30
+ | 24 | validateRecord / defective 为负数 → 抛出带具体原因的 ValidationError | 通过 | 0.1131 |
31
+ | 25 | validateRecord / defective 大于 inspected → 抛出带具体原因的 ValidationError | 通过 | 0.0584 |
32
+ | 26 | validateRecord / 非法记录的错误信息包含记录下标,便于定位 | 通过 | 0.1725 |
33
+ | 27 | aggregate 对非法输入的短路行为 / 逐条校验,遇到首条非法记录即抛出且不返回结果 | 通过 | 0.117 |
34
+ | 28 | CLI 成功路径(node src/cli.mjs <input.json>) / 主验收用例:B 10/1、A 5/0、B 10/2 → A 5/0/0、B 20/3/15,总计 25/3/12 | 通过 | 490.6289 |
35
+ | 29 | CLI 成功路径(node src/cli.mjs <input.json>) / 空数组合法:batches 为空,totals 全为 0 | 通过 | 281.0915 |
36
+ | 30 | CLI 成功路径(node src/cli.mjs <input.json>) / 零值合法:inspected 与 defective 均为 0 时 defectRate 为 0 | 通过 | 209.3507 |
37
+ | 31 | CLI 成功路径(node src/cli.mjs <input.json>) / batchId 去除前后空格后同批次累计 | 通过 | 113.847 |
38
+ | 32 | CLI 成功路径(node src/cli.mjs <input.json>) / defectRate 至多两位小数且为数值型 | 通过 | 87.8699 |
39
+ | 33 | CLI 参数错误 / 无参数 → 非零退出并说明缺少参数 | 通过 | 82.0618 |
40
+ | 34 | CLI 参数错误 / 文件不存在 → 非零退出并说明读取失败 | 通过 | 81.6583 |
41
+ | 35 | CLI 参数错误 / 多余参数 → 非零退出 | 通过 | 96.195 |
42
+ | 36 | CLI 参数错误 / 未知选项 → 非零退出 | 通过 | 98.5844 |
43
+ | 37 | CLI --help / --help 退出码 0 且 stdout 输出用法 | 通过 | 83.1551 |
44
+ | 38 | CLI --help / -h 退出码 0 且 stdout 输出用法 | 通过 | 89.7449 |
45
+ | 39 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / 非法 JSON 文本 | 通过 | 88.3874 |
46
+ | 40 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / 根不是数组 | 通过 | 88.4727 |
47
+ | 41 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / batchId 为空字符串 | 通过 | 79.4806 |
48
+ | 42 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / batchId 为纯空白 | 通过 | 78.3269 |
49
+ | 43 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / inspected 为负数 | 通过 | 81.4441 |
50
+ | 44 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / defective 为负数 | 通过 | 76.5963 |
51
+ | 45 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / inspected 为小数 | 通过 | 69.1574 |
52
+ | 46 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / defective 为小数 | 通过 | 72.4095 |
53
+ | 47 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / 数字写成字符串 | 通过 | 74.708 |
54
+ | 48 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / defective 大于 inspected | 通过 | 79.6399 |
55
+ | 49 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / 记录不是对象 | 通过 | 70.2125 |
56
+ | 50 | CLI 非法输入(非零退出 + stderr 具体原因 + stdout 无成功结果) / 错误信息带记录下标,可定位到具体记录 | 通过 | 75.1616 |
@@ -0,0 +1,38 @@
1
+ # 自动化测试逐项记录
2
+
3
+ 来源:r03-business-tests.log;共 32 项。
4
+
5
+ | ID | 用例 | 结果 | 耗时 ms |
6
+ | --- | --- | --- | ---: |
7
+ | 1 | 单元 aggregate:同批次累计、码元升序并输出 defectRate | 通过 | 1.695 |
8
+ | 2 | 单元 aggregate:空数组得到空 batches 与全零 totals | 通过 | 0.2052 |
9
+ | 3 | 单元 aggregate:inspected 为 0 时 defectRate 为 0 | 通过 | 0.1467 |
10
+ | 4 | 单元 aggregate:defectRate 至多两位小数且为数值类型 | 通过 | 0.2306 |
11
+ | 5 | 单元 aggregate:totals.defectRate 基于累计值而非各批次比率平均 | 通过 | 0.111 |
12
+ | 6 | 单元 aggregate:按 batchId 字符串码元升序(大写先于小写) | 通过 | 0.0989 |
13
+ | 7 | 单元 validateRecords:batchId 去除前后空格后作为同一批次 | 通过 | 0.1417 |
14
+ | 8 | 单元 validateRecords:接受非负整数与零值边界 | 通过 | 0.1628 |
15
+ | 9 | 单元 validateRecords:拒绝非数组、非法元素与非法字段 | 通过 | 0.683 |
16
+ | 10 | AC1 同批次累计,stdout 仅一行 JSON,totals 正确 | 通过 | 74.2086 |
17
+ | 11 | AC2 空数组合法 | 通过 | 75.882 |
18
+ | 12 | AC3 零数合法 | 通过 | 85.2254 |
19
+ | 13 | AC4 batchId 去空格归并并按码元升序 | 通过 | 82.9206 |
20
+ | 14 | AC5 非法 JSON 失败且 stdout 为空 | 通过 | 90.9043 |
21
+ | 15 | AC6 顶层非数组失败且 stdout 为空 | 通过 | 379.1634 |
22
+ | 16 | AC7 batchId 为空字符串 → 非零退出、stdout 为空、stderr 具体 | 通过 | 80.0845 |
23
+ | 17 | AC7 batchId 为纯空白 → 非零退出、stdout 为空、stderr 具体 | 通过 | 74.659 |
24
+ | 18 | AC7 batchId 缺失 → 非零退出、stdout 为空、stderr 具体 | 通过 | 78.5134 |
25
+ | 19 | AC8 inspected 为负数 → 非零退出、stdout 为空、stderr 具体 | 通过 | 121.0524 |
26
+ | 20 | AC8 defective 为负数 → 非零退出、stdout 为空、stderr 具体 | 通过 | 77.35 |
27
+ | 21 | AC9 inspected 为小数 → 非零退出、stdout 为空、stderr 具体 | 通过 | 66.7267 |
28
+ | 22 | AC9 defective 为小数 → 非零退出、stdout 为空、stderr 具体 | 通过 | 68.4103 |
29
+ | 23 | AC10 inspected 为字符串数字 → 非零退出、stdout 为空、stderr 具体 | 通过 | 71.1564 |
30
+ | 24 | AC10 defective 为字符串数字 → 非零退出、stdout 为空、stderr 具体 | 通过 | 71.2365 |
31
+ | 25 | AC11 defective 大于 inspected → 非零退出、stdout 为空、stderr 具体 | 通过 | 76.4629 |
32
+ | 26 | 非对象元素 → 非零退出、stdout 为空、stderr 具体 | 通过 | 72.6897 |
33
+ | 27 | AC12 无参数失败并提示用法 | 通过 | 75.6079 |
34
+ | 28 | 多余参数失败并提示用法 | 通过 | 73.248 |
35
+ | 29 | AC13 文件不存在失败且 stdout 为空 | 通过 | 71.4465 |
36
+ | 30 | AC14 --help 退出 0 并输出用法 | 通过 | 141.8224 |
37
+ | 31 | AC14 --help 优先于其他参数 | 通过 | 70.1995 |
38
+ | 32 | AC15 examples/batches.json 可直接运行并得到文档所述结果 | 通过 | 73.5514 |
@@ -0,0 +1,65 @@
1
+ # 0.23.2 实机循环回归报告
2
+
3
+ [← 发布说明](../../release-0.23.2.md)
4
+
5
+ 日期:2026-09-17。结论:权限缺陷修复后,两个新会话从同一空业务基线完成标准研发流程、独立验收、本地提交和归档回退;门禁专项通过。验证对象是本机 Harness 上的独立 CLI 项目,不是 QMS 页面、数据库或生产业务。
6
+
7
+ ## 环境与方法
8
+
9
+ Harness 提交 `d347e703908d0406b7a7ef80e3a0e594d86b2215`,Windows、Node 22.22.3、web profile,模型 `deepseek-v4.1-flash`,工程化开发引擎预设。独立仓库 `D:\dshtest`,分支 `codex/plugin-live-regression`,基线 `aae3bf8994ef803cf8370f5f53840b508539499c` 仅有 `.gitignore`。
10
+
11
+ 冻结需求为零依赖 ESM 质检批次统计 CLI:严格校验 JSON 记录,按 trim 后的 batchId 累计并按码元排序,计算百分数缺陷率,正确区分成功 JSON 与失败 stderr,提供单元测试、真实 CLI 子进程测试、样例及 README。所有业务代码由 DSH 编写;观察者只审阅、执行独立验收、归档及修复插件。每轮使用新会话,不读取前轮实现;QMS 未改动。
12
+
13
+ ## 轮次结果
14
+
15
+ | 轮次 | 插件 | 业务测试 / 独立黑盒 | 流程结果 | 本地提交 |
16
+ | --- | --- | --- | --- | --- |
17
+ | R01 | 0.23.1 | 24 / 19 通过 | 插件验证权限缺陷阻塞交付;停止、归档,未冒充完成 | 无 |
18
+ | R02 | 0.23.2-rc.1 | 50 / 19 通过 | 审批、3项实施审核、验证、代码审核、提交回写、完成、归档回退通过 | `15ffd9c230363520a934586107ce9f4023e828ed` |
19
+ | R03 | 0.23.2-rc.3 | 32 / 19 通过 | 设计退回修订、4项实施审核、验证、代码审核、提交回写、完成、归档回退通过 | `4e476a514d3109417bac602e818460b09dd57289` |
20
+
21
+ R02 与 R03 的权限核心构建文件 SHA256 均为 `FD116354D20D870E8981B4C098E9F0BDBE9B213397918D7181FE07E0E1713688`;期间只修正提交规则及文档。rc.2 安装核对时发现新指南误称 status 返回格式字段,已改为实际的 `commit.label` 并重打 rc.3,rc.2 不计作业务轮次。
22
+
23
+ R02 为27项单元、23项CLI子进程测试;R03 为9项单元、23项CLI子进程测试。DSH 的 R03 最终文字误写8+24,本报告按实际测试文件与TAP用例核对为9+23。逐项结果和耗时见[R02明细](R02业务测试明细.md)、[R03明细](R03业务测试明细.md)。独立黑盒19项覆盖主用例、空数组、零值、trim与取整、4类非法顶层输入、7类非法字段、非法JSON、缺参数、缺文件和帮助。
24
+
25
+ ## 门禁专项
26
+
27
+ | 场景 | 实际结果 | 结论 |
28
+ | --- | --- | --- |
29
+ | 未加载绑定技能即推进 | 返回 load skill requirement-analysis,未推进 | 通过 |
30
+ | 缺少需求产物与确认即推进 | 返回 requirement_confirmation / artifacts_present 未满足 | 通过 |
31
+ | 使用合法消息提前提交 | 返回当前阶段无提交检查点,revision仍为1 | 通过 |
32
+ | 普通权限运行 node --test | 真实exit1,子进程spawn EPERM,回执mode=workspace-write | 按预期失败 |
33
+ | 拒绝该命令的权限升级 | 工具报rejected,台账逐字节哈希不变 | 通过 |
34
+ | 明确重新授权后批准原命令 | 50项测试通过,exit0,回执mode=danger-full-access | 通过 |
35
+ | 修改唯一范围文件 | status出现验证过期的evidence_blockers,冻结旧回执保留 | 通过 |
36
+ | 同会话后续普通shell调用 | 原命令重新EPERM,未继承单次权限 | 通过 |
37
+
38
+ 拒绝前后台账 SHA256 均为 `99F13BB166B4D0C9D7EC4EAE00F0471E7CEABD97541ADD85820A64A0D2008306`。专项任务 `DSH-GATE-PROBE` 停在需求阶段,不计作完整业务轮次。过期提交的检查点路径由自动化回归覆盖;本次专项实机验证到动态过期提示,未声称在该检查点另外执行过过期提交。
39
+
40
+ R03完整流程另通过正式 `dev_task verify` 执行 `npm test`:单次审批后32项通过、exit0、实际模式danger-full-access。R02使用可在受限环境运行的真实文件描述符子进程测试,其workspace-write成功回执不冒充权限修复证据。R03修正后的提交消息首次预检即获批准,随后核对真实Git提交并登记。
41
+
42
+ ## 插件回归与缺陷
43
+
44
+ P1:0.23.1在执行验证命令之后才审批写台账,导致命令先运行且未收到批准模式。回归测试先复现“审批服务不可用却已调用一次shell”,修复后拒绝、取消、审批不可用、非法参数均不运行命令或改台账;verify与skill_result批准顺序、请求上下文、单次权限和回执写入不重复审批均受断言保护。
45
+
46
+ P2:随包提交规则要求模块名,而引擎要求任务id,R02实际出现两次格式拒绝。规则及手册改为当前任务id和status.commit.label;R03未再出现该格式错误。
47
+
48
+ 源码构建、host/client类型检查、126项P0和37项node:test回归通过;候选包干净安装、入口导入、客户端注册、包内测试及CLI语法验证通过。源码测试明细见[自动化测试明细](自动化测试明细.md)。最终0.23.2的 `npm run verify:package` 由用户在插件源码目录执行并确认通过;此项依据用户执行反馈,观察者没有独立保存该次终端日志。发布版本与远端提交另外核对,不以本报告代替发布成功回执。
49
+
50
+ ## 归档与干预
51
+
52
+ 两个完成轮次的父提交均为B0,文件分别严格限制为10个、5个;归档前工作区干净,任务均为完成、review=pass,最终登记hash等于HEAD。业务ZIP、任务JSON、会话日志及独立验收记录保存在本地 `live-project-test/regression-20260917`;备份分支为 `codex/archive-dsh-reg-r02` 和 `codex/archive-dsh-reg-r03`。业务分支最终恢复B0,保留被忽略的历史台账。
53
+
54
+ | 归档 | 业务ZIP SHA256 |
55
+ | --- | --- |
56
+ | R02 | `2545B54A201D70D536B85BDB52F2356CE2364310FCAF32E99F759408BFC98D82` |
57
+ | R03 | `F7BB52228137BA0A37722097A26AF6BBE1AEFB09C416792F4EE94EA29E71DD56` |
58
+
59
+ 观察者处理了正式需求/设计/权限审批;R03退回已知Node22测试目录入口问题,并要求DSH通过正式审批区分EPERM与入口错误,保留默认测试隔离和真实子进程。观察者未代写业务代码。测试包含这些干预,不能称为完全自主执行。
60
+
61
+ ## 能力边界与未覆盖范围
62
+
63
+ `dev_task`对阶段、证据和提交登记实施门禁,通用文件写入不会逐次经过状态机;R03实际在实施项仍为todo时写入文件,随后才逐项审核和标记done。没有安装提交钩子时,不能据此宣称插件能阻止直接shell绕过提交预检。本轮未测试强行篡改台账、直接Git绕过、多人并发、QMS集成、全部Harness/模型版本或生产部署。
64
+
65
+ scope_hash只覆盖任务files的内容,不能证明命令或范围外业务文件未变;观察者已纠正DSH一次过度解读。模型报告也可能出现测试分类计数错误,必须复核实际日志。自动化中的模拟宿主与真实DSH会话分开计证,不互相替代。
@@ -0,0 +1,43 @@
1
+ # 候选自动化用例明细
2
+
3
+ 0.23.2-rc.1;37 项 node:test 全部通过。P0 126 项未改动,逐项结果沿用 p0-details.log,包内另复核全部通过。
4
+
5
+ | ID | 用例 | 结果 | 耗时 ms |
6
+ | --- | --- | --- | ---: |
7
+ | 1 | preview has no filesystem side effects and reports exact bytes | ok | 11.3153 |
8
+ | 2 | confirmed install preserves binary assets and refuses duplicates | ok | 8.326 |
9
+ | 3 | changed content and changed installation target invalidate preview | ok | 4.0861 |
10
+ | 4 | path traversal, Windows ADS and reserved names are rejected | ok | 2.0011 |
11
+ | 5 | case-colliding filenames are rejected | ok | 2.3438 |
12
+ | 6 | bundled names and ambiguous containers are rejected | ok | 1.9229 |
13
+ | 7 | single-file rule accepts UTF-8 BOM and CRLF; empty rules are refused | ok | 6.0905 |
14
+ | 8 | file and directory prefix conflicts fail during preview | ok | 1.2461 |
15
+ | 9 | failed installation removes only its own incomplete directory | ok | 10.4183 |
16
+ | 10 | host directory scanner resolves one container child and excludes caches | ok | 6.396 |
17
+ | 11 | host scanner rejects symlink or junction source paths | ok | 3.2175 |
18
+ | 12 | deep directories and oversized files fail before installation | ok | 22.504 |
19
+ | 13 | invalid UTF-8, encoding and absent source directories report errors | ok | 1.6991 |
20
+ | 14 | registered host workspace wins over client spelling; unknown paths fail | ok | 2.8311 |
21
+ | 15 | legacy host retains its explicit workspace policy | ok | 0.1852 |
22
+ | 16 | host registry failures are not downgraded to legacy permissions | ok | 0.1354 |
23
+ | 17 | ledger shows absent storage as empty and propagates access errors | ok | 23.1621 |
24
+ | 18 | ledger rejects malformed records instead of pretending there are no tasks | ok | 0.6101 |
25
+ | 19 | 审查通过后更新状态并激活下一项,保留已完成项的审计 | ok | 9.6898 |
26
+ | 20 | 追加修复项可按 id 保留旧标题,拒绝已完成项改名后静默丢审核 | ok | 2.3858 |
27
+ | 21 | 派发立即反映进行中,重派不复用旧审核且保持单一进行项 | ok | 2.3334 |
28
+ | 22 | 无任务 id 的 status 发现当前工作区任务并支持分支过滤 | ok | 1.0932 |
29
+ | 23 | verify 升级审批不可用时不得先执行命令 | ok | 0.997 |
30
+ | 24 | verify 拒绝、取消及无效升级参数均不执行命令或改写台账 | ok | 4.5955 |
31
+ | 25 | 验证命令审批先于执行,只授权本次命令且回执写入不重复审批 | ok | 3.841 |
32
+ | 26 | skill_result 审批拒绝时不执行命令、不写入技能回执 | ok | 0.8195 |
33
+ | 27 | 状态明确区分内置节点门禁与附加技能命令回执,避免重复验证 | ok | 2.7189 |
34
+ | 28 | status 披露当前阶段记录字段和缺项,字段误用不写入且可按提示恢复 | ok | 3.6317 |
35
+ | 29 | 记录字段来自冻结流程,精简流程不硬编码标准字段,无记录阶段返回空列表 | ok | 3.7388 |
36
+ | 30 | 可选内置技能回执不会因范围变更升级成额外流转门禁 | ok | 1.7078 |
37
+ | 31 | 验证使用会话策略与取消信号,并明确返回失败及沙箱信息 | ok | 0.8526 |
38
+ | 32 | 只声明已测试、或加载失败,均不能冒充执行绑定技能 | ok | 1.3581 |
39
+ | 33 | 绑定技能失败阻止完成;成功后仍须提交真实 Git 回执 | ok | 4.0405 |
40
+ | 34 | 验证后修改代码会使旧回执失效,必须重新验证 | ok | 4.9841 |
41
+ | 35 | status 提交提示与真实门禁一致,分别披露过期验证和附加技能回执且不改台账 | ok | 5.0372 |
42
+ | 36 | 同名技能与规则在项目和个人目录各自保留管理入口 | ok | 18.9429 |
43
+ | 37 | 安装包的七个内置技能实际注册且可在资源目录发现 | ok | 2.7658 |
@@ -0,0 +1,36 @@
1
+ # 真实项目回归迭代
2
+
3
+ 版本:0.23.1,汇总本轮候选修复;完整业务流程的实机证据来自 rc.3,后续修复有针对性回归及包验证。
4
+
5
+ 以 EAM 设备结构树和单选弹窗需求重跑工作台,业务代码由工作台执行;插件修复与独立观察分开记录。
6
+
7
+ | 上一轮问题 | 本轮处理 |
8
+ | :--- | :--- |
9
+ | 项目技能被同名个人技能覆盖 | 资源目录保留各来源;绑定选择按名称去重。 |
10
+ | 无任务 ID 的入口 status 报错 | 返回候选列表,支持分支过滤,不猜测当前任务。 |
11
+ | 更新实施项状态清空审核记录 | 同 ID、同标题保留审核;重开或改标题使审核失效。 |
12
+ | verify 丢会话沙箱上下文 | 透传会话策略与取消信号,记录沙箱结果。 |
13
+ | 审核后已错过提交窗口 | 标准 v2 改为审核通过后提交,离开前核对 Git 回执。 |
14
+ | 完成才披露测试技能,未执行 | 终态绑定提前执行;加载记录和附加技能命令回执参与门禁。 |
15
+ | 内置技能被误当成附加技能重复登记 | 状态列出必需回执技能;可选内置回执过期不额外拦截。 |
16
+ | 子代理已开工而实施项仍待办 | 派工前登记并自动设进行中,禁止另一项同时进行;实际执行仍核对日志。 |
17
+ | 追加修复项重写标题使审核丢失 | 已有项支持省略标题;已审核项改名须先重新打开。 |
18
+ | 方案猜测字段、驳回后直接重试 | 要求核对资料和真实组件行为,先收集反馈再修订送审。 |
19
+
20
+ 新任务验证使用真实命令,并关联声明文件内容。改动代码后重跑验证;不会把“我测过了”直接转换为通过。附加技能可用交付文件内容校验命令,但不能用恒成功命令充当验收。
21
+
22
+ 旧任务使用冻结配置及原执行约定,不自动修改历史记录。规则解析优先级为内置、项目、个人;技能正文的选择由 Harness 技能目录负责。
23
+
24
+ 边界:文件摘要只涵盖声明的任务文件,不涵盖数据库、远端接口、依赖和未声明文件;成功退出码不证明测试充分。审核意见仍需人工判断。当前没有对任务记录做签名,也不防止有权限的人直接手改状态。
25
+
26
+ 验收要求:同一个真实需求走完确认、设计、开发、技能测试、验证、审核、受控提交;不得另建收尾任务绕过门禁,不得以简单命令替代失败的核心验证。插件发布与业务验收分开记录,未完成的真实联调不宣称通过。
27
+
28
+ 执行指引:范围清楚的小修正可由主代理完成,保留状态、审核及定向验证,不强制重复派子代理;权限或沙箱拒绝须走正式审批或报告阻塞,禁止反复换命令或修改 ACL 规避。上述行为指引不能替代 Harness 的权限执行,也尚未证明可消除模型误用。
29
+
30
+ 本轮 EAMDEV-R2 已在同一任务达到完成(revision 60),8 项审核齐全,software-testing 在终态前执行并记录真实回执,业务提交 95892e8 回写成功;未推送或发布。结构树真实请求返回非 JSON,配置大小写差异待授权修正,不能声称端到端验收通过。
31
+
32
+ 实机发现状态查询仍将过期回执任务显示为可提交,但真实 commit 门禁拒绝。rc.5 让 status 使用与 commit 相同的技能和摘要阻塞检查,新增 evidence_blockers,保持状态查询只读。报告证据归属错误仍需审查,技能加载和退出码不能证明报告内容准确。
33
+
34
+ 后续任务出现未定义记录字段:校验正确拒绝,但模型缺少主动字段提示。0.23.1 新增 artifact_requirements,按冻结流程返回当前阶段字段及缺项,错误附恢复说明;兼容敏捷流程只有 scope 的情况,两个新增用例先失败后通过。
35
+
36
+ 完整重跑方法:每轮归档业务差异、任务和问题证据,修复插件后将本轮业务改动恢复到同一基线,用独立会话重新交付完整需求。保留插件改进,不把上一轮实现复制为下一轮成果。暂停期间不调用模型;额度/鉴权问题属于服务状态,不由本包修改凭证处理。
package/hooks/commit-msg CHANGED
@@ -137,7 +137,7 @@ var STANDARD = {
137
137
  policy: "task",
138
138
  message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
139
139
  message_hint: "\u3010<task_id>\u3011\u3010TASK/T1\u3011\u8BF4\u660E \u2014\u2014 \u7B2C\u4E00\u6BB5\u586B\u672C\u4EFB\u52A1 id\uFF08\u5982 GREET-001\uFF09\uFF0C\u5199\u7ED3\u679C\u4E0D\u5199\u7A7A\u6CDB\u52A8\u4F5C",
140
- checkpoints: ["\u4EA4\u4ED8"],
140
+ checkpoints: ["\u4EE3\u7801\u5BA1\u6838"],
141
141
  file_scope: true
142
142
  },
143
143
  high_risk_requires_verification: true,
@@ -145,8 +145,8 @@ var STANDARD = {
145
145
  "\u9700\u6C42\u8BC4\u5BA1": { skills: ["requirement-analysis"], rules: ["security-redlines"] },
146
146
  "\u8BBE\u8BA1": { skills: ["solution-design"] },
147
147
  "\u5F00\u53D1": { skills: ["code-implement"], rules: ["coding-conventions"] },
148
- "\u4EA4\u4ED8": { skills: ["code-verify", "code-commit"], rules: ["coding-conventions", "commit-conventions"] },
149
- "\u4EE3\u7801\u5BA1\u6838": { skills: ["code-review"], rules: ["security-redlines"] }
148
+ "\u4EA4\u4ED8": { skills: ["code-verify"], rules: ["coding-conventions"] },
149
+ "\u4EE3\u7801\u5BA1\u6838": { skills: ["code-review", "code-commit"], rules: ["security-redlines", "commit-conventions"] }
150
150
  }
151
151
  };
152
152
  var AGILE = {
@@ -208,7 +208,7 @@ function preset(id, version, label, description, config2) {
208
208
  return { id, version, label, description, capabilities: deriveCapabilities(config2), config: config2 };
209
209
  }
210
210
  var FLOW_PRESETS = {
211
- standard: preset("standard", 1, "\u6807\u51C6\u7814\u53D1", "\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838\uFF0C\u542B\u4EA7\u7269\u95E8 + \u786E\u8BA4\u95E8", STANDARD),
211
+ standard: preset("standard", 2, "\u6807\u51C6\u7814\u53D1", "\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838\uFF0C\u5BA1\u6838\u540E\u63D0\u4EA4", STANDARD),
212
212
  agile: preset("agile", 1, "\u654F\u6377\u8F7B\u91CF", "\u9700\u6C42 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u5BA1\u67E5\uFF0C\u56DB\u9636\u6BB5\u3001\u5C11\u4EA7\u7269", AGILE),
213
213
  minimal: preset("minimal", 1, "\u7EAF\u4EE3\u7801", "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981", MINIMAL)
214
214
  };
package/lib/client.js CHANGED
@@ -4831,7 +4831,7 @@ var STANDARD = {
4831
4831
  policy: "task",
4832
4832
  message_pattern: "^\u3010(\\S+)\u3011\u3010(?:TASK|T\\d+)\u3011.+",
4833
4833
  message_hint: "\u3010<task_id>\u3011\u3010TASK/T1\u3011\u8BF4\u660E \u2014\u2014 \u7B2C\u4E00\u6BB5\u586B\u672C\u4EFB\u52A1 id\uFF08\u5982 GREET-001\uFF09\uFF0C\u5199\u7ED3\u679C\u4E0D\u5199\u7A7A\u6CDB\u52A8\u4F5C",
4834
- checkpoints: ["\u4EA4\u4ED8"],
4834
+ checkpoints: ["\u4EE3\u7801\u5BA1\u6838"],
4835
4835
  file_scope: true
4836
4836
  },
4837
4837
  high_risk_requires_verification: true,
@@ -4839,8 +4839,8 @@ var STANDARD = {
4839
4839
  "\u9700\u6C42\u8BC4\u5BA1": { skills: ["requirement-analysis"], rules: ["security-redlines"] },
4840
4840
  "\u8BBE\u8BA1": { skills: ["solution-design"] },
4841
4841
  "\u5F00\u53D1": { skills: ["code-implement"], rules: ["coding-conventions"] },
4842
- "\u4EA4\u4ED8": { skills: ["code-verify", "code-commit"], rules: ["coding-conventions", "commit-conventions"] },
4843
- "\u4EE3\u7801\u5BA1\u6838": { skills: ["code-review"], rules: ["security-redlines"] }
4842
+ "\u4EA4\u4ED8": { skills: ["code-verify"], rules: ["coding-conventions"] },
4843
+ "\u4EE3\u7801\u5BA1\u6838": { skills: ["code-review", "code-commit"], rules: ["security-redlines", "commit-conventions"] }
4844
4844
  }
4845
4845
  };
4846
4846
  var AGILE = {
@@ -4902,7 +4902,7 @@ function preset(id, version, label2, description, config) {
4902
4902
  return { id, version, label: label2, description, capabilities: deriveCapabilities(config), config };
4903
4903
  }
4904
4904
  var FLOW_PRESETS = {
4905
- standard: preset("standard", 1, "\u6807\u51C6\u7814\u53D1", "\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838\uFF0C\u542B\u4EA7\u7269\u95E8 + \u786E\u8BA4\u95E8", STANDARD),
4905
+ standard: preset("standard", 2, "\u6807\u51C6\u7814\u53D1", "\u9700\u6C42\u8BC4\u5BA1 \u2192 \u8BBE\u8BA1 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u4EE3\u7801\u5BA1\u6838\uFF0C\u5BA1\u6838\u540E\u63D0\u4EA4", STANDARD),
4906
4906
  agile: preset("agile", 1, "\u654F\u6377\u8F7B\u91CF", "\u9700\u6C42 \u2192 \u5F00\u53D1 \u2192 \u4EA4\u4ED8 \u2192 \u5BA1\u67E5\uFF0C\u56DB\u9636\u6BB5\u3001\u5C11\u4EA7\u7269", AGILE),
4907
4907
  minimal: preset("minimal", 1, "\u7EAF\u4EE3\u7801", "\u5F00\u53D1 \u2192 \u4EA4\u4ED8\uFF0C\u4E24\u9636\u6BB5\uFF0C\u53EA\u7559\u63D0\u4EA4\u95E8\u7981", MINIMAL)
4908
4908
  };
@@ -5179,6 +5179,7 @@ function BindingEditor({ stages, stageBindings, setStageBindings, skills, rules
5179
5179
  const boundSkills = stageBindings[currentStage]?.skills ?? [];
5180
5180
  const boundRules = stageBindings[currentStage]?.rules ?? [];
5181
5181
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.section, children: [
5182
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: styles.hint, children: "\u7ED1\u5B9A\u6309\u540D\u79F0\u751F\u6548\uFF1B\u540C\u540D\u8D44\u6E90\u53EF\u5728\u8D44\u6E90\u7BA1\u7406\u4E2D\u6309\u9879\u76EE\uFF0F\u4E2A\u4EBA\u5206\u522B\u67E5\u770B\u3002\u5B8C\u6210\u8282\u70B9\u7684\u6280\u80FD\u5FC5\u987B\u5728\u8FDB\u5165\u5B8C\u6210\u524D\u6267\u884C\uFF0C\u6D4B\u8BD5\u6280\u80FD\u5EFA\u8BAE\u653E\u5728\u4EA4\u4ED8\u8282\u70B9\u3002" }),
5182
5183
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.field, children: [
5183
5184
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "\u9009\u62E9\u8282\u70B9\uFF08\u6539\u54EA\u4E2A\u8282\u70B9\u7684\u6302\u8F7D\uFF09" }),
5184
5185
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: stages.map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Pill, { active: s === currentStage, onClick: () => {
@@ -5188,7 +5189,7 @@ function BindingEditor({ stages, stageBindings, setStageBindings, skills, rules
5188
5189
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: cardV, children: [
5189
5190
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5190
5191
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "skill\uFF08\u8FD9\u4E2A\u8282\u70B9\u505A\u4EC0\u4E48\uFF09" }),
5191
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 skill \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u6280\u80FD\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : skills.map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundSkills.includes(sk.name), onClick: () => {
5192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: skills.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 skill \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u6280\u80FD\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : skills.filter((sk, index, all) => all.findIndex((other) => other.name === sk.name) === index).map((sk) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundSkills.includes(sk.name), onClick: () => {
5192
5193
  toggleSkill(sk.name);
5193
5194
  }, title: `${sk.description}\uFF08${sourceLabel(sk.source)}\uFF09`, children: [
5194
5195
  sk.name,
@@ -5201,7 +5202,7 @@ function BindingEditor({ stages, stageBindings, setStageBindings, skills, rules
5201
5202
  ] }),
5202
5203
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: styles.bindingStage, children: [
5203
5204
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.fieldLabel, children: "rule\uFF08\u8FD9\u4E2A\u8282\u70B9\u5B88\u4EC0\u4E48\uFF09" }),
5204
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 rule \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u89C4\u5219\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : rules.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundRules.includes(rule.name), onClick: () => {
5205
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: styles.chips, children: rules.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: styles.sourceBadge, children: "\u6682\u65E0\u53EF\u7528 rule \u2014\u2014 \u5207\u5230\u4E0A\u65B9\u300C\u89C4\u5219\u300D\u6807\u7B7E\u9875\u65B0\u5EFA" }) : rules.filter((rule, index, all) => all.findIndex((other) => other.name === rule.name) === index).map((rule) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dsh_client_ui_primitives.Pill, { active: boundRules.includes(rule.name), onClick: () => {
5205
5206
  toggleRule(rule.name);
5206
5207
  }, title: `\u6765\u6E90\uFF1A${sourceLabel(rule.source)}`, children: [
5207
5208
  rule.name,