kld-sdd 2.6.7 → 2.6.9

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 (39) hide show
  1. package/bin/kld-sdd-init.js +39 -3
  2. package/lib/init.js +320 -45
  3. package/lib/workspace-layout.js +2 -0
  4. package/package.json +2 -2
  5. package/skywalk-sdd/context-client.cjs +59 -5
  6. package/skywalk-sdd/ontology/active-changes.cjs +297 -0
  7. package/skywalk-sdd/ontology/change-key.cjs +241 -0
  8. package/skywalk-sdd/ontology/cli.cjs +135 -0
  9. package/skywalk-sdd/ontology/list-changes.cjs +110 -0
  10. package/skywalk-sdd/ontology/modules.cjs +167 -0
  11. package/skywalk-sdd/ontology/naming-diagnose.cjs +594 -0
  12. package/skywalk-sdd/ontology/sdd-config.cjs +335 -0
  13. package/skywalk-sdd/ontology/workspace-layout.cjs +194 -0
  14. package/templates/dot-sdd.yaml +8 -0
  15. package/templates/git-hooks/commit-msg-sdd-trailer.cjs +224 -0
  16. package/templates/modules.yaml +13 -0
  17. package/templates/openspec/proposal.md +7 -1
  18. package/templates/sdd.config.yaml +12 -0
  19. package/templates/skills/kld-sdd/openspec-sync-specs/SKILL.md +148 -0
  20. package/templates/skills/kld-sdd/openspec-update-change/SKILL.md +86 -0
  21. package/templates/skills/kld-sdd/opsx-apply/SKILL.md +3 -3
  22. package/templates/skills/kld-sdd/opsx-apply/checklist.md +1 -1
  23. package/templates/skills/kld-sdd/opsx-archive/SKILL.md +11 -1
  24. package/templates/skills/kld-sdd/opsx-check/SKILL.md +73 -3
  25. package/templates/skills/kld-sdd/opsx-design/SKILL.md +9 -0
  26. package/templates/skills/kld-sdd/opsx-explore/SKILL.md +37 -17
  27. package/templates/skills/kld-sdd/opsx-kb-ingest/SKILL.md +9 -14
  28. package/templates/skills/kld-sdd/opsx-ontology-query/SKILL.md +83 -109
  29. package/templates/skills/kld-sdd/opsx-ontology-query/phase-1-prechange.md +276 -0
  30. package/templates/skills/kld-sdd/opsx-ontology-query/phase-2-during.md +354 -0
  31. package/templates/skills/kld-sdd/opsx-ontology-query/phase-3-postchange.md +223 -0
  32. package/templates/skills/kld-sdd/opsx-ontology-query/phase-4-explore.md +240 -0
  33. package/templates/skills/kld-sdd/opsx-ontology-query/phase-5-governance.md +232 -0
  34. package/templates/skills/kld-sdd/opsx-ontology-query/reference.md +92 -4
  35. package/templates/skills/kld-sdd/opsx-propose/SKILL.md +87 -16
  36. package/templates/skills/kld-sdd/opsx-propose/checklist.md +1 -0
  37. package/templates/skills/kld-sdd/opsx-spec/SKILL.md +33 -3
  38. package/templates/skills/kld-sdd/opsx-task/SKILL.md +10 -0
  39. package/templates/skills/kld-sdd/opsx-tdd-core/checklist.md +1 -1
