kld-sdd 2.6.16 → 2.6.21

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 (70) hide show
  1. package/bin/kld-sdd-init.js +10 -0
  2. package/kld-sdd-guide.html +22 -0
  3. package/lib/device-auth-cli.js +130 -0
  4. package/lib/device-auth.js +345 -0
  5. package/lib/init-account-binding.js +108 -0
  6. package/lib/init.js +238 -55
  7. package/lib/skills-bundle.js +20 -1
  8. package/lib/tool-profiles.js +8 -0
  9. package/package.json +7 -3
  10. package/skywalk-sdd/apply-worktree-finish.cjs +2 -23
  11. package/skywalk-sdd/context-client.cjs +38 -87
  12. package/skywalk-sdd/index.cjs +860 -132
  13. package/skywalk-sdd/kb-sync-identity.cjs +780 -0
  14. package/skywalk-sdd/kb-upload.cjs +505 -0
  15. package/skywalk-sdd/lib/shared.cjs +811 -0
  16. package/skywalk-sdd/lib/usage-contract.cjs +276 -0
  17. package/skywalk-sdd/lib/usage-reporter.cjs +354 -0
  18. package/skywalk-sdd/lib/user-config.cjs +157 -0
  19. package/skywalk-sdd/metrics-v3.cjs +138 -8
  20. package/skywalk-sdd/ontology/archive-package.cjs +19 -34
  21. package/skywalk-sdd/ontology/change-lock.cjs +3 -7
  22. package/skywalk-sdd/ontology/external-key.cjs +18 -4
  23. package/skywalk-sdd/ontology/id.cjs +26 -5
  24. package/skywalk-sdd/ontology/identity-index.cjs +3 -7
  25. package/skywalk-sdd/ontology/resolve-spec-root.cjs +20 -6
  26. package/skywalk-sdd/ontology/runtime.cjs +16 -12
  27. package/skywalk-sdd/ontology/traceability-validator.cjs +7 -4
  28. package/skywalk-sdd/reporting/change-report-markdown.cjs +137 -19
  29. package/skywalk-sdd/reporting/change-report-model.cjs +993 -14
  30. package/skywalk-sdd/reporting/change-report-renderer.cjs +106 -41
  31. package/skywalk-sdd/reporting/change-report-view-model.cjs +272 -43
  32. package/skywalk-sdd/reporting/core-metric-definitions.cjs +192 -0
  33. package/skywalk-sdd/spec-root.cjs +31 -0
  34. package/templates/git-hooks/pre-commit-consistency-check.cjs +271 -116
  35. package/templates/git-hooks/pre-push-consistency-check.cjs +252 -123
  36. package/templates/hooks/codebuddy/hooks/hook-gate-core.cjs +327 -0
  37. package/templates/hooks/codebuddy/hooks/sdd-apply-test-gate.cjs +54 -9
  38. package/templates/hooks/codebuddy/hooks/sdd-mid-checkpoint.cjs +63 -6
  39. package/templates/hooks/codebuddy/hooks/sdd-tdd-rhythm-gate.cjs +113 -65
  40. package/templates/openspec/proposal.md +7 -3
  41. package/templates/openspec/spec.md +3 -3
  42. package/templates/skills/kld-sdd/opsx-apply/SKILL.md +8 -6
  43. package/templates/skills/kld-sdd/opsx-apply/checklist.md +2 -0
  44. package/templates/skills/kld-sdd/opsx-apply/reference.md +29 -7
  45. package/templates/skills/kld-sdd/opsx-archive/SKILL.md +6 -5
  46. package/templates/skills/kld-sdd/opsx-check/SKILL.md +49 -17
  47. package/templates/skills/kld-sdd/opsx-check/checklist.md +4 -2
  48. package/templates/skills/kld-sdd/opsx-consistency-check/SKILL.md +187 -257
  49. package/templates/skills/kld-sdd/opsx-consistency-check/reference.md +129 -0
  50. package/templates/skills/kld-sdd/opsx-design/SKILL.md +2 -2
  51. package/templates/skills/kld-sdd/opsx-explore/SKILL.md +2 -2
  52. package/templates/skills/kld-sdd/opsx-kb-config/SKILL.md +185 -0
  53. package/templates/skills/kld-sdd/opsx-kb-config/reference.md +127 -0
  54. package/templates/skills/kld-sdd/opsx-kb-ingest/SKILL.md +218 -53
  55. package/templates/skills/kld-sdd/opsx-kb-ingest/reference.md +51 -9
  56. package/templates/skills/kld-sdd/opsx-ontology-query/SKILL.md +12 -50
  57. package/templates/skills/kld-sdd/opsx-ontology-query/phase-3-postchange.md +2 -2
  58. package/templates/skills/kld-sdd/opsx-ontology-query/reference.md +1 -1
  59. package/templates/skills/kld-sdd/opsx-propose/SKILL.md +35 -23
  60. package/templates/skills/kld-sdd/opsx-propose/checklist.md +2 -0
  61. package/templates/skills/kld-sdd/opsx-propose/reference.md +22 -17
  62. package/templates/skills/kld-sdd/opsx-rules/SKILL.md +2 -2
  63. package/templates/skills/kld-sdd/opsx-spec/SKILL.md +19 -15
  64. package/templates/skills/kld-sdd/opsx-spec/checklist.md +2 -0
  65. package/templates/skills/kld-sdd/opsx-task/SKILL.md +2 -4
  66. package/templates/skills/kld-sdd/opsx-test/SKILL.md +2 -2
  67. package/templates/skills/kld-sdd/tdd-core/reference.md +1 -1
  68. package/templates/skills/kld-sdd/tdd-rules/rules/test-skeleton-telemetry.md +1 -1
  69. package/templates/skills/kld-sdd/opsx-kb-ingest/state.example.json +0 -7
  70. package/templates/skills/kld-sdd/opsx-ontology-query/state.example.json +0 -7
@@ -9,59 +9,28 @@ description: >-
9
9
 
10
10
  # 本体知识库 · 入库
11
11
 
12
- 只负责**入库**(zip 上传)。鉴权只用 **API Key**(`Authorization: Bearer sk_sdd_…`),**禁止**走手机号登录。
12
+ 只负责**入库**(zip 上传 + 文件夹上传)。鉴权只用 **API Key**(`Authorization: Bearer sk_sdd_…`),**禁止**走手机号登录。
13
13
 
