kld-sdd 2.6.8 → 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.
@@ -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 验证(双重保障)
@@ -0,0 +1,223 @@
1
+ # Phase 3 · 变更后验证(Post-change Verification)
2
+
3
+ > **触发时机**:opsx-archive 完成 KB 入库后
4
+ > **加载方式**:opsx-archive §5.5 入库成功后 `Read` 本文件执行验证
5
+ > **前置条件**:archive zip 已成功上传到 KB,job 状态为 succeeded
6
+ >
7
+ > ✅ **数据边界**:这是 SDD 流程中**唯一**能从 KB 查到当前变更数据的阶段。
8
+ > Archive → kb-ingest 完成后,当前变更的实体已入库并成为 current 版本。
9
+ > 本阶段所有 KB 查询都是验证**刚入库的当前变更**是否正确。
10
+
11
+ ---
12
+
13
+ ## §1 版本变更生效验证
14
+
15
+ ### 场景
16
+
17
+ 入库后验证 modified 实体的新版本是否正确成为 current。
18
+
19
+ ### API
20
+
21
+ ```
22
+ GET {base}/entities/{entityId}/current-version
23
+ ```
24
+
25
+ ### 示例
26
+
27
+ 验证 CAP-USER-LOGIN 的新版本是否生效:
28
+
29
+ ```bash
30
+ curl -sS -H "Authorization: Bearer $API_KEY" \
31
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/e89287e8-0000-0000-0000-000000000000/current-version"
32
+ ```
33
+
34
+ ### 验证清单
35
+
36
+ | 字段 | 期望值 | 来源 |
37
+ |------|--------|------|
38
+ | `entityVersionId` | 新版本 UUID | archive package 中声明的 version-id |
39
+ | `deltaState` | `modified` | proposal/spec 中的 delta-state |
40
+ | `predecessorVersionId` | 旧版本 UUID | archive package 中的 predecessor-version |
41
+ | `generationRole` | `current`(本次变更 authored) | 工具链设置 / KB 推导 |
42
+
43
+ > **`generationRole` 值说明**:由 `kld-sdd` 工具链(`effective-graph.cjs`)在打包 archive 时设置,三个合法值:
44
+ > - `current` — 本次变更作者编写的事实(added/modified/removed)
45
+ > - `inherited` — 从上一次已确认 archive 继承的事实(unchanged)
46
+ > - `produced` — 系统自动生成的事实(如 change record)
47
+ >
48
+ > IngestionService 优先使用 archive 包提供的值;若缺失则从 `deltaState` 推导(`unchanged→inherited`、`added/modified/removed→current`),推导逻辑与工具链词表一致。
49
+ | `reviewStatus` | `confirmed` | 入库后自动确认 |
50
+ | `changeId` | 当前变更 ID | archive package 中的 change-id |
51
+
52
+ ### 决策逻辑
53
+
54
+ | 检查结果 | 状态 | 动作 |
55
+ |----------|------|------|
56
+ | 所有字段匹配 | ✅ 生效 | 记录验证通过 |
57
+ | entityVersionId 不匹配 | ❌ 未生效 | 检查入库 job 是否成功、predecessor 是否正确 |
58
+ | generationRole 不是 `current` 或 `inherited` | ❌ 异常 | 检查是否有版本冲突 |
59
+
60
+ ---
61
+
62
+ ## §2 历史 AC 保留验证
63
+
64
+ ### 场景
65
+
66
+ 入库后验证未修改的历史 AC 是否仍然出现在父 STMT 的 ontology-view 中。
67
+
68
+ ### API
69
+
70
+ ```
71
+ GET {base}/entities/{stmtEntityId}/ontology-view
72
+ ```
73
+
74
+ ### 示例
75
+
76
+ 验证 STMT-USER-LOGIN-001 的 AC 列表:
77
+
78
+ ```bash
79
+ curl -sS -H "Authorization: Bearer $API_KEY" \
80
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/89bbf6a6-0000-0000-0000-000000000000/ontology-view"
81
+ ```
82
+
83
+ ### 验证步骤
84
+
85
+ 1. 提取 `relations` 中 `relationType=verifiedBy && direction=outbound` 的邻居列表
86
+ 2. 按来源分类:
87
+ - `changeId = 旧变更` → 历史 AC(应保留)
88
+ - `changeId = 当前变更` → 新增/修改 AC
89
+ 3. 确认历史 AC 数量 ≥ 入库前数量
90
+ 4. 确认新增 AC 已出现
91
+
92
+ ### 验证清单
93
+
94
+ | 检查项 | 期望 | 机制 |
95
+ |--------|------|------|
96
+ | 历史 AC 仍在列表中 | ✅ 保留 | AC 未被修改 → v1 仍 current → 关系保留 |
97
+ | 新增 AC 已出现 | ✅ 加入 | 新 AC 入库 → statement_id 指向 STMT → inferred 关系生成 |
98
+ | 历史 AC 版本未变 | v1, added, predecessor=null | lineage 确认只有 1 个版本 |
99
+ | AC 的 changeId 正确 | 旧 AC = 旧变更 / 新 AC = 新变更 | 来源可追溯 |
100
+
101
+ ### 决策逻辑
102
+
103
+ | 检查结果 | 状态 | 动作 |
104
+ |----------|------|------|
105
+ | 历史 AC 全部保留 + 新 AC 已加入 | ✅ 正常 | 验证通过 |
106
+ | 历史 AC 丢失 | ❌ 异常 | 检查 archive package 是否误标 modified/removed |
107
+ | 新 AC 未出现 | ❌ 异常 | 检查 AC 的 statement_id 是否正确指向 STMT |
108
+
109
+ ---
110
+
111
+ ## §3 关系完整性验证
112
+
113
+ ### 场景
114
+
115
+ 入库后验证关键关系(contains / verifiedBy / realizes / covers)是否正确建立。
116
+
117
+ ### API
118
+
119
+ ```
120
+ GET {base}/entities/{entityId}/ontology-view
121
+ ```
122
+
123
+ ### 验证矩阵
124
+
125
+ 对以下实体类型分别检查:
126
+
127
+ | 实体类型 | 检查关系 | direction | 期望邻居 |
128
+ |----------|----------|-----------|----------|
129
+ | Change | `contains` | outbound | 下属 Capability |
130
+ | Capability | `contains` | outbound | 下属 STMT |
131
+ | Capability | `contains` | inbound | 所属 Change |
132
+ | STMT | `verifiedBy` | outbound | 下属 AC |
133
+ | DES | `realizes` | outbound | 上游 STMT |
134
+ | TASK | `covers` / `implements` | outbound | 上游 STMT / DES |
135
+ | STMT | `sourcedFrom` | outbound | DocumentSection |
136
+ | Entity | `declares` | inbound | Artifact |
137
+
138
+ ### 示例
139
+
140
+ ```bash
141
+ # 验证 CAP-USER-LOGIN 的 contains 关系
142
+ curl -sS -H "Authorization: Bearer $API_KEY" \
143
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/e89287e8-0000-0000-0000-000000000000/ontology-view" | \
144
+ jq '.data.relations[] | select(.relationType=="contains")'
145
+ ```
146
+
147
+ ### 决策逻辑
148
+
149
+ | 检查结果 | 状态 | 动作 |
150
+ |----------|------|------|
151
+ | 所有关键关系存在 | ✅ 完整 | 验证通过 |
152
+ | 缺少 contains → STMT | ❌ 断链 | 检查 spec.md 的 capability-id 引用 |
153
+ | 缺少 verifiedBy → AC | ❌ 断链 | 检查 AC 的 statement_id 属性 |
154
+ | 缺少 realizes → STMT | ❌ 断链 | 检查 design.md 的 realizes 引用 |
155
+ | 缺少 covers/implements | ⚠️ 警告 | 检查 tasks.md 的 covers/implements 引用 |
156
+
157
+ ---
158
+
159
+ ## §4 版本谱系验证
160
+
161
+ ### 场景
162
+
163
+ 验证实体的版本链完整性(v1 → v2 → ... 前后衔接)。
164
+
165
+ ### API
166
+
167
+ ```
168
+ GET {base}/entities/{entityId}/lineage
169
+ ```
170
+
171
+ ### 示例
172
+
173
+ ```bash
174
+ curl -sS -H "Authorization: Bearer $API_KEY" \
175
+ "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/entities/e89287e8-0000-0000-0000-000000000000/lineage"
176
+ ```
177
+
178
+ ### 验证清单
179
+
180
+ | 检查项 | 期望 |
181
+ |--------|------|
182
+ | 版本数 ≥ 2(modified 实体) | v1(added) → v2(modified) |
183
+ | v2.predecessorVersionId == v1.entityVersionId | 链式衔接 |
184
+ | v1.deltaState == added, v2.deltaState == modified | 状态正确 |
185
+ | 最后一个版本 generationRole == `current` 或 `inherited` | 当前版本正确 |
186
+ | 每个版本的 changeId 存在且不同 | 来源可追溯 |
187
+
188
+ ### 决策逻辑
189
+
190
+ | 检查结果 | 状态 | 动作 |
191
+ |----------|------|------|
192
+ | 链式完整 + current 正确 | ✅ 正常 | 验证通过 |
193
+ | predecessorVersionId 断裂 | ❌ 异常 | 检查 archive 的 predecessor-version 声明 |
194
+ | 最后版本非 changed | ❌ 异常 | 检查是否有后续入库覆盖 |
195
+
196
+ ---
197
+
198
+ ## §5 版本冲突检测
199
+
200
+ ### 场景
201
+
202
+ 入库时如果 predecessorVersionId 与 KB 当前版本不匹配,会标记为 conflicting。
203
+
204
+ ### 检查方式
205
+
206
+ 入库 job 响应中检查:
207
+
208
+ | 字段 | 正常 | 冲突 |
209
+ |------|------|------|
210
+ | `errorCode` | 无 | `VERSION_CONFLICT` / `EXTERNAL_REF_CONFLICT` / `EXTERNAL_REFERENCE_FORMAT_INVALID` / `SCOPE_MISMATCH` / `FEATURE_UNBOUND` |
211
+ | job status | `succeeded` | `failed`(整包回滚) |
212
+
213
+ ### 冲突处理
214
+
215
+ | 冲突类型 | 原因 | 修正方式 |
216
+ |----------|------|----------|
217
+ | `VERSION_CONFLICT` | predecessor 不匹配当前 version | 回 spec 获取正确 predecessor,重新 archive |
218
+ | `EXTERNAL_REF_CONFLICT` | 同 external key 绑定不同 entity_id | 回 propose/spec 确认身份决议 |
219
+ | `EXTERNAL_REFERENCE_FORMAT_INVALID` | 编号归一化后不合文法(含 requirement.`feature_id`) | 回需求管理系统换发合规编号,禁止手改硬闯 |
220
+ | `EXTERNAL_REFERENCE_SCOPE_MISMATCH` | 场景键 REQ 前缀不在同包 requirement 集合 | 回 spec 修正 external-ref 中 SCN 的 REQ 前缀 |
221
+ | `EXTERNAL_REFERENCE_FEATURE_UNBOUND` | feature 绑定与 requirement.`feature_id` 无法配对 | 回 propose/archive 修正线缆字段,确认 FEAT 号存在 |
222
+
223
+ > **禁止**在 KB 内现场改绑或解绑。必须回 SDD 流程修正后重新入库。