kld-sdd 2.7.8-2 → 2.7.8-3
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/README.md +2 -0
- package/USABILITY.md +52 -0
- package/lib/hook-install.js +75 -0
- package/lib/init.js +28 -148
- package/lib/managed-hook-hashes.json +24 -0
- package/package.json +2 -2
- package/skywalk-sdd/index.cjs +1 -1
- package/skywalk-sdd/kb-upload.cjs +21 -17
- package/skywalk-sdd/lib/test-execution.cjs +20 -0
- package/templates/git-hooks/commit-msg +17 -99
- package/templates/git-hooks/commit-msg-runner.cjs +44 -0
- package/templates/git-hooks/commit-msg-sdd-trailer.cjs +60 -69
- package/templates/git-hooks/consistency-check-core.cjs +61 -240
- package/templates/git-hooks/delivery-check.cjs +231 -0
- package/templates/git-hooks/delivery-snapshot.cjs +181 -0
- package/templates/git-hooks/hooks.config +8 -6
- package/templates/git-hooks/pre-commit-consistency-check.cjs +13 -31
- package/templates/git-hooks/pre-push-consistency-check.cjs +36 -83
- package/templates/openspec/proposal.md +1 -1
- package/templates/skills/kld-sdd/opsx-apply/SKILL.md +24 -22
- package/templates/skills/kld-sdd/opsx-consistency-check/SKILL.md +34 -112
- package/templates/skills/kld-sdd/opsx-consistency-check/scripts/scripts.cjs +1 -14
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opsx-consistency-check
|
|
3
|
-
description: "Spec
|
|
4
|
-
argument-hint: "[change-name]
|
|
3
|
+
description: "根据实际代码和 Spec 检查接口、业务规则与错误处理,按输入指纹复用检查回执"
|
|
4
|
+
argument-hint: "[change-name]"
|
|
5
5
|
license: MIT
|
|
6
6
|
metadata:
|
|
7
7
|
author: sdd-team
|
|
8
|
-
version: "
|
|
8
|
+
version: "4.0"
|
|
9
9
|
allowed-tools:
|
|
10
10
|
- Bash
|
|
11
11
|
- Read
|
|
@@ -13,141 +13,63 @@ allowed-tools:
|
|
|
13
13
|
- Edit
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
检查实现是否满足本次业务约定,留下可复核的证据。`opsx-check` 检查文档及其关系;本技能检查代码与 Spec,两者不能互相替代。日常 Git 提交不要求用户手动运行本技能;Apply 在实施收尾时自动调用。
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## 1. 确定输入并尝试复用
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
1. **采集必须用 hook 同款命令**(步骤 1),禁止手工拼 git diff——两边采集不一致会导致报告盖不住 diff → hook 拦截 → 重新生成仍被拦的死循环
|
|
23
|
-
2. **coveredFiles 必须与实际校验的变更文件完全一致**:path 为工作区相对路径,size/sha256 直接复用采集器输出(LF 归一化已内置),禁止估算、禁止用平台命令重算
|
|
24
|
-
3. **confidence 只能 `high`/`medium`/`low`**(其他值被 hook 判非法拦截);**generatedAt 必须本机本地时间** `YYYY-MM-DD HH:mm:ss`(禁止 UTC,hook 按本地时区做过期判断)
|
|
25
|
-
4. **md + json 成对写入** `openspec/changes/<change-name>/`,单边存在会被判报告不完整并拦截
|
|
26
|
-
5. **只读变更文件本身**,不扩展读 DTO/Model/配置/SQL 等关联文件;缺证据标"待人工核查",不中断补读
|
|
27
|
-
6. **无业务代码变更 → 不生成报告**,输出一句提示即结束(hook 对无业务代码提交直接放行)
|
|
28
|
-
7. 生成前必须先删旧报告(步骤 2c 已内置),全量重新校验,不读旧报告做增量复用
|
|
29
|
-
8. **多仓布局下 `repositories` 必填**:工作区根存在 `.sdd-workspace.yaml` 时,JSON 报告必须含 `repositories` 数组,`path` 为该 change 覆盖的代码仓名(与 `.sdd-workspace.yaml` 的 `code_repos` 条目一致)。单仓布局可省略或留空数组。hook 用此字段剥离 coveredFiles 路径前缀以对齐 diff 路径,缺失会导致路径不匹配 → 误判"无交集" → 报告形同虚设
|
|
30
|
-
|
|
31
|
-
## 执行流程(4 步)
|
|
32
|
-
|
|
33
|
-
### 1. 采集变更文件(脚本,秒级)
|
|
34
|
-
|
|
35
|
-
> **禁止环境预探测**:不要 Test-Path 探测 git 仓、不要列目录确认脚本存在——采集器自动处理单仓/多仓布局(多仓读 `.sdd-workspace.yaml` 的 code_repos 逐仓 diff),命令失败自会报错。首轮回复直接并行发起:① 采集命令 ② `list-changes`(两者无依赖)。
|
|
20
|
+
从当前实施上下文取得明确的 Change 和代码仓。多个活动 Change 不等于本次都要检查;不要按分支名猜测。多仓逐个实际涉及的代码仓运行,使用同一个 Spec 根和 Change;回执按仓库身份分别存储,互不覆盖。
|
|
36
21
|
|
|
37
22
|
```bash
|
|
38
|
-
node <spec-root>/skywalk-sdd/git-hooks/
|
|
39
|
-
node <skill-dir>/scripts/scripts.cjs list-changes
|
|
23
|
+
node "<spec-root>/skywalk-sdd/git-hooks/delivery-check.cjs" prepare --project="<代码仓>" --change=<change> --base=<实施前提交SHA>
|
|
40
24
|
```
|
|
41
25
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
- **无业务文件** → 提示"无代码变更,跳过校验"并结束
|
|
45
|
-
- **有业务文件但无活跃 change** → 报错终止,提示先执行 opsx-propose
|
|
46
|
-
- **多 change 且未指定 change-name** → 按 spec 覆盖范围把文件归属到各 change,每个 change 独立出报告;同一文件被多个 change 归属时只在首个 change 完整校验、其余复用结论(coveredFiles 仍完整包含)。**单 change 或已指定 change-name** → 全部文件归入,跳过归属逻辑
|
|
47
|
-
- **用户指定了具体文件** → 交给 `consistency-check-core.cjs --filter` 机械筛选,哈希用 `prepare-report --files-from=<列表文件>` 补算
|
|
48
|
-
|
|
49
|
-
### 2. 读上下文(a/b/c 同一回复并行发起,禁止分批等待)
|
|
50
|
-
|
|
51
|
-
a. **定位并读 spec**:`node <skill-dir>/scripts/scripts.cjs find-specs <change-name>` 拿文件列表,**禁止全量读**(近百个 spec 全读既慢又撑爆上下文)。API 路径由 AI 从已读 Controller 原生提取(任何语言的路由写法都直接认识,禁止用正则 grep 代码提取),再用**字面量片段**(如 `/api/user`;禁止含 `|`、`"`、`\`、`()` 的正则——Windows cmd 会拆解管道符与引号导致 0 命中)grep spec 目录:
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
node <skill-dir>/scripts/scripts.cjs grep-code "/api/user" <openspec-dir> --glob=spec.md -i
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**grep 省略条件(省一轮往返)**:`find-specs` 命中的变更级 spec 文件总数 ≤ 5 个时,跳过 grep 直接读这些文件(变更级 spec 本来就是该 change 的契约文档,命中概率极高);命中 > 5 个或需在全局 spec 中定位时才 grep。只读命中文件;命中 0 → 回退读变更级 spec(`changes/<name>/specs/`),仍不读全局 spec 全集。
|
|
58
|
-
|
|
59
|
-
b. **读代码(按契约角色分层,同一回复并行发起)**:首轮把全部变更文件按契约角色分三层,**全文 Read 与 grep 混排在同一回复一次发齐**(不产生额外往返;禁止的是"grep 定位后再补读"的两段式,不是 grep 本身):
|
|
60
|
-
- **契约核心(全文 Read)**:Controller、DTO/VO/QueryDTO、全局异常处理器(`*Controller`、`*DTO`、`*VO`、`*ExceptionHandler` 等,按语言现场识别)——接口契约的直接载体,必须逐字段比对
|
|
61
|
-
- **契约相关(grep 取证,不读全文)**:Service/ServiceImpl、Repository——只 grep 方法签名 + 响应构造 + 错误码,模式按语言现场定(Java `return`/`Map.of`、Python `return {`/`jsonify`、Go `c.JSON`)
|
|
62
|
-
- **无契约面(grep 确认后跳过)**:Application 启动类、`*Config`/`*Properties`、`*Util`、`BusinessException`、`*Mapper` 接口等——grep 端点声明(路由注解/路径常量)+ 业务错误码字面量,**零命中 → 结论"无契约面",不进入步骤 3 逐字段比对**;有命中 → 升级按上一条 grep 取证处理
|
|
63
|
-
- **前端**(.ts/.tsx/.vue/.js):只 grep API 调用路径 + HTTP 方法,与 spec 路径比对
|
|
64
|
-
- **coveredFiles 不受分层影响**:全部变更文件照常列入报告(硬约束 2),分层只决定"读多深",不决定"盖不盖"
|
|
65
|
-
- **例外**:契约核心文件单文件 ≥ 800 行时,先 grep 定位端点区域,再分段读相关区间
|
|
26
|
+
`--base` 优先使用 Apply 的实施前基线;首次新仓无 HEAD 时可省略,由工具选择空树。后续命令复用 prepare 保存的基线。默认读取工作区;显式检查暂存内容时加 `--scope=index`,不能把工作区内容当作暂存内容。
|
|
66
27
|
|
|
67
|
-
|
|
28
|
+
输出包括 `requiredFiles`、`inputs`、`inputFingerprint`、`preparedFile`、`reviewFile`、`reuseReview`。快照同时绑定代码、Spec、仓库身份与规则版本。指纹相同且覆盖完整时,直接复用,不删除旧报告、不重新调用模型。旧版没有输入指纹的报告需升级生成一次。
|
|
68
29
|
|
|
69
|
-
|
|
30
|
+
当前版本保守地对本仓跟踪文件及非忽略的未跟踪文件取指纹(排除生成目录、SDD 运行时),并包含本 Change 与全局规格;它不是跨仓依赖的自动发现器。检查需要其他仓的依赖时,应在该仓单独验证,并在交付摘要列出其提交。
|
|
70
31
|
|
|
71
|
-
|
|
72
|
-
> - **多 change(≥2 个)→ 必须并行**:每个 change 一个子代理,同一回复全部分派(上限 2 个,两 change 恰好一批)。**禁止**主线程逐 change 串行校验,**禁止**以"宿主并发能力不确定"为由跳过——派发在最坏情况(宿主排队串行)下也只是无收益,结果照常回收,无损害;实测多 change 串行是步骤 3 最大耗时来源(两仓各 5 分钟级推理串行叠加),并行后总耗时取单 change 最大值
|
|
73
|
-
> - **单 change → 按文件量分组**(仅适用于恰好 1 个活跃 change 的场景,不得套用到多 change 的单个 change 上):≤ 15 个文件主线程直接校验(无需子代理);> 15 个按 8-10 个/组分派子代理,逐组执行
|
|
74
|
-
> - **禁止**:主线程自己串行逐文件校验(36 文件 = 36 轮往返,是最大耗时来源);一次回复分派超过 2 个子代理(并发过高导致宿主排队 + 结果交错,实际更慢)
|
|
75
|
-
> - **派发提示必须自带分层读取规则**:子代理不读 SKILL.md,只知派发提示里写的内容——分派时必须把步骤 2b 的三层策略(契约核心全文读 / Service·Repository grep 取证 / 无契约面 grep 确认后跳过)原文写入提示。漏写则子代理退回全量读全文(实测发生:子代理全文读 ServiceImpl/Mapper/Config,上下文膨胀拖慢推理与汇总生成)
|
|
76
|
-
> - 每个子代理完成"读 spec 命中集 + 按契约角色分层读本组代码 + 步骤 3 校验",返回差异清单 + 计数,主线程汇总生成报告;公共文件只在首个归属 change 的子代理中完整校验,其余复用
|
|
32
|
+
## 2. 定向取证
|
|
77
33
|
|
|
78
|
-
|
|
34
|
+
`reuseReview=false` 时,读取 `requiredFiles` 对应的业务实现和相关 Spec。可以比较旧回执与新 `inputs` 确定变化位置,但不能把失效的旧结论直接认作本轮通过。
|
|
79
35
|
|
|
80
|
-
|
|
36
|
+
- 接口:路径、方法、请求与响应字段、错误码逐项对照。
|
|
37
|
+
- 业务规则:本次验收行为、边界条件、状态变化是否实现。
|
|
38
|
+
- 校验规则:必要的参数校验、拒绝条件是否与约定相符。
|
|
39
|
+
- 错误处理:失败路径是否满足调用方约定。
|
|
81
40
|
|
|
82
|
-
|
|
83
|
-
- **spec → code**:spec 定义的路径/方法/参数/响应字段/错误码,代码是否实现且一致
|
|
84
|
-
- **code → spec**:代码中的端点、响应字段 key、业务错误码是否已在 spec 记录(**仅枚举业务契约面**;工具方法、日志、防御性代码、DTO 转换等纯技术实现不枚举、不降级)
|
|
41
|
+
先读变更文件与对应规格,再按实际引用补读 DTO、配置、SQL 或调用方。一次批量读取独立文件;不为凑检查项全量扫描全文,也不禁止必要的依赖阅读。删除文件同样需要核对受影响的契约。
|
|
85
42
|
|
|
86
|
-
|
|
87
|
-
- 响应结构**逐字段**对比,字段名精确匹配(`token` ≠ `accessToken`);`Map.of()`/字典/结构体构造必须提取所有 key 逐一比对
|
|
88
|
-
- 每条差异定位到 `文件:行号 + spec 章节`,不贴代码原文片段
|
|
89
|
-
- 找不到证据的标 ❌/⚠️,不假设一致
|
|
43
|
+
每个结论记录 `代码路径:行号 / Spec路径:章节`。缺依据使用 `not_checked`;有实际冲突使用 `fail`;无该维度使用 `na` 并给出理由。不用 high confidence 代替事实,不把未检查维度固定写成 pass。
|
|
90
44
|
|
|
91
|
-
|
|
92
|
-
- **high**:无差异,或仅技术实现未记录
|
|
93
|
-
- **medium**:辅助性差异(非关键端点/字段缺失或不一致)
|
|
94
|
-
- **low**:关键契约不一致、spec 有关键功能代码没有、代码有业务功能 spec 没有
|
|
45
|
+
## 3. 保存真实检查结果
|
|
95
46
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
结论确定后直接写文件,**禁止**重新核对证据或推演差异。md + json 在**同一回复并行写入**(多 change 的全部报告同批写)。**禁止任何计时打点**(步骤起止时长、执行统计、额外的 `now` 调用)——报告 `generatedAt` 已由步骤 2c 的 prepare-report 输出,流程内不需要其他时间戳;执行时长统计只在用户显式要求时做,默认不做。
|
|
99
|
-
|
|
100
|
-
**JSON**(`consistency-report-result.json`,hook 唯一消费源,schema 固定):
|
|
47
|
+
把检查结果写到 `preparedFile` 同目录的 `review-input.json`,避免临时结果进入代码快照。`inputFingerprint` 原样复制,`reviewedFiles` 只列实际检查过的文件,至少覆盖本次 `requiredFiles`。
|
|
101
48
|
|
|
102
49
|
```json
|
|
103
50
|
{
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"generatedAt": "<YYYY-MM-DD HH:mm:ss 本地时间>",
|
|
107
|
-
"repositories": [
|
|
108
|
-
{ "path": "<代码仓名>" }
|
|
109
|
-
],
|
|
110
|
-
"coveredFiles": [
|
|
111
|
-
{ "path": "<工作区相对路径>", "size": 2341, "sha256": "<64位十六进制>" }
|
|
112
|
-
],
|
|
51
|
+
"inputFingerprint": "<prepare 输出>",
|
|
52
|
+
"reviewedFiles": ["src/order.js"],
|
|
113
53
|
"dimensions": {
|
|
114
|
-
"interfaceContract": {
|
|
115
|
-
"businessRules": {
|
|
116
|
-
"validationRules": {
|
|
117
|
-
"errorCodes": {
|
|
54
|
+
"interfaceContract": {"status": "pass", "evidence": ["src/order.js:12 / spec.md §接口"]},
|
|
55
|
+
"businessRules": {"status": "pass", "evidence": ["src/order.js:28 / spec.md §金额边界"]},
|
|
56
|
+
"validationRules": {"status": "not_checked", "evidence": []},
|
|
57
|
+
"errorCodes": {"status": "na", "reason": "纯计算函数,本次无错误码协议"}
|
|
118
58
|
},
|
|
119
|
-
"
|
|
120
|
-
"totalChecks": 0, "passed": 0, "failed": 0, "warnings": 0,
|
|
121
|
-
"undocumentedBusiness": 0, "undocumentedTechnical": 0, "specMissing": 0, "inconsistent": 0
|
|
122
|
-
}
|
|
59
|
+
"issues": []
|
|
123
60
|
}
|
|
124
61
|
```
|
|
125
62
|
|
|
126
|
-
`
|
|
127
|
-
|
|
128
|
-
**MD**(`consistency-report.md`,极简,禁止凑数空章节):
|
|
129
|
-
|
|
130
|
-
```markdown
|
|
131
|
-
# Spec 一致性校验报告
|
|
132
|
-
|
|
133
|
-
**变更**:<change-name> **生成时间**:<YYYY-MM-DD HH:mm:ss>
|
|
134
|
-
**校验范围**:<N 个文件> **置信度**:<high/medium/low>
|
|
63
|
+
只有无业务代码变化且四个维度都有理由判为 `na` 的文档或非实施变更,才可在回执中追加 `tests: {"status":"na","reason":"具体不适用理由"}`;工具显示测试不适用,不能说测试已通过。
|
|
135
64
|
|
|
136
|
-
|
|
65
|
+
该例包含未检查项,不能通过交付验证。依据实际取证补完,不能只改状态。
|
|
137
66
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<有差异时列下表:>
|
|
141
|
-
|
|
142
|
-
| # | 类型 | 风险 | 位置 | 描述 | 建议 |
|
|
143
|
-
|---|------|------|------|------|------|
|
|
144
|
-
| 1 | 不一致 | P0 | File.java:42 / spec §2.1 | <差异描述> | <改代码或改 spec> |
|
|
67
|
+
```bash
|
|
68
|
+
node "<spec-root>/skywalk-sdd/git-hooks/delivery-check.cjs" record-review --project="<代码仓>" --change=<change> --input="<review-input.json>"
|
|
145
69
|
```
|
|
146
70
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
---
|
|
71
|
+
工具重算指纹,输入变化时拒绝旧结论。失败或未检查的结果仍会保存并返回非零退出码,便于修复后复核;成功回执写到输出 `reviewFile`,由脚本管理哈希,不手填。回执是 Agent 的可追溯检查记录,不是对业务正确性的数学证明。
|
|
150
72
|
|
|
151
|
-
##
|
|
73
|
+
## 4. 返回实施收尾
|
|
152
74
|
|
|
153
|
-
|
|
75
|
+
报告发现的问题、检查范围与未检查部分。由 Apply 在同一轮继续执行真实测试及 `delivery-check verify`;本技能通过只表示检查回执有效,不表示测试、知识库入库或正式交付已经完成。
|
|
@@ -439,21 +439,8 @@ function prepareReport(changeDir) {
|
|
|
439
439
|
const specRoot = resolveSpecRoot();
|
|
440
440
|
if (specRoot) dir = path.resolve(specRoot, changeDir);
|
|
441
441
|
}
|
|
442
|
-
//
|
|
443
|
-
const reportFiles = ['consistency-report.md', 'consistency-report-result.json'];
|
|
442
|
+
// Keep previous evidence for comparison/reuse. Explicit clean-reports remains available.
|
|
444
443
|
const cleaned = [];
|
|
445
|
-
for (const f of reportFiles) {
|
|
446
|
-
const fp = path.join(dir, f);
|
|
447
|
-
try {
|
|
448
|
-
if (fs.existsSync(fp)) {
|
|
449
|
-
fs.unlinkSync(fp);
|
|
450
|
-
cleaned.push(fp.replace(/\\/g, '/'));
|
|
451
|
-
}
|
|
452
|
-
} catch (e) {
|
|
453
|
-
console.error('ERROR: failed to delete ' + fp + ': ' + e.message);
|
|
454
|
-
process.exit(1);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
444
|
// 2. 批量哈希(可选):仅当显式提供 --files-from=/--files= 时执行,绝不读 stdin(防交互式终端挂起)。
|
|
458
445
|
// 无输入源 = "只清理 + 取时间戳"合法模式(哈希已由 --collect --hash 提供时无需重复传入),hashes 输出空数组
|
|
459
446
|
const hashes = [];
|