14
14
  > 控制台知识库页另有浮动 Ontology Agent(会话登录 + SSE);本 Skill 仍走 API Key,二者分开。
15
15
 
16
- > **📡 共享状态**:本技能与 `opsx-ontology-query` **共用同一份 KB 配置**(`../.shared/kb-state.json`)。任一 skill 配置后,另一个自动可用,无需重复输入 API Key
16
+ > **📡 共享状态**:本技能与 `opsx-ontology-query`、`kb-upload` **共用同一份 KB 配置**(`kb-state.json`,位于 spec 仓根目录)。KB 配置(API Key + Space/KB 选择 + project-identity.json)由 `opsx-kb-config` 统一负责。
17
+
18
+ > **🖥️ 跨平台执行规则**(Windows 用户必读):
19
+ > - 入库涉及 HTTP 请求和 JSON 文件读写,**禁止**在 PowerShell 中使用 `curl` → 用 `Invoke-RestMethod` 或 Node.js 脚本(`kb-upload.cjs` 已封装)
20
+ > - **禁止**用 PowerShell `Get-Content` / `Out-File` 读写 JSON(默认写 BOM 导致 JSON.parse 失败)→ 用 write_to_file 工具或 Node.js `fs` 模块
21
+ > - **禁止** `| cat` 管道 → 直接执行命令
17
22
 
18
23
  ## Session 启动(每次用本 Skill 必做)
19
24
 
20
25
  ```
21
26
  Task Progress:
22
- - [ ] 1. 读 ../.shared/kb-state.json(没有则当空)
23
- - [ ] 2. 无 apiKey → 向用户索取并写入共享 state(勿把完整 key 打进聊天摘要)
24
- - [ ] 3. targets 或用户要重置 拉空间/KB 列表,让用户多选后写入
25
- - [ ] 4. 按意图执行入库操作(上传 / 查状态 / 列表 / 重试)
26
- - [ ] 5. 按模板输出结果
27
+ - [ ] 1. 读 kb-state.json(spec 仓根目录)
28
+ - [ ] 2. 无 apiKey 或无 targets 提示用户运行 /opsx-kb-config 配置知识库
29
+ - [ ] 3. 有配置 按意图执行入库操作(上传 / 查状态 / 列表 / 重试)
30
+ - [ ] 4. 按模板输出结果
27
31
  ```
28
32
 
29
- ### 1–2. API Key
30
-
31
- 若 `state.apiKey` 为空或无效(401/403):
32
-
33
- 1. 请用户提供 API Key(控制台「API 密钥」创建,至少含 `archive:ingest`。建议同时勾选 `context:read`,使 `opsx-ontology-query` 也能复用此 Key)。
34
- 2. 可选:请用户确认 `api`(默认 `http://localhost:8090/api`)与 `tenantKey`(默认 `default`)。
35
- 3. 写入共享 `../.shared/kb-state.json`(创建目录若不存在)。
36
- 4. 用 `GET $API/health` 探活;再用 `GET $API/v1/spaces?tenantKey=…` + Bearer 校验 key。
37
-
38
- 用户说「换密钥 / 重置 API Key」→ 清空 `apiKey`(可保留 targets),回到本步。
39
-
40
- ### 3. 选择空间与知识库(支持多选)
41
-
42
- 若 `state.targets` 为空,或用户说「重新选择 / 重置空间 / 重置知识库」:
43
-
44
- 1. `GET $API/v1/spaces?tenantKey=$TENANT_KEY`
45
- 2. 对每个相关 space:`GET $API/v1/spaces/{spaceId}/knowledge-bases`
46
- 3. 向用户展示「空间名 / spaceId → KB 名 / kbId」清单,**允许多选**。
47
- 4. 写入 `targets: [{ spaceId, spaceName, spaceKey, kbId, kbName }, …]`。
48
- 5. 仅清空 targets、保留 apiKey 即完成「重置空间和知识库」。
49
-
50
- 入库时:用户指定目标 KB(从 `targets` 中选择),仅对选中的 KB 执行上传。
51
-
52
- ### 3.5 兜底:确保 project-identity.json 存在(上传前必做)
53
-
54
- > 正常情况下 `project-identity.json` 已在 `opsx-ontology-query` 首次配置 KB 时创建。
55
- > 本步是兜底:如果用户跳过了 ontology-query(如选择 archive 降级路径),直接来做入库,需要确保文件存在且 `project_id` 正确。
56
-
57
- 1. 读取 spec 包裹包路径:
58
- ```bash
59
- SPEC_ROOT=$(node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" spec-root)
60
- ```
61
- 2. 检查 `$SPEC_ROOT/skywalk-sdd/project-identity.json`:
62
- - **不存在** → 从 `targets[0].spaceKey` 创建(格式同 `opsx-ontology-query` Step 3.5)
63
- - **已存在但 `project_id !== targets[0].spaceKey`** → 提示用户:`⚠️ project_id 与 Space spaceKey 不一致,入库将报 PROJECT_SPACE_MISMATCH。是否更新?`
64
- - **已存在且一致** → 跳过
33
+ > **KB 配置**(API Key、Space/KB 选择、project-identity.json)由 `opsx-kb-config` 统一负责。如用户需要配置或更换 KB,请引导运行 `/opsx-kb-config`。
65
34
 
66
35
  ### 4. 入库操作
67
36
 
@@ -122,11 +91,195 @@ curl -sS -X POST "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/ingestions/$JO
122
91
  - 包内无重复 `(external key, entity_id)` 绑定对
123
92
  - `project_id` / `spaceKey` 既有规则保留
124
93
  - **编号格式**:三条正则(见 reference)+ 场景 SLUG≤40 / 键总长≤120;先归一化再匹配
125
- - **场景作用域**:scenario 键的 REQ 前缀必须出现在同包 requirement 绑定集合
94
+ - **场景作用域**:scenario 键的需求编号前缀必须出现在同包 requirement 绑定集合
126
95
  - **功能配对**:同实体每条 feature 绑定必须能与某 requirement 条目的 `feature_id` 精确配对;反向同理
127
96
 
128
97
  详细字段说明 → [reference.md](reference.md)。
129
98
 
