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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kld-sdd",
3
- "version": "2.6.8",
3
+ "version": "2.6.9",
4
4
  "description": "KLD SDD OpenSpec 项目初始化工具 - 一键部署 SDD skills",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -5,6 +5,7 @@ const fs = require('fs');
5
5
  const http = require('http');
6
6
  const https = require('https');
7
7
  const { URL } = require('url');
8
+ const path = require('path');
8
9
 
9
10
  function parseArgs(argv) {
10
11
  const args = {};
@@ -71,10 +72,16 @@ function requestJson(url, payload, token, timeoutMs) {
71
72
  reject(new Error(`knowledge base returned invalid JSON (HTTP ${response.statusCode})`));
72
73
  return;
73
74
  }
74
- if (response.statusCode >= 400 || parsed?.code !== 0) {
75
+ if (response.statusCode >= 400) {
75
76
  reject(new Error(parsed?.message || `knowledge base HTTP ${response.statusCode}`));
76
77
  return;
77
78
  }
79
+ // code 字段仅当存在且不为 0 时才视为业务错误(health/ingest 等管理 API 返回 code,
80
+ // 但 resolve/search 等 context API 直接返回 data,不包含 code 字段)
81
+ if (parsed?.code != null && parsed.code !== 0) {
82
+ reject(new Error(parsed?.message || `knowledge base error code ${parsed.code}`));
83
+ return;
84
+ }
78
85
  resolve(parsed.data);
79
86
  });
80
87
  },
@@ -149,8 +156,57 @@ function buildPayload(args, mode) {
149
156
  }
150
157
 