@@ -0,0 +1,276 @@
1
+ # Phase 1 · 变更前评估(Pre-change Assessment)
2
+
3
+ > **触发时机**:opsx-propose 创建变更前 / opsx-spec 生成规格前
4
+ > **加载方式**:SDD skill 在对应阶段 `Read` 本文件
5
+ > **前置条件**:`.local/state.json` 已完成 Session 启动(apiKey + targets 就绪)
6
+ >
7
+ > ⚠️ **数据边界**:当前变更尚未入库,KB 中只有历史变更数据。
8
+ > 本阶段 KB 查询的目的:**用历史上下文辅助当前变更的决策**(身份决议、影响预评、历史 AC 查询、Spec 复用)。
9
+ > KB 返回的是上一次入库的状态,不是当前变更的状态。
10
+
11
+ ---
12
+
13
+ ## §1 需求连续性检查(Continuity)
14
+
15
+ > **已有集成**:opsx-propose §6.5 已调用。此处为完整参考。
16
+
17
+ ### 场景
18
+
19
+ 判断新需求是全新需求还是历史需求的延续,确定是否可继承历史 UUID。
20
+
21
+ ### API
22
+
23
+ ```
24
+ POST {base}/entities/resolve
25
+ ```
26
+
27
+ ### 请求
28
+
29
+ ```json
30
+ {
31
+ "externalSystem": "requirement-mgmt",
32
+ "externalObjectType": "requirement",
33
+ "externalId": "REQ-FI-2024-001",
34
+ "entityType": "Capability"
35
+ }
36
+ ```
37
+
38
+ > **编号文法**:`externalId` 必须符合 `REQ-{DOMAIN}-{YEAR}-{SEQ}` 格式(如 `REQ-FI-2024-001`)。
39
+ > 查询前先归一化:trim → REQ/FEAT 段大写。完整文法见 `SKILL.md` → 编号文法速查。
40
+
41
+ ### 决策逻辑
42
+
43
+ | 响应字段 | 值 | 含义 | SDD 动作 |
44
+ |----------|-----|------|----------|
45
+ | `resolution` | `LINK_EXISTING` | 命中可继承绑定 | `inheritanceAllowed=true` → 复用 entity-id,写 `delta-state=modified` |
46
+ | `removedBindingCount` | > 0 | 存在历史失效绑定 | 仅提示,不影响 inheritance 判定 |
47
+ | `matchType` | `HISTORICAL_ONLY` | 仅有失效绑定,`inheritanceAllowed=false` | 不可继承,新开身份 |
48
+ | `resolution` | `CREATE_NEW` | 无匹配 | 全新需求,`delta-state=added` |
49
+ | — | `SIMILAR_REQUIREMENT` | 名称/结构相似 | 仅候选,需人确认 |
50
+ | — | `NEEDS_CONFIRM` | 需人确认 | ask_user A/B/C |
51
+
52
+ ### 按功能号圈能力(FEAT scoping)
53
+
54
+ 同一 `/entities/resolve` 接口,`externalObjectType:"feature"` 可查询某 FEAT 下已有能力清单,辅助 propose 阶段勾选本次 CAP 范围:
55
+
56
+ ```json
57
+ {
58
+ "externalSystem": "requirement-mgmt",
59
+ "externalObjectType": "feature",
60
+ "externalId": "FEAT-FI-012",
61
+ "entityType": "Capability"
62
+ }
63
+ ```
64
+
65
+ 响应 `candidates` 列出存活/失效能力,`removedBindingCount` 为已失效绑定数。
66
+ > 此查询只作范围参考,不改变 Continuity 判定优先级。
67
+
68
+ ### 集成点
69
+
70
+ - opsx-propose §6.5:写入 proposal frontmatter `continuity` 字段
71
+ - 禁止扫本地 `archive/` 抄 UUID(KB 可用时);KB degraded 时 archive 作为降级手段,标注 `source: archive(degraded)`
72
+
73
+ > **Agent 行为指导**:响应中的 `clarificationQuestions` 是 AI 生成的澄清问题,Agent 应直接用 `ask_user` 呈现给用户,不要自行回答。
74
+ > `supportEvidence` / `oppositionEvidence` 可作为决策依据向用户展示。
75
+
76
+ ---
77
+
78
+ ## §2 影响范围分析(Impact Analysis)
79
+
80
+ > **新增场景**:opsx-propose 在能力分解前评估修改影响。
81
+
82
+ ### 场景
83
+
84
+ 用户要修改某个 Capability 或 STMT,需知道波及哪些下游实体(AC/DES/TASK)。
85
+
86
+ ### API(一跳结构)
87
+
88
+ ```
89
+ GET {base}/entities/{entityId}/ontology-view
90
+ ```
91
+
92
+ ### API(多跳影响)
93
+
94
+ ```
95
+ GET {base}/entities/{entityId}/impact
96
+ ```
97
+
98
+ ### 示例
99
+
100
+ 查询 CAP-USER-LOGIN(e89287e8)的影响:
101
+
102
+ ```bash
103
+ curl -sS -H "Authorization: Bearer $API_KEY" \
104
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/e89287e8-0000-0000-0000-000000000000/impact"
105
+ ```
106
+
107
+ ### 响应解读
108
+
109
+ - `anchorEntityId`:锚点实体 ID
110
+ - `maxDepth`:最大影响深度(≤4 跳)
111
+ - `nodes`:受影响实体列表(含 entityId / entityType / displayName / depth)
112
+ - `edges`:影响路径(fromEntityId → toEntityId / relationType)
113
+
114
+ ### 决策逻辑
115
+
116
+ | 影响范围 | 风险等级 | 建议 |
117
+ |----------|----------|------|
118
+ | 仅 1 跳(直接子节点) | 低 | 正常进行 |
119
+ | 2 跳(STMT → AC/DES) | 中 | 确认受影响 AC 是否需要修改 |
120
+ | 3-4 跳(到 TASK) | 高 | 先与用户确认影响范围再继续 |
121
+
122
+ ### 集成点
123
+
124
+ - opsx-propose §3(能力分解):在列出 modified Capability 前,查询影响范围写入 proposal §4 影响范围
125
+ - opsx-propose §6.5:Continuity 结果结合影响范围,判断 iteration vs new
126
+
127
+ ---
128
+
129
+ ## §3 历史覆盖场景查询(Historical AC Coverage)
130
+
131
+ > **新增场景**:opsx-spec 生成规格前,查询当前 STMT 已有哪些 AC。
132
+
133
+ ### 场景
134
+
135
+ 为已有 STMT 追加新场景时,需知道历史 AC 列表,避免遗漏或重复。
136
+
137
+ ### API
138
+
139
+ ```
140
+ GET {base}/entities/{stmtEntityId}/ontology-view
141
+ ```
142
+
143
+ ### 示例
144
+
145
+ 查询 STMT-USER-LOGIN-001(89bbf6a6)的 AC 列表:
146
+
147
+ ```bash
148
+ curl -sS -H "Authorization: Bearer $API_KEY" \
149
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/89bbf6a6-0000-0000-0000-000000000000/ontology-view"
150
+ ```
151
+
152
+ ### 响应解读
153
+
154
+ 从 `relations` 数组提取 `relationType=verifiedBy && direction=outbound` 的邻居:
155
+
156
+ ```json
157
+ {
158
+ "relationType": "verifiedBy",
159
+ "direction": "outbound",
160
+ "neighbor": {
161
+ "entityId": "c9f6a0e8-0000-0000-0000-000000000000",
162
+ "canonicalKey": "AC-USER-LOGIN-001",
163
+ "displayName": "正确凭证登录成功",
164
+ "changeId": "CHG-ADD-USER-LOGIN"
165
+ }
166
+ }
167
+ ```
168
+
169
+ ### 决策逻辑
170
+
171
+ > ⚠️ **数据边界**:KB 中只有已入库的历史变更数据。当前变更的 AC 尚未入库,不会出现在查询结果中。以下决策基于"KB 返回的全部是历史 AC"这一前提。
172
+
173
+ | 发现 | 含义 | SDD 动作 |
174
+ |------|------|----------|
175
+ | AC 来自旧变更(changeId ≠ 当前) | 历史保留场景 | 新场景编号从 `max+1` 开始,不重复;SCN 格式 `:SCN-{slug}-{NNN}`(见 `SKILL.md` → 编号文法速查) |
176
+ | 无 AC | 全新 STMT 或历史无场景 | 正常创建首个 AC |
177
+ | AC 的 statement_id 指向当前 STMT | 关系正确 | 确认新 AC 也写 statement_id |
178
+ | STMT 在 KB 中不存在 | 全新 STMT(added) | 无历史 AC 可查,直接创建 |
179
+
180
+ ### 关键机制
181
+
182
+ - `verifiedBy` 是 inferred 关系(rule_id=nested-acceptance-scenario),由 AC 的 `statement_id` 属性推导
183
+ - 历史 AC 未被修改时,其 v1 仍是 current,关系自动保留
184
+ - ontology-view 只显示每个实体的 current version
185
+
186
+ ### 集成点
187
+
188
+ - opsx-spec §3:在 match-requirement 之后,对 modified STMT 查询历史 AC
189
+ - opsx-spec §6:生成新 AC 时确认编号不与历史冲突
190
+
191
+ ---
192
+
193
+ ## §4 Spec 复用评估(Spec Reuse)
194
+
195
+ > **已有集成**:opsx-spec §3 已调用。此处为完整参考。
196
+
197
+ ### 场景
198
+
199
+ 查找是否有可复用的历史规格(statements / ACs / constraints / designElements / tasks)。
200
+
201
+ ### API
202
+
203
+ ```
204
+ POST {base}/context/match-requirement
205
+ ```
206
+
207
+ ### 请求
208
+
209
+ ```json
210
+ {
211
+ "query": "用户登录认证",
212
+ "targetStage": "spec",
213
+ "entityId": "e89287e8-0000-0000-0000-000000000000",
214
+ "externalSystem": "requirement-mgmt",
215
+ "externalObjectType": "requirement",
216
+ "externalId": "REQ-FI-2024-001"
217
+ }
218
+ ```
219
+
220
+ ### 决策逻辑
221
+
222
+ | `reuseMode` | 含义 | SDD 动作 |
223
+ |-------------|------|----------|
224
+ | `INHERIT` | 确定性命中,可继承 UUID | unchanged 写继承引用;modified 复用 entity-id + predecessor |
225
+ | `REFERENCE` | 仅候选,不能自动复用 | 只参考内容,新开身份 |
226
+ | — | 无命中 | 全新建 |
227
+
228
+ ### 响应消费
229
+
230
+ - `reuseBundles[].statements` → 优先消费,写入 spec 的 STMT
231
+ - `reuseBundles[].acceptanceCriteria` → 参考场景定义
232
+ - `reuseBundles[].designElements` → 仅理解上下文,不能写成 Spec 的 How
233
+ - 实体上的 `externalRefs` → 写入场景 `external-ref`
234
+
235
+ ### 集成点
236
+
237
+ - opsx-spec §3:Continuity=iteration 时必须带 `entityId` + external
238
+ - 禁止从本地 `archive/` 抄 UUID 当跨迭代继承源(KB 可用时);KB degraded 时 archive 作为降级手段,标注 `source: archive(degraded)`
239
+
240
+ > **Agent 行为指导**:消费 `specGenerationContext` 判断复用率——`reusableStatements` > 50% 走迭代修改,< 20% 走全新建。
241
+ > `warnings` 和 `clarificationQuestions` 应呈现给用户,不要忽略。
242
+
243
+ ---
244
+
245
+ ## §5 约束冲突检测(Constraint Conflict)
246
+
247
+ > **新增场景**:opsx-spec 新增 Constraint 时检查冲突。
248
+
249
+ ### 场景
250
+
251
+ 新增约束时,检查 KB 中是否已有语义矛盾的约束。
252
+
253
+ ### API
254
+
255
+ ```
256
+ POST {base}/context/search
257
+ ```
258
+
259
+ ### 请求
260
+
261
+ ```json
262
+ {
263
+ "query": "密码最小长度限制",
264
+ "entityTypes": ["Constraint"],
265
+ "limit": 10
266
+ }
267
+ ```
268
+
269
+ ### 决策逻辑
270
+
271
+ - 返回结果中若存在与新增约束语义矛盾的 Constraint → 标记 warning,提示用户确认
272
+ - 无冲突或无命中 → 正常创建
273
+
274
+ ### 集成点
275
+
276
+ - opsx-spec §6:创建 CON-* 前可选调用
@@ -0,0 +1,354 @@
1
+ # Phase 2 · 变更中辅助(During-change Assistance)
2
+
3
+ > **触发时机**:opsx-design / opsx-task / opsx-check 阶段
4
+ > **加载方式**:SDD skill 在对应阶段 `Read` 本文件
5
+ > **前置条件**:`.local/state.json` 已完成 Session 启动
6
+ >
7
+ > ⚠️ **数据边界**:当前变更尚未入库(Archive → kb-ingest 之前),KB 中只有历史变更数据。
8
+ > 本阶段所有 KB 查询都是查**历史上下文**,用于辅助决策,不能用于验证当前变更的内部一致性。
9
+ > 当前变更的内部一致性由**本地文件 + semantic-check** 保证。
10
+
11
+ ---
12
+
13
+ ## §1 历史设计参考(Historical Design Reference)
14
+
15
+ > **新增场景**:opsx-design 创建 DES 前,查询历史设计作为参考。
16
+
17
+ ### 场景
18
+
19
+ 设计阶段,为当前变更的 DesignElement 查找历史设计模式、已有实现关系,辅助新设计决策。
20
+
21
+ > ⚠️ **不能用于验证当前变更的 DES**:当前变更的 DES 尚未入库,`ontology-view` 只返回历史版本。
22
+ > - 如果 DES 是 `added`(新增)→ KB 中不存在此实体
23
+ > - 如果 DES 是 `modified`(修改)→ KB 返回的是**旧版本**的 realizes 关系,不是当前变更的
24
+ > - 当前变更的 DES realizes 关系应从**本地 design.md** 验证
25
+
26
+ ### API(查询历史 DES 的关系结构)
27
+
28
+ ```
29
+ GET {base}/entities/{historicalDesEntityId}/ontology-view
30
+ ```
31
+
32
+ ### 示例
33
+
34
+ 查询历史 DES-USER-LOGIN-001(a5e8b950)的一跳结构作为参考:
35
+
36
+ ```bash
37
+ curl -sS -H "Authorization: Bearer $API_KEY" \
38
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/a5e8b950-0000-0000-0000-000000000000/ontology-view"
39
+ ```
40
+
41
+ ### 响应解读
42
+
43
+ 从 `relations` 检查 `relationType=realizes && direction=outbound`:
44
+
45
+ ```json
46
+ {
47
+ "relationType": "realizes",
48
+ "direction": "outbound",
49
+ "neighbor": {
50
+ "canonicalKey": "STMT-USER-LOGIN-001",
51
+ "entityId": "89bbf6a6-0000-0000-0000-000000000000"
52
+ }
53
+ }
54
+ ```
55
+
56
+ ### 决策逻辑
57
+
58
+ | 查询目的 | KB 返回 | SDD 动作 |
59
+ |----------|---------|----------|
60
+ | 了解历史 DES realizes 哪个 STMT | 历史版本关系 | 参考历史模式,新 DES 的 realizes 引用对齐 |
61
+ | 查找类似设计 | context/search DesignElement | 仅参考,不能直接复用 UUID(除非 INHERIT) |
62
+ | 确认上游 STMT 是否存在 | STMT 在 KB 中为 current | 确认 STMT entity-id 可继承 |
63
+
64
+ ### 设计复用检索
65
+
66
+ 用语义搜索查找历史类似设计:
67
+
68
+ ```json
69
+ {
70
+ "query": "用户凭证存储与密码验证",
71
+ "entityTypes": ["DesignElement"],
72
+ "limit": 10
73
+ }
74
+ ```
75
+
76
+ 返回的历史 DesignElement 仅作参考,不可直接复用 UUID(除非 INHERIT)。
77
+
78
+ ### 集成点
79
+
80
+ - opsx-design §5:代码锚点分析后,查 KB 了解历史设计模式
81
+ - opsx-design §6:创建 DES 时参考历史 realizes 引用格式
82
+ - ⚠️ 当前变更 DES 的 realizes 验证 → 走本地 design.md + semantic-check
83
+
84
+ ---
85
+
86
+ ## §2 历史任务追溯参考(Historical Task Traceability)
87
+
88
+ > **新增场景**:opsx-task 创建 TASK 前,查询历史任务关系作为参考。
89
+
90
+ ### 场景
91
+
92
+ 任务拆解时,查询历史 TASK 的关系结构(covers/implements/verifies),辅助新任务的追溯设计。
93
+
94
+ > ⚠️ **不能用于验证当前变更的 TASK**:当前变更的 TASK 尚未入库。
95
+ > - 如果 TASK 是 `added` → KB 中不存在
96
+ > - 如果 TASK 是 `modified` → KB 返回旧版本关系
97
+ > - 当前变更 TASK 的 covers/implements 应从**本地 tasks.md** 验证
98
+
99
+ ### API(查询历史 TASK 的关系结构)
100
+
101
+ ```
102
+ GET {base}/entities/{historicalTaskEntityId}/ontology-view
103
+ ```
104
+
105
+ ### 示例
106
+
107
+ 查询历史 TASK-USER-LOGIN-003(f5446144)的一跳结构作为参考:
108
+
109
+ ```bash
110
+ curl -sS -H "Authorization: Bearer $API_KEY" \
111
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/f5446144-0000-0000-0000-000000000000/ontology-view"
112
+ ```
113
+
114
+ ### 响应解读
115
+
116
+ 检查 `relations` 中的关系类型:
117
+
118
+ | relationType | direction | 含义 |
119
+ |--------------|-----------|------|
120
+ | `implements` | outbound → DES | 历史任务实现了某设计元素 |
121
+ | `covers` | outbound → STMT | 历史任务覆盖了某规格声明 |
122
+ | `verifies` | outbound → AC | 历史任务验证了某验收场景 |
123
+ | `dependsOn` | outbound → TASK | 历史任务依赖另一任务 |
124
+
125
+ ### 决策逻辑
126
+
127
+ | 查询目的 | KB 返回 | SDD 动作 |
128
+ |----------|---------|----------|
129
+ | 了解历史 TASK 的追溯模式 | 历史版本关系 | 参考模式设计新 TASK 的 covers/implements |
130
+ | 确认上游 STMT/DES 是否存在 | 实体在 KB 中为 current | 确认 entity-id 可继承 |
131
+ | 检查历史 TASK 依赖链 | dependsOn 关系 | 参考依赖模式,避免循环 |
132
+
133
+ ### 集成点
134
+
135
+ - opsx-task §7:创建 TASK 后参考历史追溯模式
136
+ - opsx-task §8:质量自检时参考历史关系格式
137
+ - ⚠️ 当前变更 TASK 的 covers/implements 验证 → 走本地 tasks.md + semantic-check
138
+
139
+ ---
140
+
141
+ ## §3 历史覆盖率基线(Historical Coverage Baseline)
142
+
143
+ > **新增场景**:opsx-check 阶段,查 KB 覆盖率了解**入库前**的基线状态。
144
+
145
+ ### 场景
146
+
147
+ 检查 KB 中已入库规格的覆盖完整性,识别**历史遗留**的覆盖率缺口。
148
+
149
+ > ⚠️ **数据边界**:KB coverage 只反映**已入库变更**的覆盖率,不含当前变更。
150
+ > - 当前变更的覆盖率由**本地 semantic-check** 负责(主权威)
151
+ > - KB coverage 的价值在于:发现历史遗留缺口,判断当前变更是否应该顺手修复
152
+ > - 如果当前变更修改了某个有缺口的 STMT,可以顺手补 AC
153
+
154
+ ### API
155
+
156
+ ```
157
+ GET {base}/coverage
158
+ ```
159
+
160
+ > 注:coverage 是 KB 级别 API,路径含 kbId。
161
+
162
+ ### 示例
163
+
164
+ ```bash
165
+ curl -sS -H "Authorization: Bearer $API_KEY" \
166
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/coverage"
167
+ ```
168
+
169
+ ### 响应解读
170
+
171
+ ```json
172
+ {
173
+ "gaps": [
174
+ {
175
+ "entityId": "xxx-0000-0000-0000-000000000000",
176
+ "entityType": "SpecificationStatement",
177
+ "displayName": "某规格声明",
178
+ "gapType": "missing_acceptance_criterion"
179
+ }
180
+ ]
181
+ }
182
+ ```
183
+
184
+ ### gapType 分类
185
+
186
+ | gapType | entityType | 含义 | 严重度 |
187
+ |---------|------------|------|--------|
188
+ | `missing_acceptance_criterion` | SpecificationStatement | STMT 缺少 AC | ❌ 阻断 |
189
+ | `missing_specification_statement` | DesignElement | DES 缺少 realizes | ❌ 阻断 |
190
+ | `missing_upstream_trace` | Task | TASK 缺少 covers/implements | ⚠️ 警告 |
191
+
192
+ ### 决策逻辑
193
+
194
+ | 检查结果 | 含义 | SDD 动作 |
195
+ |----------|------|----------|
196
+ | gaps 为空 | 历史全覆盖 | 当前变更只需保证自身覆盖率(本地 semantic-check) |
197
+ | 有 gap 且 gap 实体在当前变更范围内 | 历史遗留 + 当前变更涉及 | 顺手修复:在当前变更中补 AC/realizes |
198
+ | 有 gap 但 gap 实体不在当前变更范围 | 纯历史遗留 | 记录为技术债,不阻塞当前变更 |
199
+ | 当前变更自身覆盖率 | **不查 KB** | 走本地 semantic-check(主权威) |
200
+
201
+ ### 集成点
202
+
203
+ - opsx-check §4:KB 覆盖率作为**历史基线**参考,不作为当前变更的覆盖率权威
204
+ - opsx-check §4.2:本地 semantic-check 是当前变更覆盖率的主权威
205
+ - 禁止用 KB coverage 的 gap 来阻断当前变更(除非 gap 实体在变更范围内)
206
+
207
+ ---
208
+
209
+ ## §4 历史变更统计(Historical Change Inventory)
210
+
211
+ > **新增场景**:opsx-check / opsx-explore 查询 KB 中的**历史**变更统计。
212
+
213
+ ### 场景
214
+
215
+ 查看 KB 中已入库的变更列表和统计,了解迭代历史和变更模式。
216
+
217
+ > ⚠️ **数据边界**:KB changes 只含**已入库**的变更。当前变更不在列表中(直到 Archive → kb-ingest)。
218
+ > - 查历史变更趋势 → KB changes ✅
219
+ > - 查当前变更状态 → 本地 `openspec/changes/{change-id}/` ✅
220
+
221
+ ### API
222
+
223
+ ```
224
+ GET {base}/changes
225
+ GET {base}/changes/{changeId}
226
+ ```
227
+
228
+ ### 示例
229
+
230
+ ```bash
231
+ # 列出所有已入库变更
232
+ curl -sS -H "Authorization: Bearer $API_KEY" \
233
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/changes"
234
+
235
+ # 查看特定历史变更详情
236
+ curl -sS -H "Authorization: Bearer $API_KEY" \
237
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/changes/CHG-ADD-USER-LOGIN"
238
+ ```
239
+
240
+ ### 响应解读
241
+
242
+ 变更列表(`GET /changes`)每项字段(camelCase):
243
+
244
+ ```json
245
+ {
246
+ "changeId": "CHG-ADD-USER-LOGIN",
247
+ "title": "CHG-ADD-USER-LOGIN",
248
+ "status": "confirmed",
249
+ "createdAt": "2026-07-23T06:09:46.219924Z",
250
+ "updatedAt": "2026-07-23T06:09:46.219924Z",
251
+ "archiveId": "urn:kld:sdd:archive:...",
252
+ "producer": "kld-sdd@1.0.0",
253
+ "schemaVersion": "kld-sdd-canonical-facts/v2",
254
+ "contentHash": "sha256:...",
255
+ "versionCount": 85,
256
+ "addedCount": 85,
257
+ "modifiedCount": 0,
258
+ "removedCount": 0,
259
+ "unchangedCount": 0
260
+ }
261
+ ```
262
+
263
+ > 注:`title` 当前等于 `changeId`,非人类可读标题。
264
+
265
+ 变更详情(`GET /changes/{changeId}`)为嵌套结构:
266
+
267
+ ```json
268
+ {
269
+ "metadata": {
270
+ "change_id": "CHG-ADD-USER-LOGIN",
271
+ "title": "CHG-ADD-USER-LOGIN",
272
+ "status": "confirmed",
273
+ "updated_at": "2026-07-23T06:09:46.219924Z",
274
+ "snapshot_id": "uuid",
275
+ "archive_id": "urn:kld:sdd:archive:...",
276
+ "producer": "kld-sdd@1.0.0",
277
+ "schema_version": "kld-sdd-canonical-facts/v2",
278
+ "content_hash": "sha256:...",
279
+ "archive_created_at": "2026-07-23T06:09:31.919Z"
280
+ },
281
+ "entityVersions": [
282
+ { "entityId": "...", "entityType": "Capability", "deltaState": "added", "..." : "..." }
283
+ ]
284
+ }
285
+ ```
286
+
287
+ > ⚠️ `metadata` 内字段为 snake_case,`entityVersions` 内为 camelCase(Java record 序列化)。
288
+ ```
289
+
290
+ ### 决策逻辑
291
+
292
+ | 查询目的 | KB 返回 | SDD 动作 |
293
+ |----------|---------|----------|
294
+ | 了解历史变更频率和类型分布 | 已入库变更列表 | 评估迭代节奏 |
295
+ | 确认上次入库的变更 ID | 最近一次 confirmed 变更 | 作为 predecessor 参考上下文 |
296
+ | 查当前变更状态 | **不查 KB** | 看本地 `openspec/changes/{change-id}/` |
297
+
298
+ ### 集成点
299
+
300
+ - opsx-check:参考历史变更统计,不作为当前变更的权威
301
+ - opsx-explore:展示 KB 中的历史变更概览
302
+
303
+ ---
304
+
305
+ ## §5 入库前一致性预检(Pre-archive Consistency Check)
306
+
307
+ > **新增场景**:opsx-check / opsx-archive 在打包归档前,验证 predecessor version 是否与 KB 当前版本匹配。
308
+
309
+ ### 场景
310
+
311
+ Archive 打包前,对每个 `modified` 实体验证:本地声明的 `predecessor-version-id` 是否等于 KB 中该实体的 `current-version`。如果不匹配,入库时会触发 `VERSION_CONFLICT`,整包回滚。
312
+
313
+ > 这是**预防性检查**,在入库前发现问题,避免入库后失败再返工。
314
+
315
+ ### API
316
+
317
+ ```
318
+ GET {base}/entities/{entityId}/current-version
319
+ ```
320
+
321
+ ### 示例
322
+
323
+ 验证 CAP-USER-LOGIN 的当前版本(入库前预检):
324
+
325
+ ```bash
326
+ curl -sS -H "Authorization: Bearer $API_KEY" \
327
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/e89287e8-0000-0000-0000-000000000000/current-version"
328
+ ```
329
+
330
+ ### 验证步骤
331
+
332
+ 1. 从本地 proposal.md / spec.md 中提取每个 modified 实体的 `entity-id` 和 `predecessor-version-id`
333
+ 2. 对每个 modified 实体调用 `current-version` API
334
+ 3. 对比:
335
+
336
+ | 本地声明 | KB 返回 | 结果 |
337
+ |----------|---------|------|
338
+ | `predecessor-version-id` == KB `entityVersionId` | ✅ 一致 | 可安全入库 |
339
+ | `predecessor-version-id` ≠ KB `entityVersionId` | ❌ 不一致 | 有其他变更已入库,需更新 predecessor |
340
+ | KB 中无此实体(404) | entity 是 added | 确认 delta-state=added,无需 predecessor |
341
+
342
+ ### 决策逻辑
343
+
344
+ | 检查结果 | 状态 | 动作 |
345
+ |----------|------|------|
346
+ | 所有 modified 实体的 predecessor 匹配 | ✅ 可入库 | 继续 Archive → kb-ingest |
347
+ | 某 modified 实体 predecessor 不匹配 | ❌ 冲突 | 回 spec 获取 KB 最新 version-id,更新 predecessor,重新打包 |
348
+ | 某 modified 实体在 KB 中不存在 | ⚠️ 异常 | 检查 delta-state 应为 added 而非 modified |
349
+
350
+ ### 集成点
351
+
352
+ - opsx-check §4:一致性检查中加入 KB predecessor 预检
353
+ - opsx-archive §4:打包前自动预检,失败则阻断打包
354
+ - opsx-archive §5.5:入库后用 Phase 3 验证(双重保障)