99
+ ### 4.5 文件夹上传(支持随时入库)
100
+
101
+ 支持直接传入 SDD 变更目录,自动完成语义校验、元数据生成、打包上传。**不要求 SDD 流程全部走完**,任意阶段均可入库。
102
+
103
+ **用法**:
104
+
105
+ ```bash
106
+ # 仅校验(不上传)
107
+ node skywalk-sdd/kb-upload.cjs --validate-only --folder=<变更目录路径> [--minimum-level=propose-spec]
108
+
109
+ # 文件夹上传(自动跑语义管线 + 生成元数据 + 打包 zip + 上传)
110
+ node skywalk-sdd/kb-upload.cjs --folder=<变更目录路径> [--minimum-level=propose-spec]
111
+
112
+ # zip 包上传(兼容现有方式)
113
+ node skywalk-sdd/kb-upload.cjs --package=<zip 路径>
114
+ ```
115
+
116
+ #### 上传等级(`--minimum-level`)
117
+
118
+ | 等级 | 最低要求 | 入库内容 | 适用场景 |
119
+ |------|---------|----------|---------|
120
+ | `propose-spec`(默认) | proposal.md + spec.md | Change、Capability、STMT、AC、Constraint | 需求定义阶段入库 |
121
+ | `design` | + design.md | + DesignElement | 补充技术方案 |
122
+ | `task` | + tasks.md | + Task、TaskDependency | 补充任务拆解 |
123
+ | `full` | 全部 4 个 | 全部实体 | 完整归档 |
124
+
125
+ #### 前置校验规则
126
+
127
+ - 校验必需文件存在(按 `--minimum-level` 决定)
128
+ - 校验 `project-identity.json` 存在且 `project_id === spaceKey`(本地预检,避免上传后报 `PROJECT_SPACE_MISMATCH`)
129
+ - 若 `project-identity.json` 不存在 → 提示运行 `/opsx-kb-config` 配置知识库
130
+
131
+ #### 重新入库前:KB 身份同步(重要)
132
+
133
+ 当 Change 的 proposal.md / spec.md / design.md / tasks.md **内容被修改后重新上传**(KB 中已存在同 entity-id 的实体),需要更新被修改实体的身份元数据(delta-state + version-id + predecessor-version),否则 KB 会拒绝(`VERSION_IDENTITY_CONFLICT`:同 version-id 但 content_hash 不同)。
134
+
135
+ > **KB 入库原理**:对每个实体执行 `INSERT … ON CONFLICT (entity_version_id) DO NOTHING`。若 version-id 已存在且 entity-id + content_hash 一致 → 幂等跳过 ✅;若 content_hash 不同 → `VERSION_IDENTITY_CONFLICT` ❌。因此,**未修改的实体不需要动**——它们 version-id + content_hash 都没变 → KB 自动幂等跳过。
136
+
137
+ > **语义校验**:`kb-upload.cjs --folder` 在上传前运行 `reconcileChange()` 语义校验。当本地无 confirmed archive(单变更场景)时,语义校验跳过基于历史的 lineage 检查,`modified` 实体只需提供合法的 `predecessor-version`(来自 KB resolve)即可通过。
138
+
139
+ **判断是否为重新入库**(满足任一即为重新入库):
140
+
141
+ - spec.md / proposal.md 身份块中已有 `entity-id` + `version-id`(说明之前已分配过身份)
142
+ - 上次 `kb-upload.cjs --folder` 返回 `succeeded`(KB 中已有该实体)
143
+ - 上传返回 `VERSION_IDENTITY_CONFLICT`(错误消息含 anchorId / name / versionId)
144
+
145
+ **重新入库步骤**(只针对**被修改的实体**):
146
+
147
+ > **⚠️ 文档实体也需要同步**:修改 .md 文件内容时,需同步**两类**实体:
148
+ > 1. **结构实体**(Artifact / DocumentSection)— 存储在 `ontology/ontology-identities.json` 中,由 reconcile 管理
149
+ > 2. **业务实体**(STMT / AC / CON / CAP)— 身份块写在 markdown 中
150
+ >
151
+ > 常见错误:只同步了业务实体(AC/STMT),遗漏了结构实体(文档 Artifact)→ KB 报 `VERSION_IDENTITY_CONFLICT`。
152
+
153
+ **方式 A:自动同步(推荐)**
154
+
155
+ ```bash
156
+ # 自动扫描 content_hash 变化,同步所有变更的结构实体 + 内容有变化的业务实体
157
+ # (内容驱动模式:只同步 content_hash 真正变化的实体,不污染未变实体)
158
+ node skywalk-sdd/kb-sync-identity.cjs \
159
+ --file=spec.md \
160
+ --change=<change-key> \
161
+ --project=.
162
+
163
+ # 或精准指定变更的业务实体锚点(用户明确知道改了哪些 AC/STMT/CON)
164
+ node skywalk-sdd/kb-sync-identity.cjs \
165
+ --file=spec.md \
166
+ --change=<change-key> \
167
+ --project=. \
168
+ --anchors=AC-USER-CRUD-006
169
+
170
+ # 干跑模式(只看报告不修改文件)
171
+ node skywalk-sdd/kb-sync-identity.cjs \
172
+ --file=spec.md \
173
+ --change=<change-key> \
174
+ --project=. \
175
+ --dry-run
176
+
177
+ # 跳过 KB 验证(KB 不可用时强制本地同步,风险:predecessor 可能不匹配 KB)
178
+ node skywalk-sdd/kb-sync-identity.cjs \
179
+ --file=spec.md \
180
+ --change=<change-key> \
181
+ --project=. \
182
+ --skip-kb-verify
183
+ ```
184
+
185
+ 脚本自动完成:
186
+ - **Phase 0**: 读取 KB 配置(kb-state.json + project-identity.json)→ KB API 健康检查 → KB resolve 验证实体当前 version-id
187
+ - **结构实体同步**: 扫描 `ontology-identities.json` 中结构实体(Artifact + DocumentSection)的 content_hash 变化,为变更实体生成新 version-id(predecessor=KB验证的 version-id)
188
+ - **业务实体同步**: 基于结构实体同步的 DocumentSection 变化结果,只为 content_hash 真正变化的业务实体生成新 version-id 并更新 markdown 身份块。未变化的 `added` 实体保持原样,不会被无端 version-bump
189
+ - **同步报告**: 输出哪些实体被同步、哪些跳过、predecessor 来源(local/KB)
190
+
191
+ > **✅ 内容驱动安全保证**:默认模式下,脚本通过 Part 1 的 DocumentSection content_hash 比较结果驱动 Part 2 的业务实体筛选。只有 `delta-state=added` **且** 对应 DocumentSection content_hash 真正变化的实体才会被转为 `modified`。未变化的 `added` 实体保持原样,不会造成版本污染。
192
+ >
193
+ > **⚠️ 精准模式** (`--anchors`): 当用户明确知道改了哪些实体时使用。脚本信任用户指定,即使 Part 1 未检测到 content_hash 变化也会同步(适用于身份元数据变更等非内容性修改场景)。
194
+
195
+ > **Phase 0 说明**:脚本默认会查询 KB 获取实体的当前 version-id 作为 predecessor。如果本地 version-id 与 KB 不一致(如 git 恢复后),脚本会自动使用 KB 的 version-id 作为 predecessor 并输出警告。如果 KB 不可达,脚本会降级为本地模式(使用本地 version-id)并输出警告。使用 `--skip-kb-verify` 可强制跳过所有 KB 操作。
196
+
197
+ > ⛔ **禁止**跳过同步直接 `kb-upload.cjs --folder`:被修改的实体 version-id 未变 + content_hash 变了 → KB 报 `VERSION_IDENTITY_CONFLICT`。
198
+ >
199
+ > ⛔ **禁止**删除整个 `ontology/` + `artifacts/` 缓存来绕过冲突:会导致所有实体被重新计算 hash 和 version-id,造成不必要的版本扩散。应使用 `kb-sync-identity.cjs` 精准同步。
200
+
201
+ **方式 B:手动同步(脚本不可用时 fallback)**
202
+
203
+ 1. **识别被修改的实体**——Agent 知道自己改了哪些内容。例如:修改了 AC-USER-CRUD-007 的默认分页大小,则只需处理该实体。若修改了 spec.md 的多处内容,列出所有受影响的实体 anchor(如 STMT-xxx、AC-xxx、CON-xxx)。
204
+
205
+ > ⚠️ **不要忘记结构实体**:修改了 .md 文件后,该文件的 Artifact 实体(文档级)也需要同步。结构实体存储在 `ontology/ontology-identities.json` 中,需更新其 `version_id` 字段。
206
+
207
+ 2. **对每个被修改的实体,查 KB → 生成新 version-id → 更新身份块**
208
+
209
+ 2a. 查询 KB 获取该实体的当前 version-id:
210
+
211
+ ```bash
212
+ # 示例:查询 AC-USER-CRUD-007(external-id 为场景键)
213
+ node "$(cat .sdd-spec-root)/skywalk-sdd/context-client.cjs" \
214
+ --mode=resolve \
215
+ --external-system=requirement-mgmt \
216
+ --external-object-type=scenario \
217
+ --external-id="REQ-US-2026-001:SCN-user-crud-007" \
218
+ --space-id="$ENGINEERING_KB_SPACE_ID" \
219
+ --kb-id="$ENGINEERING_KB_KB_ID"
220
+ ```
221
+
222
+ KB 返回 `candidates[]`,每项含 `entityId` 和 `entityVersionId`(完整 UUID,`id.cjs` 自动归一化为 8-hex)。
223
+
224
+ > 没有 `external-ref` 的实体(如 STMT、CON)可用 `--entity-id=<spec.md中的entity-id>` + `--entity-type=<SpecificationStatement|Constraint>` 查询。
225
+
226
+ 2b. 生成新 version-id:
227
+
228
+ ```bash
229
+ # AC-USER-CRUD-007,KB 返回 entityId=e248ba63, entityVersionId=be5581d9
230
+ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" semantic-identity \
231
+ --delta-state=modified \
232
+ --entity-id=e248ba63 \
233
+ --predecessor-version=be5581d9
234
+ # → 输出新的 version_id(如 3f8a1c2b)
235
+ ```
236
+
237
+ 2c. 更新 spec.md / proposal.md 中该实体的身份块:
238
+
239
+ ```markdown
240
+ ##### 场景:[AC-USER-CRUD-007] 默认分页查询
241
+ - **entity-id**: e248ba63 ← 不变(复用 KB 的 entityId)
242
+ - **version-id**: 3f8a1c2b ← 改为步骤 2b 生成的新 version-id
243
+ - **delta-state**: modified ← 从 added 改为 modified
244
+ - **predecessor-version**: be5581d9 ← 新增:KB 返回的 entityVersionId
245
+ - **external-ref**: requirement-mgmt:scenario:REQ-US-2026-001:SCN-user-crud-007
246
+ ```
247
+
248
+ 3. **未修改的实体保持原样不动**——它们 version-id + content_hash 都没变 → KB 自动幂等跳过。不需要改为 `unchanged` 或 `modified`。
249
+
250
+ 4. **先校验再上传**:
251
+
252
+ ```bash
253
+ # 先校验(含语义校验,确认 modified 实体身份块正确)
254
+ node skywalk-sdd/kb-upload.cjs --validate-only --folder=<变更目录路径>
255
+
256
+ # 校验通过后上传
257
+ node skywalk-sdd/kb-upload.cjs --folder=<变更目录路径>
258
+ ```
259
+
260
+ > ⛔ **禁止**跳过步骤 1-3 直接 `kb-upload.cjs --folder`:被修改的实体 version-id 未变 + content_hash 变了 → KB 报 `VERSION_IDENTITY_CONFLICT`(错误消息含 anchorId / name / versionId,据此定位是哪个实体)。
261
+
262
+ **其他影响入库的因素**:
263
+
264
+ | 因素 | 说明 | 是否需 Agent 处理 |
265
+ |------|------|-------------------|
266
+ | `archive_id` | `kb-upload.cjs` 每次自动生成新的 | ❌ 自动处理 |
267
+ | `project_id` | 必须匹配 Space 的 `spaceKey`,前置校验已拦截 | ❌ 已校验 |
268
+ | `external-ref` 冲突 | 同 external-key 已绑不同 entity-id → `EXTERNAL_REF_CONFLICT` | ✅ 见下文错误处理 |
269
+ | `ARCHIVE_IMMUTABILITY_VIOLATION` | 同一 archive_id 上传不同 content_hash | ❌ 不会发生(每次新 archive_id) |
270
+ | 多个实体同时修改 | 每个被修改的实体都需步骤 2 | ✅ 对每个分别处理 |
271
+
272
+ #### 文件夹上传 vs Zip 上传
273
+
274
+ | 维度 | 文件夹上传 | Zip 上传 |
275
+ |------|-----------|---------|
276
+ | 输入 | 原始变更目录 | 已打包 zip |
277
+ | 语义管线 | 自动执行(semantic-scan → reconcile → check) | 无需(zip 已含元数据) |
278
+ | 元数据生成 | 自动生成(archive-manifest + canonical-facts + conversion-report) | 无需(zip 已含) |
279
+ | 适用场景 | 任意 SDD 阶段入库 | 已有 zip 补传 / 归档后上传 |
280
+
281
+ > 文件夹上传最终也会打包成 zip 走同一上传接口,KB 后端解析逻辑不变。
282
+
130
283
  ### 5. 输出模板