151
158
  async function retrieveContext(args = parseArgs(process.argv), env = process.env) {
152
- const spaceId = args['space-id'] || env.ENGINEERING_KB_SPACE_ID || '';
153
- const kbId = args['kb-id'] || env.ENGINEERING_KB_KB_ID || '';
159
+ // 优先从共享 state 文件读取配置(与 opsx-ontology-query / opsx-kb-ingest 共用)
160
+ // 搜索多个可能的 IDE skills 目录(.codebuddy / .claude / .cursor 等)
161
+ let stateConfig = {};
162
+ const stateFile = args['state-file'] || env.SDD_KB_STATE_FILE;
163
+ const candidatePaths = [];
164
+ if (stateFile) candidatePaths.push(stateFile);
165
+ // 从 skywalk-sdd 目录向上查找 skills/.shared/kb-state.json
166
+ const ideDirs = ['.codebuddy', '.claude', '.cursor', '.vscode'];
167
+ for (const ide of ideDirs) {
168
+ candidatePaths.push(path.join(__dirname, '..', ide, 'skills', '.shared', 'kb-state.json'));
169
+ }
170
+ // 也检查 skywalk-sdd 同级的 .shared
171
+ candidatePaths.push(path.join(__dirname, '.shared', 'kb-state.json'));
172
+ for (const p of candidatePaths) {
173
+ try {
174
+ if (fs.existsSync(p)) {
175
+ stateConfig = JSON.parse(fs.readFileSync(p, 'utf8'));
176
+ break;
177
+ }
178
+ } catch (_) { /* try next */ }
179
+ }
180
+
181
+ const apiBase = args['api-base'] || stateConfig.api || env.ENGINEERING_KB_API || 'http://localhost:8090/api';
182
+ const token = args.token || stateConfig.apiKey || env.ENGINEERING_KB_TOKEN || '';
183
+ const spaceId = args['space-id'] || env.ENGINEERING_KB_SPACE_ID ||
184
+ (stateConfig.targets && stateConfig.targets.length > 0 ? stateConfig.targets[0].spaceId : '');
185
+ const kbId = args['kb-id'] || env.ENGINEERING_KB_KB_ID ||
186
+ (stateConfig.targets && stateConfig.targets.length > 0 ? stateConfig.targets[0].kbId : '');
187
+
188
+ // --check-only: 只检查 KB 配置是否就绪,不发起 API 请求
189
+ // 用于 SDD 各阶段(propose/spec/design/task/check)统一检测 KB 可用性,消除相对路径歧义
190
+ if (args['check-only']) {
191
+ const missing = [];
192
+ if (!token) missing.push('apiKey');
193
+ if (!spaceId) missing.push('spaceId');
194
+ if (!kbId) missing.push('kbId');
195
+ if (missing.length > 0) {
196
+ return {
197
+ available: false,
198
+ reason: 'engineering_kb_not_configured',
199
+ missing,
200
+ hint: 'Run opsx-ontology-query Session startup to configure .shared/kb-state.json',
201
+ };
202
+ }
203
+ return {
204
+ available: true,
205
+ api: apiBase,
206
+ targets: stateConfig.targets || [],
207
+ };
208
+ }
209
+
154
210
  if (!spaceId || !kbId) {
155
211
  return {
156
212
  available: false,
@@ -162,8 +218,6 @@ async function retrieveContext(args = parseArgs(process.argv), env = process.env
162
218
  }
163
219
 
164
220
  const mode = String(args.mode || 'match').trim().toLowerCase() === 'resolve' ? 'resolve' : 'match';
165
- const apiBase = args['api-base'] || env.ENGINEERING_KB_API || 'http://localhost:8090/api';
166
- const token = args.token || env.ENGINEERING_KB_TOKEN || '';
167
221
  const timeoutMs = Number(args.timeout || env.ENGINEERING_KB_TIMEOUT_MS || 30000);
168
222
  const payload = buildPayload(args, mode);
169
223
  const data = await requestJson(
@@ -0,0 +1,148 @@
1
+ ---
2
+ name: openspec-sync-specs
3
+ description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.
4
+ allowed-tools: Bash(openspec:*)
5
+ license: MIT
6
+ compatibility: Requires openspec CLI.
7
+ metadata:
8
+ author: openspec
9
+ version: "1.0"
10
+ generatedBy: "1.6.0"
11
+ ---
12
+
13
+ Sync delta specs from a change to main specs.
14
+
15
+ This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).
16
+
17
+ **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store <id>` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`). Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root.
18
+
19
+ **Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
20
+
21
+ **Steps**
22
+
23
+ 1. **If no change name provided, prompt for selection**
24
+
25
+ Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.
26
+
27
+ Show changes that have delta specs (under `specs/` directory).
28
+
29
+ **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
30
+
31
+ 2. **Resolve change context**
32
+
33
+ Run:
34
+ ```bash
35
+ openspec status --change "<name>" --json
36
+ ```
37
+
38
+ 3. **Find delta specs**
39
+
40
+ Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the list of delta spec files.
41
+
42
+ Each delta spec file contains sections like:
43
+ - `## ADDED Requirements` - New requirements to add
44
+ - `## MODIFIED Requirements` - Changes to existing requirements
45
+ - `## REMOVED Requirements` - Requirements to remove
46
+ - `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)
47
+
48
+ If no delta specs found, inform user and stop.
49
+
50
+ 4. **For each delta spec, apply changes to main specs**
51
+
52
+ For each repo-local capability delta spec path returned by the CLI:
53
+
54
+ a. **Read the delta spec** to understand the intended changes
55
+
56
+ b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)
57
+
58
+ c. **Apply changes intelligently**:
59
+
60
+ **ADDED Requirements:**
61
+ - If requirement doesn't exist in main spec → add it
62
+ - If requirement already exists → update it to match (treat as implicit MODIFIED)
63
+
64
+ **MODIFIED Requirements:**
65
+ - Find the requirement in main spec
66
+ - Apply the changes - this can be:
67
+ - Adding new scenarios (don't need to copy existing ones)
68
+ - Modifying existing scenarios
69
+ - Changing the requirement description
70
+ - Preserve scenarios/content not mentioned in the delta
71
+
72
+ **REMOVED Requirements:**
73
+ - Remove the entire requirement block from main spec
74
+
75
+ **RENAMED Requirements:**
76
+ - Find the FROM requirement, rename to TO
77
+
78
+ d. **Create new main spec** if capability doesn't exist yet:
79
+ - Create `openspec/specs/<capability>/spec.md`
80
+ - Add Purpose section (can be brief, mark as TBD)
81
+ - Add Requirements section with the ADDED requirements
82
+
83
+ 5. **Show summary**
84
+
85
+ After applying all changes, summarize:
86
+ - Which capabilities were updated
87
+ - What changes were made (requirements added/modified/removed/renamed)
88
+
89
+ **Delta Spec Format Reference**
90
+
91
+ ```markdown
92
+ ## ADDED Requirements
93
+
94
+ ### Requirement: New Feature
95
+ The system SHALL do something new.
96
+
97
+ #### Scenario: Basic case
98
+ - **WHEN** user does X
99
+ - **THEN** system does Y
100
+
101
+ ## MODIFIED Requirements
102
+
103
+ ### Requirement: Existing Feature
104
+ #### Scenario: New scenario to add
105
+ - **WHEN** user does A
106
+ - **THEN** system does B
107
+
108
+ ## REMOVED Requirements
109
+
110
+ ### Requirement: Deprecated Feature
111
+
112
+ ## RENAMED Requirements
113
+
114
+ - FROM: `### Requirement: Old Name`
115
+ - TO: `### Requirement: New Name`
116
+ ```
117
+
118
+ **Key Principle: Intelligent Merging**
119
+
120
+ Unlike programmatic merging, you can apply **partial updates**:
121
+ - To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios
122
+ - The delta represents *intent*, not a wholesale replacement
123
+ - Use your judgment to merge changes sensibly
124
+
125
+ **Output On Success**
126
+
127
+ ```
128
+ ## Specs Synced: <change-name>
129
+
130
+ Updated main specs:
131
+
132
+ **<capability-1>**:
133
+ - Added requirement: "New Feature"
134
+ - Modified requirement: "Existing Feature" (added 1 scenario)
135
+
136
+ **<capability-2>**:
137
+ - Created new spec file
138
+ - Added requirement: "Another Feature"
139
+
140
+ Main specs are now updated. The change remains active - archive when implementation is complete.
141
+ ```
142
+
143
+ **Guardrails**
144
+ - Read both delta and main specs before making changes
145
+ - Preserve existing content not mentioned in delta
146
+ - If something is unclear, ask for clarification
147
+ - Show what you're changing as you go
148
+ - The operation should be idempotent - running twice should give same result
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: openspec-update-change
3
+ description: Update an OpenSpec change by revising its existing planning artifacts and keeping them coherent with one another. Use when the user wants to revise a change's plan, fold new decisions into it, or reconcile its artifacts after an edit. Never edits code.
4
+ allowed-tools: Bash(openspec:*)
5
+ license: MIT
6
+ compatibility: Requires openspec CLI.
7
+ metadata:
8
+ author: openspec
9
+ version: "1.0"
10
+ generatedBy: "1.6.0"
11
+ ---
12
+
13
+ Revise a change's existing planning artifacts and keep them coherent. Never edit code.
14
+
15
+ **Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store <id>` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`). Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root.
16
+
17
+ **Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
18
+
19
+ **Steps**
20
+
21
+ 1. **If no change name provided, prompt for selection**
22
+
23
+ Run `openspec list --json` to get available changes sorted by most recently modified. Then use the **AskUserQuestion tool** to let the user select which change to update.
24
+
25
+ Present the top 3-4 most recently modified changes as options, showing:
26
+ - Change name
27
+ - Schema (from `schema` field if present, otherwise "spec-driven")
28
+ - Status (e.g., "0/5 tasks", "complete", "no tasks")
29
+ - How recently it was modified (from `lastModified` field)
30
+
31
+ Mark the most recently modified change as "(Recommended)" since it's likely what the user wants to update.
32
+
33
+ **IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
34
+
35
+ 2. **Get the change's artifacts**
36
+ ```bash
37
+ openspec status --change "<name>" --json
38
+ ```
39
+ Parse the JSON to understand current state. The response includes:
40
+ - `schemaName`: The workflow schema being used (e.g., "spec-driven")
41
+ - `artifacts`: Array of artifacts with their status ("done", "ready", "blocked")
42
+ - `isComplete`: Boolean indicating if all artifacts are complete
43
+ - `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths.
44
+
45
+ The artifact ids and paths come from the active schema - do NOT assume them, and do NOT branch on hardcoded artifact names. Custom schemas must work unchanged.
46
+
47
+ The files to edit are `artifactPaths.<id>.existingOutputPaths` - the concrete files that exist on disk, already glob-expanded for glob artifacts (e.g. `specs/**/*.md`). Do NOT write to `resolvedOutputPath`: for a glob artifact it is still the glob pattern, not a real file.
48
+
49
+ 3. **Understand the request**
50
+ - If the user asked for a specific revision ("the design now uses X"), that is the starting edit.
51
+ - If they only said "update" / "make this coherent", treat it as a coherence review: read the existing artifacts and check them against each other for contradictions, gaps, and duplication.
52
+
53
+ 4. **Read and reconcile**
54
+ - Read the artifact(s) the request touches and the change's other existing artifacts.
55
+ - Apply the requested edit. Then check every other existing artifact against it - in ANY direction: an edit to a later artifact may require revising an earlier one, not only the other way around. Build order is a useful reading order, not a constraint on which artifacts may be revised.
56
+ - Note everything that is now inconsistent, missing, or contradictory.
57
+ - Revise only files that already exist (`existingOutputPaths`). Do NOT create artifacts that don't exist yet, and do NOT invent new files under a glob artifact - note them and point the user to `/opsx:continue` to create them.
58
+ - If the change is already coherent, say so and make no edits.
59
+
60
+ 5. **Confirm and apply, one artifact at a time**
61
+ - Show each proposed revision and why. Write only after the user confirms.
62
+ - If the user rejects a revision, do not write it - leave that artifact unchanged.
63
+ - When a substantial rewrite is needed, get that artifact's rules and template first:
64
+ ```bash
65
+ openspec instructions <artifact-id> --change "<name>" --json
66
+ ```
67
+
68
+ 6. **Point to the next step (guidance only - NEVER act on it)**
69
+ - Artifacts still missing -> suggest `/opsx:continue` to create them.
70
+ - Change already implemented (tasks checked off / already applied) -> the code may no longer match the revised plan; suggest `/opsx:apply` to carry the delta into code.
71
+ - Everything done and implemented -> suggest `/opsx:archive`.
72
+
73
+ **Output**
74
+
75
+ After each invocation, show:
76
+ - Which artifacts were revised (and which proposed revisions were rejected)
77
+ - Anything deferred to `/opsx:continue` (not-yet-created artifacts or files)
78
+ - Where the change stands and the recommended next command
79
+
80
+ **Guardrails**
81
+ - Planning artifacts only - NEVER edit implementation code. If the revised plan implies code changes, stop and point to `/opsx:apply`.
82
+ - Use the artifact ids and paths reported by `openspec status`; never branch on hardcoded artifact names.
83
+ - Edit only the concrete files in `existingOutputPaths`; never write to a glob `resolvedOutputPath`.
84
+ - Do not advance the build frontier: no new artifacts, no new files under glob artifacts - that is `/opsx:continue`'s job.
85
+ - Confirm every edit with the user before writing.
86
+ - If the request changes the change's *intent* rather than refining it, recommend starting fresh with `/opsx:new` (the "Update vs. Start Fresh" heuristic).
@@ -17,7 +17,7 @@ allowed-tools:
17
17
 
18
18
  你是一个 SDD(Specification-Driven Development)变更归档专家。激活本技能后,你要安全地结束变更生命周期:真实归档文档、同步正式 specs、记录 archive telemetry,并生成最终中文度量报告。
19
19
 
20
- > **硬依赖(收尾入库)**:zip 生成后的上传依赖同级已部署的 **`opsx-kb-ingest`**。进入 §5.5 前必须先 `Read` 该技能的 `SKILL.md` 并完成其 Session 启动。缺失则提示用户重新 `kld-sdd-init`,**不要**自造另一套入库协议。
20
+ > **硬依赖(收尾入库)**:zip 生成后的上传依赖同级已部署的 **`opsx-kb-ingest`**。进入 §5.5 前必须先 `Read` 该技能的 `SKILL.md` 并完成其 Session 启动。入库成功后,`Read` `opsx-ontology-query/phase-3-postchange.md` 验证版本生效、AC 保留、关系完整性。缺失则提示用户重新 `kld-sdd-init`,**不要**自造另一套入库协议。
21
21
 
22
22
  > **跨平台执行规则**
23
23
  > - 先确认当前终端工作目录是项目根目录;若不是,先 `cd` 到项目根目录。
@@ -3,7 +3,8 @@ name: opsx-check
3
3
  description: "质量检查技能 - 验证文档完整性、一致性、算法正确性及可执行性"
4
4
  argument-hint: "[change-name] [上下文文件...]"
5
5
  license: MIT
6
- compatibility: Requires openspec CLI.
6
+ compatibility: Requires openspec CLI; depends on opsx-ontology-query for external-key validation and baseline checks.
7
+ depends-on: opsx-ontology-query
7
8
  metadata:
8
9
  author: sdd-team
9
10
  version: "3.0"
@@ -25,6 +26,10 @@ allowed-tools:
25
26
  > 即使检查发现代码相关问题,也只记录在检查报告中,**不自动修复代码**。
26
27
  > 代码修复将在 `/opsx-apply` 阶段进行。
27
28
 
29
+ > **KB 上下文**:check 阶段需验证外部键格式(REQ/FEAT/SCN 文法)、SCN REQ 前缀一致性和历史覆盖率基线。进入相关步骤前先 `Read` `opsx-ontology-query/phase-2-during.md` §3-5,并按 `SKILL.md` → Session 启动准备 API Key + targets。
30
+ >
31
+ > **📡 KB 就绪检查**:§2.6 在进入 KB 相关检查前会检测 KB 配置状态。若未配置,会**主动询问**用户选择「配置」或「跳过」,KB 相关检查项降级为仅本地验证。
32
+
28
33
 
29
34
  > **🖥️ 跨平台执行规则**
30
35
  > - 先确认当前终端工作目录是项目根目录;若不是,先 `cd` 到项目根目录。
@@ -106,6 +111,34 @@ node skywalk-sdd/ontology/cli.cjs diagnose-naming --project=. --mode=code-repo
106
111
 
107
112
  最终检查报告必须包含「多仓库关联配置」章节(命令输出已按此格式打印)。
108
113
 
114
+ ### 2.6 【KB 就绪检查】检测并配置知识库连接
115
+
116
+ 在进入 KB 相关检查(外部键验证、coverage 基线)之前,检测 Engineering KB 的连接状态。
117
+
118
+ 1. 检查 proposal.md frontmatter 中 `kb-status` 字段:
119
+ - 若 `kb-status: degraded(by-user-choice)` → KB 已被用户明确跳过,本阶段 KB 相关检查降级为仅本地验证(external-key 格式校验 + 本地 semantic-check),跳过 KB API 调用。
120
+ - 若未标记 → 继续检查。
121
+ 2. 运行 KB 就绪检查(程序化检测,自动搜索多 IDE 目录,消除路径歧义):
122
+ ```bash
123
+ node skywalk-sdd/context-client.cjs --check-only
124
+ ```
125
+ - 输出 `"available": true` → KB 已配置
126
+ - 输出 `"available": false` → KB 未配置
127
+ 3. **若已配置** → 直接进入 §3,正常使用 KB 做 coverage 基线、predecessor 预检。
128
+ 4. **若未配置** → 使用 **AskUserQuestion** 询问:
129
+
130
+ > "📡 **Engineering KB 未配置**
131
+ >
132
+ > KB 可以提供覆盖率基线检查、predecessor 版本预检(防止入库冲突)。是否现在配置?
133
+ >
134
+ > - A. **配置 KB**
135
+ > - B. **跳过 KB**,仅执行本地检查(semantic-check + external-key 格式校验),入库前无 predecessor 预检
136
+ > - C. **取消操作**"
137
+
138
+ - **选 A** → 配置 → 进入 §3。
139
+ - **选 B** → KB 相关检查项降级:coverage 基线跳过、`current-version` 预检跳过。检查报告中标注 `kb: degraded(by-user-choice)`。
140
+ - **选 C** → 终止 check。
141
+
109
142
  ### 3. 【上下文加载】识别并读取用户提供的文件
110
143
 
111
144
  **自动识别上下文文件**:
@@ -27,6 +27,15 @@ allowed-tools:
27
27
  > **完成本阶段后,绝对禁止自动继续执行 task 等后续阶段。**
28
28
  > 阶段边界自检见 `./checklist.md`「阶段边界⛔」。
29
29
 
30
+ > **KB 上下文**:设计时可参考历史设计决策。
31
+ > 1. 检查 proposal.md frontmatter `kb-status`:若 `degraded(by-user-choice)` → 跳过 KB,仅用本地上下文。
32
+ > 2. 否则运行 KB 就绪检查:
33
+ > ```bash
34
+ > node skywalk-sdd/context-client.cjs --check-only
35
+ > ```
36
+ > - `"available": true` → 若需查历史设计参考,先 `Read` `opsx-ontology-query/phase-2-during.md` §1
37
+ > - `"available": false` → **KB 不可用不阻塞 design 流程**,仅跳过历史设计参考查询
38
+
30
39
  > **⚠️ 渐进式上下文加载原则**
31
40
  >
32
41
  > - 本技能针对**单一 Capability** 执行设计(Simple 模式例外,见下方 S1 说明)
@@ -13,20 +13,14 @@ description: >-
13
13
 
14
14
  > 控制台知识库页另有浮动 Ontology Agent(会话登录 + SSE);本 Skill 仍走 API Key,二者分开。
15
15
 
16
- 本地状态文件(含密钥,勿提交):
17
-
18
- ```text
19
- skills/opsx-kb-ingest/.local/state.json
20
- ```
21
-
22
- 字段说明 → [reference.md](reference.md)。
16
+ > **📡 共享状态**:本技能与 `opsx-ontology-query` **共用同一份 KB 配置**(`../.shared/kb-state.json`)。任一 skill 配置后,另一个自动可用,无需重复输入 API Key。
23
17
 
24
18
  ## Session 启动(每次用本 Skill 必做)
25
19
 
26
20
  ```
27
21
  Task Progress:
28
- - [ ] 1. 读 .local/state.json(没有则当空)
29
- - [ ] 2. 无 apiKey → 向用户索取并写入 state(勿把完整 key 打进聊天摘要)
22
+ - [ ] 1. 读 ../.shared/kb-state.json(没有则当空)
23
+ - [ ] 2. 无 apiKey → 向用户索取并写入共享 state(勿把完整 key 打进聊天摘要)
30
24
  - [ ] 3. 无 targets 或用户要重置 → 拉空间/KB 列表,让用户多选后写入
31
25
  - [ ] 4. 按意图执行入库操作(上传 / 查状态 / 列表 / 重试)
32
26
  - [ ] 5. 按模板输出结果
@@ -36,9 +30,9 @@ Task Progress:
36
30
 
37
31
  若 `state.apiKey` 为空或无效(401/403):
38
32
 
39
- 1. 请用户提供 API Key(控制台「API 密钥」创建,至少含 `archive:ingest`)。
33
+ 1. 请用户提供 API Key(控制台「API 密钥」创建,至少含 `archive:ingest`。建议同时勾选 `context:read`,使 `opsx-ontology-query` 也能复用此 Key)。
40
34
  2. 可选:请用户确认 `api`(默认 `http://localhost:8090/api`)与 `tenantKey`(默认 `default`)。
41
- 3. 写入 `.local/state.json`(创建目录若不存在)。
35
+ 3. 写入共享 `../.shared/kb-state.json`(创建目录若不存在)。
42
36
  4. 用 `GET $API/health` 探活;再用 `GET $API/v1/spaces?tenantKey=…` + Bearer 校验 key。
43
37
 
44
38
  用户说「换密钥 / 重置 API Key」→ 清空 `apiKey`(可保留 targets),回到本步。
@@ -165,17 +159,18 @@ curl -sS -X POST "$API/v1/spaces/$SPACE_ID/knowledge-bases/$KB_ID/ingestions/$JO
165
159
  - 无 `targets` 不得臆造 spaceId/kbId。
166
160
  - 上传前确认 zip 包路径存在且为有效 zip 文件。
167
161
  - 入库失败时展示 `errorCode` 和 `errorMessage`,不编造原因。
168
- - 完整 apiKey 只写 state 文件;聊天里最多显示前缀(如 `sk_sdd_****`)。
162
+ - 完整 apiKey 只写共享 state 文件(`../.shared/kb-state.json`);聊天里最多显示前缀(如 `sk_sdd_****`)。
169
163
  - 401/403 时清掉 `apiKey`,请用户重贴;勿循环重试。
164
+ - **共享状态**:state 文件与 `opsx-ontology-query` 共用。如用户此前已通过查询 skill 配置过 KB,本 skill 启动时直接读取已有配置,无需重复询问。
170
165
 
171
166
  ## 用户口令
172
167
 
173
168
  | 用户说 | Agent 做 |
174
169
  |--------|----------|
175
- | (首次使用) | 要 key → 选 KB(多选)→ 再操作 |
170
+ | (首次使用) | 要 key → 选 KB(多选)→ 写共享 state → 再操作。此后 `opsx-ontology-query` 也自动可用 |
176
171
  | 换密钥 / 重置 API Key | 清 apiKey,重走第 2 步 |
177
172
  | 重新选择 / 重置空间或知识库 | 清 targets,重走第 3 步 |
178
- | 上传 / 入库 | 用当前 targets 中选中的 KB 上传 zip |
173
+ | 上传 / 入库 | 用当前共享 targets 中选中的 KB 上传 zip |
179
174
  | 查状态 / 看任务 | 用 jobId 查询任务状态 |
180
175
  | 列任务 / 看历史 | 列出最近入库任务 |
181
176
  | 重试 | 对失败的 jobId 执行重试 |