131
284
 
132
285
  ```markdown
@@ -149,11 +302,23 @@ curl -sS -X POST "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/ingestions/$JO
149
302
 
150
303
  成功时展示 `report.externalRefsWritten`。冲突**不**出现在成功模板。
151
304
 
305
+ 若 `errorCode=VERSION_IDENTITY_CONFLICT`(version-id 与 KB 已锁定版本冲突):
306
+
307
+ 1. 错误消息中包含 `anchorId`、`name`、`entityId`、`versionId`,据此**定位是哪个实体**被修改后未更新身份。
308
+ 2. 按「重新入库前:KB 身份同步」步骤操作:对该实体查询 KB → 生成新 version-id → 更新 delta-state=modified + predecessor-version → 重新上传。
309
+ 3. **只需处理该实体**,其余未修改实体不用动(KB 自动幂等跳过)。
310
+
311
+ 若语义校验阶段报 `SEM_VERSION_LINEAGE_MISSING`(`modified` 实体无法定位前序版本):
312
+
313
+ 1. 说明本地存在 confirmed archive(如通过 SDD archive 流程归档的其他变更),但 markdown 中 `predecessor-version` 与 archive 中的 version-id 不匹配。
314
+ 2. 检查 `predecessor-version` 是否来自 KB resolve 返回的 `entityVersionId`(而非手写)。
315
+ 3. 按「重新入库前:KB 身份同步」步骤 2a 重新查询 KB,确认 `entityVersionId`,然后重新生成 version-id 并更新身份块。
316
+
152
317
  若 `errorCode=EXTERNAL_REF_CONFLICT`(整包已回滚):
153
318
 
154
319
  1. 展示 `report.details`(externalRef / anchor / existingEntityId / incomingEntityId)。
155
320
  2. 向用户给出两个修正选项:
156
- - **复用历史身份**:回到 kld-sdd,复用 KB 中原有 entity_id / current version,重新 check 归档 → 入库
321
+ - **复用历史身份**:按「重新入库前:KB 身份同步」步骤——查询 KB 获取已有 entity-id version-id,更新 delta-state=modified + predecessor-version,重新上传
157
322
  - **改为新锚点**:回到 kld-sdd,分配新锚点与新 entity_id,重新 check → 归档 → 入库
158
323
  3. **禁止**在 KB 内现场改绑或解绑。
159
324
 
@@ -161,8 +326,8 @@ curl -sS -X POST "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/ingestions/$JO
161
326
 
162
327
  | errorCode | 指引 |
163
328
  |-----------|------|
164
- | `EXTERNAL_REFERENCE_FORMAT_INVALID` | 编号不合规**回需求管理系统换发**;不得手改编号硬闯 |
165
- | `EXTERNAL_REFERENCE_SCOPE_MISMATCH` | 场景键 REQ 前缀不在申报集合 → 回 kld-sdd spec 修正 external-ref |
329
+ | `EXTERNAL_REFERENCE_FORMAT_INVALID` | 编号含非白名单字符**检查外部编号来源**;不得手改编号硬闯 |
330
+ | `EXTERNAL_REFERENCE_SCOPE_MISMATCH` | 场景键需求编号前缀不在申报集合 → 回 kld-sdd spec 修正 external-ref |
166
331
  | `EXTERNAL_REFERENCE_FEATURE_UNBOUND` | feature↔requirement.`feature_id` 配对断裂 → 回 propose/archive 修正线缆字段 |
167
332
 
168
333
  **禁止**手改包内编号绕过门禁。
@@ -173,18 +338,17 @@ curl -sS -X POST "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/ingestions/$JO
173
338
  - 无 `targets` 不得臆造 spaceId/kbId。
174
339
  - 上传前确认 zip 包路径存在且为有效 zip 文件。
175
340
  - 入库失败时展示 `errorCode` 和 `errorMessage`,不编造原因。
176
- - 完整 apiKey 只写共享 state 文件(`../.shared/kb-state.json`);聊天里最多显示前缀(如 `sk_sdd_****`)。
341
+ - 完整 apiKey 只写共享 state 文件(`kb-state.json`,spec 仓根目录);聊天里最多显示前缀(如 `sk_sdd_****`)。
177
342
  - 401/403 时清掉 `apiKey`,请用户重贴;勿循环重试。
178
- - **共享状态**:state 文件与 `opsx-ontology-query` 共用。如用户此前已通过查询 skill 配置过 KB,本 skill 启动时直接读取已有配置,无需重复询问。
343
+ - **共享状态**:state 文件与 `opsx-ontology-query`、`kb-upload`、`opsx-kb-config` 共用。KB 配置由 `opsx-kb-config` 统一负责。
179
344
 
180
345
  ## 用户口令
181
346
 
182
347
  | 用户说 | Agent 做 |
183
348
  |--------|----------|
184
- | (首次使用) | key KB(多选)→ 写共享 state → 再操作。此后 `opsx-ontology-query` 也自动可用 |
185
- | 换密钥 / 重置 API Key | apiKey,重走第 2 |
186
- | 重新选择 / 重置空间或知识库 | targets,重走第 3 |
187
- | 上传 / 入库 | 用当前共享 targets 中选中的 KB 上传 zip |
349
+ | 配置 / 换密钥 / KB | 引导运行 `/opsx-kb-config`(本技能不处理配置) |
350
+ | 上传 zip / 入库 | 用当前共享 targets 中选中的 KB 上传 zip |
351
+ | 文件夹上传 / 随时入库 | 运行 `kb-upload.cjs --folder=<path>`,自动打包上传 |
188
352
  | 查状态 / 看任务 | 用 jobId 查询任务状态 |
189
353
  | 列任务 / 看历史 | 列出最近入库任务 |
190
354
  | 重试 | 对失败的 jobId 执行重试 |
@@ -192,6 +356,7 @@ curl -sS -X POST "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/ingestions/$JO
192
356
  ## 心智模型(简述)
193
357
 
194
358
  - 入库是同步操作:上传后后端立即解析 zip、校验、写入数据库,返回最终 job 状态。
359
+ - 投影是异步操作:入库成功后,后端异步执行 vector embedding + AGE graph 投影(通常 5-30 秒)。正常 SDD 流程中,阶段间由用户手动触发,间隔远大于投影时间,无需特殊处理。
195
360
  - 幂等机制:同一 `archive_id` + `content_hash` 重复上传会命中幂等,不重复写入。
196
361
  - `archive_id` 不可变:同一 `archive_id` 上传不同 `content_hash` 会被拒绝(`ARCHIVE_IMMUTABILITY_VIOLATION`)。
197
362
  - `project_id` 必须匹配:zip 包 manifest 中的 `project_id` 必须等于目标 Space 的 `spaceKey`。
@@ -8,7 +8,7 @@
8
8
 
9
9
  ```json
10
10
  {
11
- "api": "http://localhost:8090/api",
11
+ "api": "http://10.29.213.80:8080/api",
12
12
  "tenantKey": "default",
13
13
  "apiKey": "sk_sdd_…",
14
14
  "updatedAt": "2026-07-19T12:00:00Z",
@@ -117,7 +117,7 @@ POST {base}/ingestions/{jobId}/retry
117
117
  | `stage` | String | `validating` / `canonical-store` / `committed` / `failed` |
118
118
  | `idempotentHit` | boolean | 是否命中幂等(同 archive_id + content_hash) |
119
119
  | `relationStatus` | String | `pending` / `committed` / `rolled_back` / `not_required` |
120
- | `projectionStatus` | String | `pending` / `not_started` / |
120
+ | `projectionStatus` | String | `pending` / `not_started` / `complete` / `degraded` / `disabled` |
121
121
  | `errorCode` | String | 失败错误码(见下表) |
122
122
  | `errorMessage` | String | 失败错误描述 |
123
123
  | `report` | JsonNode | 入库报告(成功含 `externalRefsWritten`;冲突失败含 `details`) |
@@ -134,6 +134,8 @@ POST {base}/ingestions/{jobId}/retry
134
134
  | `INGEST_FAILED` | 通用入库失败 |
135
135
  | `PROJECT_SPACE_MISMATCH` | manifest 中 project_id 与目标 Space spaceKey 不一致 |
136
136
  | `ARCHIVE_IMMUTABILITY_VIOLATION` | 同一 archive_id 已存在不同 content_hash |
137
+ | `VERSION_IDENTITY_CONFLICT` | version-id 已存在但 content_hash 或 entity_id 不同;错误消息含 anchorId / name / versionId 帮助定位。该 Change 之前已入库,需对被修改的实体按「重新入库前:KB 身份同步」步骤更新 delta-state=modified + predecessor-version 后重新上传 |
138
+ | `SEM_VERSION_LINEAGE_MISSING` | 语义校验阶段:modified/removed 实体的 predecessor-version 在本地 archive 中找不到对应版本。检查 predecessor-version 是否来自 KB resolve 返回的 entityVersionId |
137
139
  | `MANIFEST_MISSING` | 缺少必需的 manifest 文件 |
138
140
  | `INVALID_FILE_TYPE` | 包含不允许的文件类型 |
139
141
  | `SIZE_LIMIT_EXCEEDED` | 超过包/文件/条目大小限制 |
@@ -141,26 +143,26 @@ POST {base}/ingestions/{jobId}/retry
141
143
  | `EXTERNAL_REF_CONFLICT` | 同外部键+同锚点已绑不同 entity_id;整包回滚;见 `report.details` |
142
144
  | `EXTERNAL_REFERENCE_TYPE_MISMATCH` | 包内 object_type 与实体类型不匹配 |
143
145
  | `EXTERNAL_REFERENCE_DUPLICATE_IN_PACKAGE` | 包内重复 `(external key, entity_id)` |
144
- | `EXTERNAL_REFERENCE_FORMAT_INVALID` | 编号归一化后不合规(含 requirement.`feature_id`);回需求系统换发 |
145
- | `EXTERNAL_REFERENCE_SCOPE_MISMATCH` | 场景键 REQ 前缀不在同包 requirement 集合;回 kld-sdd spec 修正 |
146
+ | `EXTERNAL_REFERENCE_FORMAT_INVALID` | 编号归一化后不合规(含非白名单字符 A-Z 0-9 - _ 或超长);请检查外部编号来源 |
147
+ | `EXTERNAL_REFERENCE_SCOPE_MISMATCH` | 场景键需求编号前缀不在同包 requirement 集合;回 kld-sdd spec 修正 |
146
148
  | `EXTERNAL_REFERENCE_FEATURE_UNBOUND` | feature 绑定与 requirement.`feature_id` 无法配对;回 propose/archive |
147
149
  | `FACTS_SCHEMA_UNSUPPORTED` | canonical-facts schema 非 v1/v2 |
148
150
 
149
151
  ### 编号正则(与 KB 设计 §2 / ExternalKeyFormat 一致)
150
152
 
151
153
  ```text
152
- requirement: ^REQ-[A-Z][A-Z0-9]{1,7}-[0-9]{4}-[0-9]{3,6}$
153
- feature: ^FEAT-[A-Z][A-Z0-9]{1,7}-[0-9]{3,6}$
154
- scenario: ^REQ-[A-Z][A-Z0-9]{1,7}-[0-9]{4}-[0-9]{3,6}:SCN-[a-z0-9]+(-[a-z0-9]+)*-[0-9]{3}$
154
+ requirement: ^[A-Z0-9_-]+$
155
+ feature: ^[A-Z0-9_-]+$
156
+ scenario: ^[A-Z0-9_-]+:SCN-[a-z0-9]+(-[a-z0-9]+)*-[0-9]{3}$
155
157
  ```
156
158
 
157
- requirement 条目可选 `feature_id`(FEAT 文法);配对关系随线缆走,KB 不反查 frontmatter。
159
+ requirement 条目可选 `feature_id`(同 feature 文法);配对关系随线缆走,KB 不反查 frontmatter。
158
160
 
159
161
  ### `EXTERNAL_REF_CONFLICT` 的 report.details
160
162
 
161
163
  ```json
162
164
  {
163
- "externalRef": { "system": "requirement-mgmt", "objectType": "requirement", "externalId": "REQ-…" },
165
+ "externalRef": { "system": "requirement-mgmt", "objectType": "requirement", "externalId": "KLERP-001" },
164
166
  "anchor": "CAP-ORDER-CANCEL",
165
167
  "existingEntityId": "<uuid>",
166
168
  "existingCurrentVersionId": "<uuid>",
@@ -207,3 +209,43 @@ requirement 条目可选 `feature_id`(FEAT 文法);配对关系随线缆
207
209
  ]
208
210
  }
209
211
  ```
212
+
213
+ ## 文件夹上传(kb-upload.cjs)
214
+
215
+ ### 用法
216
+
217
+ ```bash
218
+ # 仅校验
219
+ node skywalk-sdd/kb-upload.cjs --validate-only --folder=<path> [--minimum-level=propose-spec]
220
+
221
+ # 文件夹上传(自动语义管线 + 元数据生成 + 打包 + 上传)
222
+ node skywalk-sdd/kb-upload.cjs --folder=<path> [--minimum-level=propose-spec] [--space-id=<id>] [--kb-id=<id>]
223
+
224
+ # zip 包上传
225
+ node skywalk-sdd/kb-upload.cjs --package=<zip-path> [--space-id=<id>] [--kb-id=<id>]
226
+ ```
227
+
228
+ ### 参数
229
+
230
+ | 参数 | 必填 | 说明 |
231
+ |------|------|------|
232
+ | `--folder=<path>` | 与 `--package` 二选一 | SDD 变更目录路径 |
233
+ | `--package=<zip>` | 与 `--folder` 二选一 | 已打包的 zip 路径 |
234
+ | `--minimum-level` | 否 | 上传最低等级:`propose-spec`(默认)/ `design` / `task` / `full` |
235
+ | `--validate-only` | 否 | 仅校验不上传 |
236
+ | `--space-id=<id>` | 否 | 目标 Space ID(从 kb-state.json targets[0] 读取) |
237
+ | `--kb-id=<id>` | 否 | 目标 KB ID(从 kb-state.json targets[0] 读取) |
238
+
239
+ ### project_id 解析优先级
240
+
241
+ 1. `$SPEC_ROOT/skywalk-sdd/project-identity.json` 的 `project_id` 字段
242
+ 2. 都没有 → 报错:`请运行 /opsx-kb-config 配置知识库`
243
+
244
+ ### 上传等级校验
245
+
246
+ | 等级 | 必需文件 |
247
+ |------|---------|
248
+ | `propose-spec` | proposal.md + spec.md |
249
+ | `design` | + design.md |
250
+ | `task` | + tasks.md |
251
+ | `full` | 全部 4 个 + ontology 状态完整 |
@@ -41,53 +41,17 @@ SDD 流程:Propose → Spec → Design → Task → Check → Apply → Archiv
41
41
 
42
42
  ## Session 启动(每次用本 Skill 必做)
43
43
 
44
- > **📡 共享状态**:本技能与 `opsx-kb-ingest` **共用同一份 KB 配置**(`../.shared/kb-state.json`)。任一 skill 配置后,另一个自动可用,无需重复输入 API Key
44
+ > **📡 共享状态**:本技能与 `opsx-kb-ingest`、`kb-upload` **共用同一份 KB 配置**(`kb-state.json`,位于 spec 仓根目录)。KB 配置(API Key + Space/KB 选择 + project-identity.json)由 `opsx-kb-config` 统一负责。
45
45
 
46
46
  ```
47
47
  Task Progress:
48
- - [ ] 1. 读 ../.shared/kb-state.json(没有则当空)
49
- - [ ] 2. 无 apiKey → 向用户索取并写入共享 state(勿把完整 key 打进聊天摘要)
50
- - [ ] 3. targets 或用户要重置 → 拉空间/KB 列表,让用户多选后写入
51
- - [ ] 4. 按意图查询(可对多个 KB 逐个查询)
52
- - [ ] 5. 按模板输出;无命中不编造
48
+ - [ ] 1. 读 kb-state.json(spec 仓根目录)
49
+ - [ ] 2. 无 apiKey 或无 targets 提示用户运行 /opsx-kb-config 配置知识库
50
+ - [ ] 3. 有配置 按意图查询(可对多个 KB 逐个查询)
51
+ - [ ] 4. 按模板输出;无命中不编造
53
52
  ```
54
53
 
55
- **API Key**:控制台「API 密钥」创建,scope `context:read`。401/403 清掉 apiKey 请用户重贴,勿循环重试。
56
-
57
- **选择空间/KB**:`GET $API/v1/spaces?tenantKey=…` → 对每个 space `GET …/knowledge-bases` → 展示清单**允许多选** → 写入共享 `../.shared/kb-state.json` 的 `targets`。
58
-
59
- ### 3.5 写入项目身份文件(首次配置 Space 后)
60
-
61
- > `project-identity.json` 是 spec 仓 Git 中的**团队共享**文件,记录 `project_id`(= KB Space 的 `spaceKey`)。Archive 阶段 `archive-docs` 读取此文件生成 `archive-manifest.json`,kb-ingest 上传时 KB 校验 `project_id === spaceKey`。
62
-
63
- 选择 Space 完成后(Step 3 写入 `targets` 后),执行以下逻辑:
64
-
65
- 1. 读取 spec 包裹包路径:
66
- ```bash
67
- SPEC_ROOT=$(node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" spec-root)
68
- ```
69
- 2. 检查 `$SPEC_ROOT/skywalk-sdd/project-identity.json` 是否已存在
70
- 3. **不存在** → 创建(取 `targets[0].spaceKey` 作为 `project_id`):
71
- ```json
72
- {
73
- "schema_version": "kld-sdd-project-identity/v1",
74
- "project_id": "<targets[0].spaceKey>",
75
- "created_at": "<ISO timestamp>",
76
- "kb_space_id": "<targets[0].spaceId>",
77
- "kb_space_name": "<targets[0].spaceName>"
78
- }
79
- ```
80
- 输出:`✓ 已创建 skywalk-sdd/project-identity.json(project_id: <spaceKey>),请提交到 spec 仓 Git 以便团队共享`
81
- 4. **已存在但 `project_id` 与 `targets[0].spaceKey` 不一致** → 用 AskUserQuestion 询问:
82
- > "project-identity.json 中的 project_id 与当前选择的 KB Space spaceKey 不一致:
83
- > - 文件中:`<existing project_id>`
84
- > - 当前 Space:`<spaceKey>`
85
- > 是否更新?"
86
- - 用户确认 → 更新 `project_id` + `kb_space_id` + `kb_space_name`
87
- - 用户拒绝 → 保留原值(可能入库时报 `PROJECT_SPACE_MISMATCH`)
88
- 5. **已存在且一致** → 跳过,不输出
89
-
90
- > state.json 字段 schema、鉴权细节、列表接口 → [reference.md](reference.md)。
54
+ > **KB 配置**(API Key、Space/KB 选择、project-identity.json)由 `opsx-kb-config` 统一负责。如用户需要配置或更换 KB,请引导运行 `/opsx-kb-config`。
91
55
 
92
56
  ## 查询
93
57
 
@@ -118,12 +82,12 @@ Task Progress:
118
82
  ### 编号文法速查(权威在 KB 仓设计 §2)
119
83
 
120
84
  ```text
121
- requirement: ^REQ-[A-Z][A-Z0-9]{1,7}-[0-9]{4}-[0-9]{3,6}$
122
- feature: ^FEAT-[A-Z][A-Z0-9]{1,7}-[0-9]{3,6}$
123
- scenario: ^REQ-…:SCN-[a-z0-9]+(-[a-z0-9]+)*-[0-9]{3}$
85
+ requirement: ^[A-Z0-9_-]+$
86
+ feature: ^[A-Z0-9_-]+$
87
+ scenario: ^[A-Z0-9_-]+:SCN-[a-z0-9]+(-[a-z0-9]+)*-[0-9]{3}$
124
88
  ```
125
89
 
126
- 归一化:trim;REQ/FEAT 段大写;SCN slug 小写。编号五律摘要:REQ/FEAT 仅需求系统铸号;SCN 由 kld-sdd/opsx-spec 铸号;编号≠身份;归属权威在需求系统;历史绑定 append-only。
90
+ 归一化:trim;requirement/feature 段大写;SCN slug 小写。编号五律摘要:requirement/feature 由外部需求系统铸号(格式不限 REQ-/FEAT- 前缀,白名单 A-Z 0-9 - _);SCN 由 kld-sdd/opsx-spec 铸号;编号≠身份;归属权威在需求系统;历史绑定 append-only。
127
91
 
128
92
  > 按功能号圈能力(FEAT query)、match-requirement / resolve 完整 curl 示例与响应字段解读 → [reference.md](reference.md)。
129
93
 
@@ -148,16 +112,14 @@ scenario: ^REQ-…:SCN-[a-z0-9]+(-[a-z0-9]+)*-[0-9]{3}$
148
112
  - 无 `apiKey` 不得猜密钥、不得改走 login。
149
113
  - 无 `targets` 不得臆造 spaceId/kbId。
150
114
  - 无命中 → 写明「无当前依据」,禁止编造条款。
151
- - 完整 apiKey 只写共享 state 文件(`../.shared/kb-state.json`);聊天里最多显示前缀(如 `sk_sdd_****`)。
115
+ - 完整 apiKey 只写共享 state 文件(`kb-state.json`,spec 仓根目录);聊天里最多显示前缀(如 `sk_sdd_****`)。
152
116
  - **共享状态**:state 文件与 `opsx-kb-ingest` 共用。配置一次,两个 skill 都生效。
153
117
 
154
118
  ## 用户口令
155
119
 
156
120
  | 用户说 | Agent 做 |
157
121
  |--------|----------|
158
- | (首次使用) | key KB(多选)→ 写共享 state → 再查。此后 `opsx-kb-ingest` 也自动可用 |
159
- | 换密钥 / 重置 API Key | 清 apiKey,重走 Session 第 2 步 |
160
- | 重新选择 / 重置空间或知识库 | 清 targets,重走 Session 第 3 步 |
122
+ | 配置 / 换密钥 / KB | 引导运行 `/opsx-kb-config`(本技能不处理配置) |
161
123
  | 查 / Spec 复用 / 影响… | 用当前共享 targets 查询 |
162
124
 
163
125
  ## 心智模型
@@ -216,8 +216,8 @@ curl -sS -H "Authorization: Bearer $API_KEY" \
216
216
  |----------|------|----------|
217
217
  | `VERSION_CONFLICT` | predecessor 不匹配当前 version | 回 spec 获取正确 predecessor,重新 archive |
218
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 前缀 |
219
+ | `EXTERNAL_REFERENCE_FORMAT_INVALID` | 编号含非白名单字符(A-Z 0-9 - _ 之外的字符)或超长 | 检查外部编号来源,修正后重新入库 |
220
+ | `EXTERNAL_REFERENCE_SCOPE_MISMATCH` | 场景键需求编号前缀不在同包 requirement 集合 | 回 spec 修正 external-ref 中场景键的需求编号前缀 |
221
221
  | `EXTERNAL_REFERENCE_FEATURE_UNBOUND` | feature 绑定与 requirement.`feature_id` 无法配对 | 回 propose/archive 修正线缆字段,确认 FEAT 号存在 |
222
222
 
223
223
  > **禁止**在 KB 内现场改绑或解绑。必须回 SDD 流程修正后重新入库。
@@ -8,7 +8,7 @@
8
8
 
9
9
  ```json
10
10
  {
11
- "api": "http://localhost:8090/api",
11
+ "api": "http://10.29.213.80:8080/api",
12
12
  "tenantKey": "default",
13
13
  "apiKey": "sk_sdd_…",
14
14
  "updatedAt": "2026-07-19T12:00:00Z",