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
@@ -153,9 +153,10 @@ if (require.main === module) {
153
153
  process.exit(0);
154
154
  }
155
155
 
156
- // G4: 批量更新检测
157
- if (changes.length > 3) {
158
- // 安全网 2: 全部有 task_update 遥测 → check-task 合法更新,放行
156
+ // G4: 批量更新检测(E1 修正:不再提前退出,模式检查继续执行)
157
+ var skipPerTaskCheck = false;
158
+ if (changes.length >= 2 && hasTddTasks) {
159
+ // 安全网 2: 全部有 task_update 遥测 → check-task 合法更新,跳过逐个检查
159
160
  const allHaveTaskUpdate = changes.every(change =>
160
161
  events.some(e => e.type === 'task_update' && e.task_id === change.taskId));
161
162
  if (!allHaveTaskUpdate) {
@@ -164,79 +165,126 @@ if (require.main === module) {
164
165
  '⛔ 禁止批量修改任务状态。必须逐个通过 task_update → check-task 流程更新。\n' +
165
166
  `批量变更的任务: ${changes.map(c => c.taskId).join(', ')}`);
166
167
  }
167
- process.exit(0); // 合法批量更新,放行
168
+ // E1 修正:有 task_update → 跳过逐个证据检查,但模式检查继续执行
169
+ skipPerTaskCheck = true;
168
170
  }
169
171
 
170
- // 逐个检查
171
- for (const change of changes) {
172
- const { taskId, taskType } = change;
173
-
174
- if (taskType === 'red') {
175
- const hasRedEvidence = events.some(e =>
176
- e.type === 'test_result' && e.task_id === taskId &&
177
- e.result === 'failure' &&
178
- e.details && e.details.test_results && e.details.test_results.tdd_phase === 'red');
179
- if (!hasRedEvidence) {
180
- core.blockWithReason(
181
- `[SDD TDD Rhythm Gate] 任务 ${taskId} 是 RED 任务,标记完成前必须先运行测试并确认失败。\n\n` +
182
- '未检测到对应的 test_result(result=failure, tdd_phase=red) 遥测事件。\n' +
183
- '请先运行测试确认 RED 失败,记录 test_result 后再标记任务完成。');
184
- }
185
- }
172
+ // 逐个检查(E1 修正:批量安全网触发时跳过逐个检查,但模式检查仍执行)
173
+ if (!skipPerTaskCheck) {
174
+ for (const change of changes) {
175
+ const { taskId, taskType } = change;
186
176
 
187
- if (taskType === 'green') {
188
- const hasGreenEvidence = events.some(e =>
189
- e.type === 'test_result' && e.task_id === taskId &&
190
- e.result === 'success' &&
191
- e.details && e.details.test_results && e.details.test_results.tdd_phase === 'green');
192
- if (!hasGreenEvidence) {
193
- core.blockWithReason(
194
- `[SDD TDD Rhythm Gate] 任务 ${taskId} 是 GREEN 任务,标记完成前必须先运行测试并确认通过。\n\n` +
195
- '未检测到对应的 test_result(result=success, tdd_phase=green) 遥测事件。\n' +
196
- '请先运行测试确认 GREEN 通过,记录 test_result 后再标记任务完成。');
177
+ if (taskType === 'red') {
178
+ const hasRedEvidence = events.some(e =>
179
+ e.type === 'test_result' && e.task_id === taskId &&
180
+ e.result === 'failure' &&
181
+ e.details && e.details.test_results && e.details.test_results.tdd_phase === 'red');
182
+ if (!hasRedEvidence) {
183
+ core.blockWithReason(
184
+ `[SDD TDD Rhythm Gate] 任务 ${taskId} 是 RED 任务,标记完成前必须先运行测试并确认失败。\n\n` +
185
+ '未检测到对应的 test_result(result=failure, tdd_phase=red) 遥测事件。\n' +
186
+ '请先运行测试确认 RED 失败,记录 test_result 后再标记任务完成。');
187
+ }
197
188
  }
198
- // G5: RED→GREEN 间隔检查
199
- const pairedRedTaskId = findPairedRedTaskId(newContent, taskId);
200
- if (pairedRedTaskId) {
201
- const redEvent = events.find(e =>
202
- e.type === 'test_result' && e.task_id === pairedRedTaskId && e.result === 'failure');
203
- const greenEvent = events.find(e =>
204
- e.type === 'test_result' && e.task_id === taskId && e.result === 'success');
205
- if (redEvent && greenEvent) {
206
- const gap = (new Date(greenEvent.timestamp).getTime() -
207
- new Date(redEvent.timestamp).getTime()) / 1000;
208
- if (gap < 60) {
209
- core.blockWithReason(
210
- `[SDD TDD Rhythm Gate] TDD 节奏异常:\n\n` +
211
- `任务 ${taskId}(GREEN) ${pairedRedTaskId}(RED) 的测试执行间隔仅 ${gap} 秒,建议 >60 秒。\n` +
212
- '可能存在批量执行或跳过 RED 阶段的情况。');
189
+
190
+ if (taskType === 'green') {
191
+ const hasGreenEvidence = events.some(e =>
192
+ e.type === 'test_result' && e.task_id === taskId &&
193
+ e.result === 'success' &&
194
+ e.details && e.details.test_results && e.details.test_results.tdd_phase === 'green');
195
+ if (!hasGreenEvidence) {
196
+ core.blockWithReason(
197
+ `[SDD TDD Rhythm Gate] 任务 ${taskId} 是 GREEN 任务,标记完成前必须先运行测试并确认通过。\n\n` +
198
+ '未检测到对应的 test_result(result=success, tdd_phase=green) 遥测事件。\n' +
199
+ '请先运行测试确认 GREEN 通过,记录 test_result 后再标记任务完成。');
200
+ }
201
+ // G5: RED→GREEN 间隔检查
202
+ const pairedRedTaskId = findPairedRedTaskId(newContent, taskId);
203
+ if (pairedRedTaskId) {
204
+ const redEvent = events.find(e =>
205
+ e.type === 'test_result' && e.task_id === pairedRedTaskId && e.result === 'failure');
206
+ const greenEvent = events.find(e =>
207
+ e.type === 'test_result' && e.task_id === taskId && e.result === 'success');
208
+ if (redEvent && greenEvent) {
209
+ const gap = (new Date(greenEvent.timestamp).getTime() -
210
+ new Date(redEvent.timestamp).getTime()) / 1000;
211
+ if (gap < 60) {
212
+ core.blockWithReason(
213
+ `[SDD TDD Rhythm Gate] TDD 节奏异常:\n\n` +
214
+ `任务 ${taskId}(GREEN) 与 ${pairedRedTaskId}(RED) 的测试执行间隔仅 ${gap} 秒,建议 >60 秒。\n` +
215
+ '可能存在批量执行或跳过 RED 阶段的情况。');
216
+ }
213
217
  }
214
218
  }
215
219
  }
216
- }
217
220
 
218
- if (taskType === 'refactor') {
219
- const hasRefactorEvidence = events.some(e =>
220
- e.type === 'test_result' && e.task_id === taskId &&
221
- e.result === 'success' &&
222
- e.details && e.details.test_results && e.details.test_results.tdd_phase === 'refactor');
223
- if (!hasRefactorEvidence) {
224
- core.blockWithReason(
225
- `[SDD TDD Rhythm Gate] 任务 ${taskId} 是 REFACTOR 任务,` +
226
- '标记完成前必须先运行测试确认全部通过(测试仍绿)。\n\n' +
227
- '未检测到对应的 test_result(result=success, tdd_phase=refactor) 遥测事件。');
221
+ if (taskType === 'refactor') {
222
+ const hasRefactorEvidence = events.some(e =>
223
+ e.type === 'test_result' && e.task_id === taskId &&
224
+ e.result === 'success' &&
225
+ e.details && e.details.test_results && e.details.test_results.tdd_phase === 'refactor');
226
+ if (!hasRefactorEvidence) {
227
+ core.blockWithReason(
228
+ `[SDD TDD Rhythm Gate] 任务 ${taskId} 是 REFACTOR 任务,` +
229
+ '标记完成前必须先运行测试确认全部通过(测试仍绿)。\n\n' +
230
+ '未检测到对应的 test_result(result=success, tdd_phase=refactor) 遥测事件。');
231
+ }
228
232
  }
229
- }
230
233
 
231
- // 安全网 3: unknown 类型降级为警告
232
- if (taskType === 'unknown') {
233
- console.log(JSON.stringify({
234
- decision: 'allow',
235
- message: `⚠️ [SDD TDD Rhythm Gate] 任务 ${taskId} 的类型字段无法识别,已放行。` +
236
- '建议补全 **类型** 字段,可选值:测试-RED | 实现-GREEN | 重构-REFACTOR | 配置 | 数据层 | 接口层 | 接口测试',
237
- }));
234
+ // 安全网 3: unknown 类型降级为警告
235
+ if (taskType === 'unknown') {
236
+ console.log(JSON.stringify({
237
+ decision: 'allow',
238
+ message: `⚠️ [SDD TDD Rhythm Gate] 任务 ${taskId} 的类型字段无法识别,已放行。` +
239
+ '建议补全 **类型** 字段,可选值:测试-RED | 实现-GREEN | 重构-REFACTOR | 配置 | 数据层 | 接口层 | 接口测试',
240
+ }));
241
+ }
242
+ // non-tdd 类型:直接放行
238
243
  }
239
- // non-tdd 类型:直接放行
244
+ }
245
+
246
+ // ═══ E1/E2/E3: 全局 TDD 批量执行模式检测(总是执行,不受 skipPerTaskCheck 影响) ═══
247
+ const batchPattern = core.detectTddBatchPattern(
248
+ events,
249
+ activeStage.timestamp,
250
+ newContent
251
+ );
252
+
253
+ if (batchPattern.has_violation && batchPattern.severity === 'critical') {
254
+ const criticalViolations = batchPattern.violations.filter(v => v.severity === 'critical');
255
+ const violationMessages = criticalViolations.map(v =>
256
+ `【${v.type}】${v.message}`
257
+ ).join('\n');
258
+
259
+ // 构建恢复引导
260
+ const tddTaskIds = batchPattern.tdd_events
261
+ .map(e => e.task_id)
262
+ .filter((v, i, a) => a.indexOf(v) === i);
263
+
264
+ core.blockWithReason(
265
+ `⛔ [SDD TDD Rhythm Gate] 检测到 TDD 批量执行违规!\n\n` +
266
+ `违规详情:\n${violationMessages}\n\n` +
267
+ `涉及任务:${tddTaskIds.join(', ')}\n\n` +
268
+ `━━━ 恢复步骤 ━━━\n` +
269
+ `1. 回退相关源代码到第一个违规任务之前的状态\n` +
270
+ `2. 逐对重新执行 RED→GREEN 循环(每对间隔 > 60 秒)\n` +
271
+ `3. 每次运行测试后记录 test_result 事件\n` +
272
+ `4. 全部重新执行后,再次更新 tasks.md\n\n` +
273
+ `注意:重新执行产生的新 test_result 事件会覆盖旧的批量事件。\n` +
274
+ `Hook 检查每个任务的最新事件,不会卡死。\n` +
275
+ `━━━━━━━━━━━━`);
276
+ }
277
+
278
+ if (batchPattern.has_violation && batchPattern.severity === 'warning') {
279
+ const warningViolations = batchPattern.violations.filter(v => v.severity === 'warning');
280
+ const warningMessages = warningViolations.map(v =>
281
+ `【${v.type}】${v.message}`
282
+ ).join('\n');
283
+ console.log(JSON.stringify({
284
+ decision: 'allow',
285
+ message: `⚠️ [SDD TDD Rhythm Gate] TDD 节奏警告:\n${warningMessages}\n` +
286
+ '建议检查是否批量执行了测试。',
287
+ }));
240
288
  }
241
289
 
242
290
  process.exit(0);
@@ -13,12 +13,16 @@ delta-state: "added"
13
13
  predecessor-version: "" # added 留空;modified/removed 指向直接前序版本
14
14
  mode: "" # full=分 Capability 产物,simple=根目录精简产物
15
15
  test-strategy: "" # tdd=测试先行, impl-first=实现优先, none=无测试
16
- # 外部需求键(默认必填 ≥1 个合规 REQ;探索性/纯内部重构可走 numbering-waiver)
16
+ change-type: "" # config | transaction | report | composite | unknown,由 Agent 自动分类
17
+ change-type-source: "agent-inferred"
18
+ change-type-confidence: "" # high | medium | low
19
+ change-type-reason: "" # 一句中文分类理由
20
+ # 外部需求键(默认必填 ≥1 个;编号格式:大写字母+数字+连字符+下划线,例 KLERP-001、REQ-FI-2024-001;探索性/纯内部重构可走 numbering-waiver)
17
21
  requirement-refs:
18
22
  - system: requirement-mgmt
19
23
  object-type: requirement
20
- external-id: REQ-<DOMAIN>-<YEAR>-<SEQ> # 例 REQ-FI-2024-001
21
- feature-id: FEAT-<DOMAIN>-<SEQ> # 可选,需求所属功能(需求系统权威)
24
+ external-id: "<外部需求编号>" # 例 KLERP-001, REQ-FI-2024-001, 1010000
25
+ feature-id: "<外部功能编号>" # 可选,需求所属功能(例 FEAT-FI-012, KLERP_F-001)
22
26
  # numbering-waiver:
23
27
  # reason: "探索性原型,本轮不种桥"
24
28
  # Continuity:字段一律来自知识库 resolve,禁止本地 archive 文件夹名
@@ -34,7 +34,7 @@ capability-id: "CAP-<CAPABILITY>" # 必须与 proposal.md 中的 Capability ID
34
34
  - **version-id**: <UUID>
35
35
  - **delta-state**: added
36
36
  - **predecessor-version**: 无
37
- - **external-ref**: requirement-mgmt:scenario:REQ-<DOMAIN>-<YEAR>-<SEQ>:SCN-<slug>-<NNN>
37
+ - **external-ref**: requirement-mgmt:scenario:<外部需求编号>:SCN-<slug>-<NNN>
38
38
  - **当** <!-- 触发条件 -->
39
39
  - **预期** <!-- 预期结果 -->
40
40
 
@@ -43,7 +43,7 @@ capability-id: "CAP-<CAPABILITY>" # 必须与 proposal.md 中的 Capability ID
43
43
  - **version-id**: <UUID>
44
44
  - **delta-state**: added
45
45
  - **predecessor-version**: 无
46
- - **external-ref**: requirement-mgmt:scenario:REQ-<DOMAIN>-<YEAR>-<SEQ>:SCN-<slug>-<NNN>
46
+ - **external-ref**: requirement-mgmt:scenario:<外部需求编号>:SCN-<slug>-<NNN>
47
47
  - **当** <!-- 触发条件 -->
48
48
  - **预期** <!-- 预期结果 -->
49
49
 
@@ -63,7 +63,7 @@ capability-id: "CAP-<CAPABILITY>" # 必须与 proposal.md 中的 Capability ID
63
63
  - **version-id**: <新 UUID>
64
64
  - **delta-state**: <modified|added>
65
65
  - **predecessor-version**: <modified 时填写;added 为无>
66
- - **external-ref**: requirement-mgmt:scenario:REQ-<DOMAIN>-<YEAR>-<SEQ>:SCN-<slug>-<NNN>
66
+ - **external-ref**: requirement-mgmt:scenario:<外部需求编号>:SCN-<slug>-<NNN>
67
67
  - **当** <!-- 触发条件 -->
68
68
  - **预期** <!-- 预期结果 -->
69
69
 
@@ -27,18 +27,20 @@ allowed-tools:
27
27
  > - ⛔ **隔离红线**:绝对禁止加载同级其他 Capability 的文档
28
28
 
29
29
  > **🖥️ 跨平台执行规则**
30
- > - **写代码**:cwd 保持在 Git 根(含 `src/`);**文档 / telemetry**:`--project` 指向 SDD 包裹包(`node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" spec-root` 可查看)。
31
- > - `openspec` 命令:优先 `node "$(cat .sdd-spec-root)/skywalk-sdd/openspec-shim.cjs" list`(自动 cd 到包裹包)。
30
+ > - **写代码**:cwd 保持在 Git 根(含 `src/`);**文档 / telemetry**:`--project` 指向 SDD 包裹包(`node <spec-package>/skywalk-sdd/spec-root.cjs` 可获取)。
31
+ > - `openspec` 命令:`cd <spec-package> && openspec …`(先 cd 到包裹包即可)。路径不确定时用 `node <spec-package>/skywalk-sdd/spec-root.cjs` 验证。
32
32
  > - Telemetry 命令默认使用 `--project=.`,兼容 Windows、macOS、Linux。
33
33
  > - ${SHELL_GUIDANCE}
34
34
  > - 不要省略 `--source=opsx-command` 与 `--session-id=<会话ID>`。
35
35
  > **📊 Telemetry(必做,不得跳过)**
36
- > - 阶段开始 / 阶段结束 / `task_update` / `ai_adoption_review` / `worktree_finish` 的**完整命令模板**见 `./reference.md`「📊 Telemetry 命令模板」。
36
+ > - 阶段开始 / 阶段结束 / `task_update` / `final_output_snapshot` / `ai_adoption_review` / `worktree_finish` 的**完整命令模板**见 `./reference.md`「📊 Telemetry 命令模板」。
37
37
  > - 不得跳过任何 telemetry 记录;`task_update` 的 `--task-id=<TASK-ID>` 必须替换为实际任务 ID,否则 E4 指标无法计算;TDD 测试骨架任务须在 `--details-json` 带 `"task_kind":"test-skeleton"`(P3,详见 `./reference.md`)。
38
38
  > - 较大的 `--details-json` 负载可先写入文件,再通过 `--details-file="$(cat .sdd-spec-root)/skywalk-sdd/state/<变更名称>-<type>.json"` 传递(例如 `task_update` 对应 `<变更名称>-task-update.json`)。
39
39
  > - `task_update` 记录成功后会自动调用 `check-task` 更新 `tasks.md` 中的 checkbox;录入成功后,agent 可以通过 `check-task` 命令验证该 checkbox 已更新。
40
40
  > - **⚠️ P1-2 ai_adoption_review 必填 ai_diff**:记录 AI 产出快照时,`--details-json` 必须含 `ai_diff.files_changed`(即使=0)与 `ai_diff.files`(产出文件路径数组,非空),**不得只发 `assertions`**。`vcs_mode=readonly` 时 `ai_diff.added_lines` 不得为 null——用只读 `git diff --numstat HEAD` 取值(apply Git 只读策略允许);`vcs_mode=no-git` 时可填 null。工具侧已加记录时硬校验:`files` 空数组或 `readonly` 下 `added_lines=null` 将 **拒绝记录**(与 conformance_review 校验对称)。缺失 `ai_diff` 会导致 report 变更文件数为 null(工具侧已加 `assertions[].files` 兜底,但 `ai_diff` 是主数据源)。完整模板见 `./reference.md`「§5.1」。
41
41
  > - **严格证据链**:一次真实测试执行只写一条严格 `test_result`;任务完成事件只通过 `test_event_id` 引用成功的 green/refactor/regression 测试,并明确 `tdd_required=true/false`,不复制测试计数。测试不适用时必须写明原因。完整 schema 见 `./reference.md`。
42
+ > - **任务涉及文件必记**:每条严格 `task_update` 必须在 `task_update.files` 写本任务实际修改的仓库相对路径;本任务确实没有改文件时,改填具体的 `no_file_change_reason`。两者至少有一个。
43
+ > - **最终交付文件必记**:apply 所有文件就绪后记录严格 `final_output_snapshot`,其中 `final_output_snapshot.files` 是最终交付文件的仓库相对路径清单。报告把它与逐任务文件分开说明;旧 `ai_adoption_review.ai_diff.files` 只作兼容来源。
42
44
  > - **process_note 必记**:用户决策、范围变化、API/模型/测试异常及恢复动作必须写严格 `process_note`;范围、模式、测试策略选择统一用 `kind=user_decision` 并标注 `decision_type`。
43
45
 
44
46
  > **🔒 Git 策略(只读增强,不改变开发流)**
@@ -254,9 +256,9 @@ g. **继续下一个层级** — 重新检查 DAG,找出依赖已满足的下
254
256
 
255
257
  此自检确保 tasks.md 的 checkbox 与实际代码状态完全同步。
256
258
 
257
- ### 5.1 【Telemetry 必做】记录 AI 产出快照
259
+ ### 5.1 【Telemetry 必做】记录最终交付文件与 AI 产出快照
258
260
 
259
- 当前 Capability AI 代码产出完成后,必须记录 `ai_adoption_review`,但不得为了采集快照自动提交 commit。**完整命令模板与说明见 `./reference.md`「§5.1 记录 AI 产出快照」**。
261
+ 当前 Capability 的全部文件就绪后,先记录 `final_output_snapshot` 作为“最终交付文件”权威口径;如需 AI 采纳率指标,再记录 `ai_adoption_review`。不得为了采集快照自动提交 commit。**完整命令模板与说明见 `./reference.md`「§5.1 记录最终交付文件与 AI 产出快照」**。
260
262
 
261
263
  ### 6. 完成或暂停时显示状态
262
264
 
@@ -316,6 +318,6 @@ g. **继续下一个层级** — 重新检查 DAG,找出依赖已满足的下
316
318
  ## 渐进披露
317
319
 
318
320
  - Read `checklist.md` 仅在执行 apply 需要校验门禁/自检时 — 含 §1.2 Check 门禁检查点、§5d/§5e 编译/测试门禁自检、§5e.1 TDD 节奏校验、§5f.1 checkbox 全量同步校验、§6.0 单元测试真实执行自检、§6.1 worktree 收尾前置条件、Guardrails ⛔ 强制项勾选表。
319
- - Read `reference.md` 仅在需要参考详细模板时 — 含 📊 Telemetry 命令模板(start/end/task_update/ai_adoption_review/worktree_finish)、§1.5 worktree 全套策略(Step 0.1-3 + record-base + 多 cap 合并顺序)、§5c 子代理派发、§5.1 AI 产出快照、§6.0 单元测试、§6.1 worktree 收尾脚本。
321
+ - Read `reference.md` 仅在需要参考详细模板时 — 含 📊 Telemetry 命令模板(start/end/task_update/final_output_snapshot/ai_adoption_review/worktree_finish)、§1.5 worktree 全套策略(Step 0.1-3 + record-base + 多 cap 合并顺序)、§5c 子代理派发、§5.1 最终交付文件与 AI 产出快照、§6.0 单元测试、§6.1 worktree 收尾脚本。
320
322
  - `implementer-prompt.md` 为子代理派发提示模板(§5c 派发时组合 tasks/design/overview 上下文使用)。
321
323
  - `worktree-setup.md` 为 worktree 快速参考(§1.5 策略的精简版,与 reference.md §1.5 完整版并存:reference=完整策略,worktree-setup=快速参考)。
@@ -82,6 +82,7 @@ description: opsx-apply 的阶段强制检查点与自检清单。仅在执行 a
82
82
  - [ ] “验收证据”与主任务进度分开统计;必须由真实测试、人工验收或评审证据确认,不自动勾选
83
83
  - [ ] 显示进度:`✅ [TASK-ID] 已完成 [N/M]`
84
84
  - [ ] 记录严格任务事件:`task_update` 必须含 `--task-id`、`--run-id`,完成时引用成功的 green/refactor/regression `test_event_id` 并明确 `tdd_required=true/false`;测试不适用时写明 `verification_not_applicable_reason`
85
+ - [ ] 每条 `task_update` 已记录本任务实际修改的 `files`;确实无文件修改时已填写具体 `no_file_change_reason`
85
86
  - [ ] ⛔ **task_update 后必须验证状态已更新**:执行 `node "$(cat .sdd-spec-root)/skywalk-sdd/index.cjs" check-task --project=. --change=<变更名称> --task-id=<TASK-ID>`,确认对应规范状态行已变为 `[x]`
86
87
 
87
88
  ### §5f.1 apply 结束前 checkbox 全量同步校验
@@ -92,6 +93,7 @@ description: opsx-apply 的阶段强制检查点与自检清单。仅在执行 a
92
93
  - [ ] `acceptance_evidence` 单独报告已确认/待确认数量,不将其混入任务完成率
93
94
  - [ ] 手动验证清单(如有)仅在真实完成后勾选
94
95
  - [ ] 文档更新项(如有)已完成或显式标注推迟
96
+ - [ ] 所有文件就绪后已记录严格 `final_output_snapshot`:`snapshot_kind=final`,`vcs_mode=readonly|no-git`,`files_changed` 等于 `files` 去重数量,新增/删除行数符合 VCS 模式;无交付文件时 `files=[]`、`files_changed=0` 且有具体 `no_output_reason`
95
97
 
96
98
  ---
97
99
 
@@ -17,7 +17,7 @@ description: opsx-apply 的详细模板:telemetry 命令、worktree 全套策
17
17
  ### task_update(每完成一个任务记录)
18
18
 
19
19
  ```bash
20
- node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=task_update --command=apply --project=. --change=<变更名称> --capability=<capability-name> --task-id=<TASK-ID> --run-id=<本次任务更新稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --status=completed --result=success --summary="<TASK-ID> 完成" --details-json="{\"task_update\":{\"test_event_id\":\"<同一change内成功test_result的event_id>\",\"tdd_required\":<true|false>,\"tdd_pair_id\":\"<pair-N>\",\"tdd_role\":\"green\"},\"files_changed\":[]}"
20
+ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=task_update --command=apply --project=. --change=<变更名称> --capability=<capability-name> --task-id=<TASK-ID> --run-id=<本次任务更新稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --status=completed --result=success --summary="<TASK-ID> 完成" --details-json="{\"task_update\":{\"test_event_id\":\"<同一change内成功test_result的event_id>\",\"tdd_required\":<true|false>,\"tdd_pair_id\":\"<pair-N>\",\"tdd_role\":\"green\",\"files\":[\"<本任务实际修改的仓库相对路径>\"]}}"
21
21
 
22
22
  也可互斥使用 `test_run_id`(同 change、覆盖当前任务、唯一严格完成候选);解析成功后会补齐规范化 `test_event_id`。
23
23
  ```
@@ -27,9 +27,17 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=task_upd
27
27
  只有文档、纯配置说明等确实不适用测试的任务,才能显式声明:
28
28
 
29
29
  ```json
30
- {"task_update":{"verification_not_applicable":true,"verification_not_applicable_reason":"<为什么本任务无需测试的具体原因>"}}
30
+ {"task_update":{"verification_not_applicable":true,"verification_not_applicable_reason":"<为什么本任务无需测试的具体原因>","files":["<本任务实际修改的仓库相对路径>"]}}
31
31
  ```
32
32
 
33
+ 若本任务只完成分析、验证或等待,没有修改任何文件,必须明确写:
34
+
35
+ ```json
36
+ {"task_update":{"no_file_change_reason":"<本任务为何没有修改文件的具体原因>"}}
37
+ ```
38
+
39
+ `task_update.files` 与 `no_file_change_reason` 至少提供一个;不要用空数组掩盖未采集。
40
+
33
41
  **🧪 TDD 测试骨架任务(`test-strategy: tdd`)**:当任务是"测试骨架"时,`task_update` 必须在 `--details-json` 中带 `"task_kind":"test-skeleton"`。
34
42
 
35
43
  > 完整 test-skeleton telemetry 模板见 tdd-rules/rules/test-skeleton-telemetry.md
@@ -37,7 +45,7 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=task_upd
37
45
  **📄 通过文件传递大 payload**:若 `details-json` 内容过长,可先写入 `"$(cat .sdd-spec-root)/skywalk-sdd/state/<变更名称>-task-update.json`,再使用 `--details-file` 指定该文件:
38
46
 
39
47
  ```bash
40
- node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --type=task_update --command=apply --project=. --change=<变更名称> --capability=<capability-name> --task-id=<TASK-ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --status=completed --result=success --summary="<TASK-ID> 完成" --details-file="$(cat .sdd-spec-root)/skywalk-sdd/state/<变更名称>-task-update.json"
48
+ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=task_update --command=apply --project=. --change=<变更名称> --capability=<capability-name> --task-id=<TASK-ID> --run-id=<本次任务更新稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --status=completed --result=success --summary="<TASK-ID> 完成" --details-file="$(cat .sdd-spec-root)/skywalk-sdd/state/<变更名称>-task-update.json"
41
49
  ```
42
50
 
43
51
  **✅ 验证 checkbox 已更新**:`task_update` 记录成功后会自动调用 `check-task` 更新 `tasks.md` 中的任务 checkbox。需要显式校验时可执行:
@@ -124,7 +132,17 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=process_
124
132
  | 模型故障 | `model_error` | - |
125
133
  | 测试环境异常 | `test_exception` | - |
126
134
 
127
- ### ai_adoption_review(AI 产出快照)
135
+ ### final_output_snapshot(最终交付文件)
136
+
137
+ 所有实现、测试和文档文件就绪后记录一次严格最终快照:
138
+
139
+ ```bash
140
+ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=final_output_snapshot --command=apply --project=. --change=<变更名称> --capability=<capability-name> --run-id=<最终快照稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --result=success --summary="最终交付文件快照" --details-json="{\"final_output_snapshot\":{\"snapshot_kind\":\"final\",\"vcs_mode\":\"<readonly|no-git>\",\"files\":[\"<仓库相对路径1>\",\"<仓库相对路径2>\"],\"files_changed\":<N>,\"added_lines\":<只读Git统计值或null>,\"deleted_lines\":<只读Git统计值或null>}}"
141
+ ```
142
+
143
+ 这是报告“最终交付文件”的权威来源。`files_changed` 必须等于 `files` 去重后的数量;`vcs_mode=readonly` 时新增/删除行数必须是非负整数,`vcs_mode=no-git` 时两者可为 `null`。确实没有交付文件时,使用空 `files`、`files_changed=0` 并补充具体 `no_output_reason`。清单只能使用仓库相对路径,不得使用绝对路径或 `..`。旧 `ai_adoption_review.ai_diff.files` 继续兼容读取,但新流程不得用逐任务文件清单冒充最终交付快照。
144
+
145
+ ### ai_adoption_review(AI 产出快照,采纳率兼容口径)
128
146
 
129
147
  当前 Capability 的 AI 代码产出完成后,必须记录 `ai_adoption_review`,但不得为了采集快照自动提交 commit。
130
148
 
@@ -372,9 +390,13 @@ Agent("实现 TASK-03: 创建权限数据模型", ...)
372
390
 
373
391
  ---
374
392
 
375
- ## §5.1 记录 AI 产出快照
393
+ ## §5.1 记录最终交付文件与 AI 产出快照
376
394
 
377
- 当前 Capability AI 代码产出完成后,必须记录 `ai_adoption_review`,但不得为了采集快照自动提交 commit。
395
+ 当前 Capability 的全部文件就绪后,必须先记录 `final_output_snapshot`;如需 AI 采纳率指标,再记录 `ai_adoption_review`。不得为了采集快照自动提交 commit。
396
+
397
+ ```bash
398
+ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=final_output_snapshot --command=apply --project=. --change=<变更名称> --capability=<capability-name> --run-id=<最终快照稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --result=success --summary="最终交付文件快照" --details-json="{\"final_output_snapshot\":{\"snapshot_kind\":\"final\",\"vcs_mode\":\"<readonly|no-git>\",\"files\":[\"<仓库相对路径1>\",\"<仓库相对路径2>\"],\"files_changed\":<N>,\"added_lines\":<只读Git统计值或null>,\"deleted_lines\":<只读Git统计值或null>}}"
399
+ ```
378
400
 
379
401
  > **⚠️ 采集时序(N1)**:`ai_adoption_review` 应在 apply 收尾、**所有文件就绪后**采集(含 README/CHANGELOG/dist 产物/后补文件),确保 `ai_diff.files_changed` 完整。若采集后又补文件,须补录 `--status=final` 事件更新快照,避免 ai_snapshot 时序不全导致 ai_diff 缺漏。
380
402
 
@@ -387,7 +409,7 @@ Git 可用时只读统计 SHA/diff;Git 不可用时使用 `vcs_mode=no-git`
387
409
  node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --type=ai_adoption_review --command=apply --project=. --change=<变更名称> --capability=<capability-name> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --status=ai_snapshot --result=success --summary="AI 代码产出快照" --details-json="{\"ai_adoption\":{\"review_status\":\"ai_snapshot\",\"vcs_mode\":\"<readonly|no-git>\",\"base_git_sha\":\"<base_git_sha_or_null>\",\"ai_git_sha\":\"<ai_git_sha_or_null>\",\"ai_diff\":{\"files_changed\":<N>,\"files\":[\"<产出文件路径1>\",\"<产出文件路径2>\"],\"added_lines\":<git_diff_numstat_HEAD_取值或0>,\"deleted_lines\":<同左>},\"notes\":\"未自动提交 commit;vcs_mode=readonly 时 added_lines 用只读 git diff --numstat HEAD 取值(不得填 null,工具侧硬校验);vcs_mode=no-git 时可填 null\"}}"
388
410
  ```
389
411
 
390
- > 该命令亦见上文「📊 Telemetry 命令模板 → ai_adoption_review」。
412
+ > 两种命令亦见上文「📊 Telemetry 命令模板 → final_output_snapshot / ai_adoption_review」。
391
413
 
392
414
  ---
393
415
 
@@ -17,14 +17,15 @@ 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 启动。入库成功后,`Read` `opsx-ontology-query/phase-3-postchange.md` 验证版本生效、AC 保留、关系完整性。缺失则提示用户重新 `kld-sdd-init`,**不要**自造另一套入库协议。
20
+ > **硬依赖(收尾入库)**:zip 生成后的上传依赖同级已部署的 **`opsx-kb-ingest`**。进入 §5.5 前必须先 `Read` 该技能的 `SKILL.md` 并确认 KB 已配置(配置由 `opsx-kb-config` 负责)。入库成功后,`Read` `opsx-ontology-query/phase-3-postchange.md` 验证版本生效、AC 保留、关系完整性。缺失则提示用户重新 `kld-sdd-init`,**不要**自造另一套入库协议。
21
21
 
22
22
  > **跨平台执行规则**
23
23
  > - **SDD 文档根** = `*-sdd-specs` 包裹包(含 `openspec/`、`modules.yaml`),不是 Git 根或工作区根。
24
- > - `openspec` 命令:优先 `node "$(cat .sdd-spec-root)/skywalk-sdd/openspec-shim.cjs" list`(自动 cd 到包裹包),或先 `cd` 到包裹包再执行。
25
- > - Telemetry / ontology:`node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" …`(Git 根无 skywalk-sdd/);`spec-root` 可用 `node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" spec-root`。
24
+ > - `openspec` 命令:`cd <spec-package> && openspec …`(先 cd 到包裹包即可)。路径不确定时用 `node <spec-package>/skywalk-sdd/spec-root.cjs` 验证。
25
+ > - Telemetry / ontology:`node <spec-package>/skywalk-sdd/log.cjs …`(直接在包裹包内执行);`--project=.` 指当前 spec 包裹包。
26
26
  > - Telemetry 命令默认使用 `--project=.`,兼容 Windows、macOS、Linux。
27
27
  > - 不要裸写 Windows 反斜杠绝对路径;如必须使用绝对路径,请加引号或改成正斜杠。
28
+ > - **PowerShell 禁忌**(Windows 用户必读):禁止 `| cat`(直接执行或用 `node -e`);禁止 `curl`(HTTP 请求走 `context-client.cjs` / `kb-upload.cjs` 或用 `Invoke-RestMethod`);禁止 `Get-Content` / `Out-File` 读写 JSON(用 write_to_file 工具或 Node.js `fs`,避免 BOM 污染)。
28
29
  > - 不要省略 `--source=opsx-command` 和 `--session-id=<会话ID>`。
29
30
  > - 本技能不调用 OpenSpec 自带归档命令;统一使用 SkyWalk-SDD 的 `archive-docs`。
30
31
 
@@ -169,8 +170,8 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" active-change --remove
169
170
 
170
171
  ### 5.5 收尾入库(opsx-kb-ingest)
171
172
 
172
- 1. 确认 `${AGENT_SKILL_DIR}/opsx-kb-ingest/SKILL.md` 存在并 Read;按该技能完成 API Key / targets
173
- 2. 归档 zip 生成后,**加载并执行** **`opsx-kb-ingest`** 上传(勿只口头提示而不走技能流程);成功则写 `ingest-receipt.json`。
173
+ 1. 确认 `${AGENT_SKILL_DIR}/opsx-kb-ingest/SKILL.md` 存在并 Read;KB 配置(API Key / targets / project-identity.json)由 `opsx-kb-config` 统一负责,如未配置则提示运行 `/opsx-kb-config`。
174
+ 2. 归档 zip 生成后,**加载并执行** **`opsx-kb-ingest`** 上传(勿只口头提示而不走技能流程);也可直接使用 `kb-upload.cjs --package=<zip路径>` 上传;成功则写 `ingest-receipt.json`。
174
175
  3. 若返回 `EXTERNAL_REF_CONFLICT`,引导回 spec/check 修正后重入,**禁止**在 KB 内现场改绑。
175
176
 
176
177
  > 注意:`archive-docs` 成功执行后已经在内部写入 `stage_end`,因此**不要在成功的归档后再单独运行 `node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" end --command=archive ...`**。仅在第 5 步归档命令失败时,才需要运行下方的失败分支 `end`。
@@ -4,10 +4,10 @@ description: "质量检查技能 - 验证文档完整性、一致性、算法正
4
4
  argument-hint: "[change-name] [上下文文件...]"
5
5
  license: MIT
6
6
  compatibility: Requires openspec CLI; depends on opsx-ontology-query for external-key validation and baseline checks.
7
- depends-on: opsx-ontology-query
8
7
  metadata:
9
8
  author: sdd-team
10
9
  version: "3.0"
10
+ depends-on: opsx-ontology-query
11
11
  allowed-tools:
12
12
  - Bash
13
13
  - Read
@@ -26,21 +26,22 @@ allowed-tools:
26
26
  > 即使检查发现代码相关问题,也只记录在检查报告中,**不自动修复代码**。
27
27
  > 代码修复将在 `/opsx-apply` 阶段进行。
28
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。
29
+ > **KB 上下文**:check 阶段需验证外部键格式(requirement/feature/scenario 文法)、SCN 需求编号前缀一致性和历史覆盖率基线。进入相关步骤前先 `Read` `opsx-ontology-query/phase-2-during.md` §3-5,并按 `SKILL.md` → Session 启动准备 API Key + targets。
30
30
  >
31
31
  > **📡 KB 就绪检查**:§2.6 在进入 KB 相关检查前会检测 KB 配置状态。若未配置,会**主动询问**用户选择「配置」或「跳过」,KB 相关检查项降级为仅本地验证。
32
32
 
33
33
 
34
34
  > **🖥️ 跨平台执行规则**
35
35
  > - **SDD 文档根** = `*-sdd-specs` 包裹包(含 `openspec/`、`modules.yaml`),不是 Git 根或工作区根。
36
- > - `openspec` 命令:优先 `node "$(cat .sdd-spec-root)/skywalk-sdd/openspec-shim.cjs" list`(自动 cd 到包裹包),或先 `cd` 到包裹包再执行。
37
- > - Telemetry / ontology:`node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" …`(Git 根无 skywalk-sdd/);`spec-root` 可用 `node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" spec-root`。
36
+ > - `openspec` 命令:`cd <spec-package> && openspec …`(先 cd 到包裹包即可)。路径不确定时用 `node <spec-package>/skywalk-sdd/spec-root.cjs` 验证。
37
+ > - Telemetry / ontology:`node <spec-package>/skywalk-sdd/log.cjs …`(直接在包裹包内执行);`--project=.` 指当前 spec 包裹包。
38
38
  > - Telemetry 命令默认使用 `--project=.`,兼容 Windows、macOS、Linux。
39
39
  > - ${SHELL_GUIDANCE}
40
40
  > - 不要省略 `--source=opsx-command` 与 `--session-id=<会话ID>`。
41
41
  > **📊 Telemetry(必做,不得跳过)**
42
42
  > - 阶段开始:`node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" start --command=check --project=. --change=<变更名称> --capability=<可选capability-name> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID>`(保存 event_id)
43
- > - 检查报告生成后,必须先记录结构化检查结果:`node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --type=check_result --command=check --project=. --change=<变更名称> --capability=<可选capability-name> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --result=success/partial/failure --summary="检查结果摘要" --details-json="{\"check_results\":{\"total\":0,\"errors\":0,\"warnings\":0,\"warning_items\":[],\"warning_dispositions\":[{\"warning\":\"<稳定编号>\",\"disposition\":\"fixed|accepted|waived|needs_input|open\",\"reason\":\"<处置依据>\"}],\"suggestions\":0,\"fixed_before_apply\":0,\"consistency_score\":null,\"reviewer\":\"<reviewer-identifier>\",\"review_session_id\":\"<当前check会话ID>\",\"author_session_id\":\"<文档作者/apply会话ID或unknown>\",\"reviewer_independence\":\"independent-review|self-review|unknown\",\"categories\":{\"completeness\":{\"passed\":0,\"total\":0},\"consistency\":{\"passed\":0,\"total\":0},\"executability\":{\"passed\":0,\"total\":0},\"tdd_compliance\":{\"passed\":0,\"total\":0}},\"task_completion\":{\"completed\":0,\"incomplete\":0,\"total\":0,\"has_incomplete\":false,\"checked_for_archive_readiness\":false}}}"`
43
+ > - 下方 `check_result` 命令中的 `0` 是待替换位置,禁止原样照抄;写入前必须用本轮实测值替换,且顶层 `total` 必须是大于 0 的整数,否则 strict 记录会拒绝该事件。
44
+ > - 检查报告生成后,必须先记录结构化检查结果:`node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=check_result --command=check --project=. --change=<变更名称> --capability=<可选capability-name> --run-id=<本轮Check稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --result=success/partial/failure --summary="检查结果摘要" --details-json="{\"check_results\":{\"total\":0,\"errors\":0,\"warnings\":0,\"warning_items\":[],\"warning_dispositions\":[{\"warning\":\"<稳定编号>\",\"disposition\":\"fixed|accepted|waived|needs_input|open\",\"reason\":\"<处置依据>\"}],\"suggestions\":0,\"fixed_before_apply\":0,\"consistency_score\":null,\"reviewer\":\"<reviewer-identifier>\",\"review_execution_mode\":\"<subagent|main-agent-fallback>\",\"reviewer_agent_id\":\"<子代理真实ID;主Agent回退时填null>\",\"parent_session_id\":\"<父会话ID;主Agent回退时可填null>\",\"review_session_id\":\"<当前check会话ID>\",\"author_session_id\":\"<文档作者/apply真实会话ID;无法确认时仅允许主Agent回退填unknown>\",\"reviewer_independence\":\"<independent-review|self-review|unknown>\",\"fallback_reason_code\":\"<主Agent回退时五类稳定码之一;子代理成功时填null>\",\"fallback_reason\":\"<主Agent回退时具体中文原因;子代理成功时填null>\",\"categories\":{\"completeness\":{\"passed\":0,\"total\":0},\"consistency\":{\"passed\":0,\"total\":0},\"executability\":{\"passed\":0,\"total\":0},\"tdd_compliance\":{\"passed\":0,\"total\":0}},\"task_completion\":{\"completed\":0,\"incomplete\":0,\"total\":0,\"has_incomplete\":false,\"checked_for_archive_readiness\":false}}}"`
44
45
  > - `check_result` 记录成功后,才允许阶段结束:`node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" end --event-id=<event_id> --command=check --project=. --change=<变更名称> --capability=<可选capability-name> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --result=success/partial/failure --summary="摘要"`
45
46
  > - **【B1 摘要数字校验】** `stage_end --summary` 中的数字(如「N 个场景」「N 层 DAG」「N 个任务」)必须与 `spec.md`/`tasks.md`/`test-scenarios.md` 的实统计交叉校验一致后再填写,不得凭记忆自填。典型失真:summary 写「11 个场景」实际 spec 含 13 条断言、「5 层 DAG」实际 tasks 修复后为 6 层。check 阶段发现不一致时,修正 summary 或补齐文档,使三者数字自洽。
46
47
 
@@ -76,6 +77,29 @@ openspec list
76
77
  - `specs/<capability>/design.md`(实现方案)
77
78
  - `specs/<capability>/tasks.md`(或 task.md,兼容旧格式)(任务拆解)
78
79
 
80
+ ### 2.1 默认使用一个独立子代理评审
81
+
82
+ Check 默认启动且只启动 **一个独立子代理**。主 Agent 先确定待检查的最终文档路径、作者会话 ID 和固定输出结构,再让子代理直接读取这些最终产物;不得先把主 Agent 的判断摘要喂给子代理,也不得让评审子代理再次启动子代理或递归委派。
83
+
84
+ ${CHECK_REVIEW_DELEGATION_GUIDANCE}
85
+
86
+ 正常路径:
87
+
88
+ 1. 启动一个全新评审上下文,记录 `reviewer_agent_id`、`parent_session_id` 和 `review_session_id`。
89
+ 2. 子代理独立执行完整性、一致性、可执行性、算法正确性和 TDD 合规检查。
90
+ 3. 主 Agent 只校验返回结构、展示原始结论并记录事件,不得把主 Agent 身份写成子代理身份。
91
+ 4. 只有 `review_execution_mode=subagent`、评审者身份存在、评审会话与作者会话不同且 `reviewer_independence=independent-review` 时,Q3 才是“已独立验证”。
92
+
93
+ 只有子代理能力不可用或调用失败时,主 Agent 才执行同一检查。回退必须记录 `review_execution_mode=main-agent-fallback`、通俗原因,并从以下标准原因中选择一个:
94
+
95
+ - `SUBAGENT_CAPABILITY_UNAVAILABLE`:当前 Agent 环境没有子代理能力。
96
+ - `SUBAGENT_PERMISSION_DENIED`:权限策略不允许启动子代理。
97
+ - `SUBAGENT_START_FAILED`:子代理启动失败。
98
+ - `SUBAGENT_TIMEOUT`:子代理超时未返回。
99
+ - `SUBAGENT_RESULT_INVALID`:子代理结果缺字段或无法解析。
100
+
101
+ 回退时 `reviewer_independence` 只能是 `self-review` 或 `unknown`,Q3 仍可计算,但必须显示“由主 Agent 自查,未经过独立复核”及具体回退原因。
102
+
79
103
  ### 2.5 【多仓库关联配置诊断】(在五维检查之前)
80
104
 
81
105
  先执行轻量配置诊断,**不执行代码 diff**,只检查命名与引用配置:
@@ -129,15 +153,15 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" diagnose-naming --proj
129
153
  3. **若已配置** → 直接进入 §3,正常使用 KB 做 coverage 基线、predecessor 预检。
130
154
  4. **若未配置** → 使用 **AskUserQuestion** 询问:
131
155
 
132
- > "📡 **Engineering KB 未配置**
156
+ > "📡 **知识库未配置**
133
157
  >
134
- > KB 可以提供覆盖率基线检查、predecessor 版本预检(防止入库冲突)。是否现在配置?
158
+ > 知识库可以帮你做覆盖率基线检查和版本冲突预检。现在要配置吗?
135
159
  >
136
- > - A. **配置 KB**
137
- > - B. **跳过 KB**,仅执行本地检查(semantic-check + external-key 格式校验),入库前无 predecessor 预检
138
- > - C. **取消操作**"
160
+ > - A. **现在配置** — 运行 /opsx-kb-config
161
+ > - B. **暂不配置,先继续** 仅做本地检查(不检查版本冲突)
162
+ > - C. **取消** — 终止本次操作"
139
163
 
140
- - **选 A** → 配置 进入 §3。
164
+ - **选 A** → 引导运行 `/opsx-kb-config`,配置完成后进入 §3。
141
165
  - **选 B** → KB 相关检查项降级:coverage 基线跳过、`current-version` 预检跳过。检查报告中标注 `kb: degraded(by-user-choice)`。
142
166
  - **选 C** → 终止 check。
143
167
 
@@ -248,16 +272,24 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" tasks-status --project=. --chan
248
272
  - `reviewer`: 执行本次 check 的代理或会话标识。
249
273
  - `review_session_id`: 当前 check 会话 ID(与 `--session-id` 一致)。
250
274
  - `author_session_id`: 文档作者或 apply 阶段会话 ID;无法确定时填 `unknown`。
251
- - `reviewer_independence`: `independent-review`(独立 evaluator 且会话与作者不同)| `self-review` | `unknown`。优先使用独立 evaluator;不可用时继续检查但标 `self-review` 或 `unknown`,报告中 Q3 为 `provisional`。
275
+ - `review_execution_mode`: `subagent` `main-agent-fallback`。
276
+ - `reviewer_agent_id`: 独立子代理或独立任务标识;主 Agent 回退时省略。
277
+ - `parent_session_id`: 启动子代理的主会话 ID。
278
+ - `review_session_id`: 独立评审会话 ID;主 Agent 回退时为当前检查会话。
279
+ - `author_session_id`: 文档作者会话 ID。
280
+ - `reviewer_independence`: `independent-review` | `self-review` | `unknown`。
281
+ - `fallback_reason_code` / `fallback_reason`: 仅主 Agent 回退时填写,原因码必须来自 §2.1 的五个标准值。
252
282
  - `categories`: 至少包含 `completeness`、`consistency`、`executability`。
253
283
  - `task_completion`: 从 `tasks-status` 输出整理而来;未进入 apply 时 `checked_for_archive_readiness=false`。
254
284
 
285
+ 下面命令中的 `0` 仅表示待填数字的位置,执行前必须全部换成本轮实测值;顶层 `total` 必须是大于 0 的整数。禁止为了通过校验而编造计数。
286
+
255
287
  在终端执行(必须成功):
256
288
  ```bash
257
- node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --type=check_result --command=check --project=. --change=<变更名称> --capability=<可选capability-name> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --result=success/partial/failure --summary="检查结果摘要" --details-json="{\"check_results\":{\"total\":0,\"errors\":0,\"warnings\":0,\"warning_items\":[],\"suggestions\":0,\"fixed_before_apply\":0,\"consistency_score\":null,\"reviewer\":\"<reviewer-identifier>\",\"review_session_id\":\"<当前check会话ID>\",\"author_session_id\":\"<文档作者/apply会话IDunknown>\",\"reviewer_independence\":\"independent-review|self-review|unknown\",\"categories\":{\"completeness\":{\"passed\":0,\"total\":0},\"consistency\":{\"passed\":0,\"total\":0},\"executability\":{\"passed\":0,\"total\":0},\"tdd_compliance\":{\"passed\":0,\"total\":0}},\"task_completion\":{\"completed\":0,\"incomplete\":0,\"total\":0,\"has_incomplete\":false,\"checked_for_archive_readiness\":false}}}"
289
+ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=check_result --command=check --project=. --change=<变更名称> --capability=<可选capability-name> --run-id=<本轮Check稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID> --result=success/partial/failure --summary="检查结果摘要" --details-json="{\"check_results\":{\"total\":0,\"errors\":0,\"warnings\":0,\"warning_items\":[],\"suggestions\":0,\"fixed_before_apply\":0,\"consistency_score\":null,\"reviewer\":\"<reviewer-identifier>\",\"review_execution_mode\":\"<subagent|main-agent-fallback>\",\"reviewer_agent_id\":\"<子代理真实ID;主Agent回退时填null>\",\"parent_session_id\":\"<父会话ID;主Agent回退时可填null>\",\"review_session_id\":\"<当前check会话ID>\",\"author_session_id\":\"<文档作者/apply真实会话ID;无法确认时仅允许主Agent回退填unknown>\",\"reviewer_independence\":\"<independent-review|self-review|unknown>\",\"fallback_reason_code\":\"<主Agent回退时五类稳定码之一;子代理成功时填null>\",\"fallback_reason\":\"<主Agent回退时具体中文原因;子代理成功时填null>\",\"categories\":{\"completeness\":{\"passed\":0,\"total\":0},\"consistency\":{\"passed\":0,\"total\":0},\"executability\":{\"passed\":0,\"total\":0},\"tdd_compliance\":{\"passed\":0,\"total\":0}},\"task_completion\":{\"completed\":0,\"incomplete\":0,\"total\":0,\"has_incomplete\":false,\"checked_for_archive_readiness\":false}}}"
258
290
  ```
259
291
 
260
- > **⚠️ P1-1 check_result details 不得为空**:`--details-json` 必须含 `categories` / `task_completion` / reviewer 独立性字段等,**禁止传空对象 `{}`**。空 details 导致 Q3 不可计算(工具侧虽有 state fallback 兜底,但事件 details 是主数据源)。
292
+ > **⚠️ P1-1 check_result details 不得为空**:`--details-json` 必须含正整数 `total`、非负整数 `errors`、四类 `categories`、计数自洽的 `task_completion` reviewer 独立性字段等,**禁止传空对象 `{}`**。空 details 导致 Q3 不可计算,并会被 strict 记录直接拒绝;历史非 strict 事件仍按兼容口径读取。
261
293
 
262
294
  > **⚠️ P2-3 check 纳入 task_completion 判定**:执行 `tasks-status` 后,若 `has_incomplete=true`,`check_result` 的 `--result` 应标 `partial` 并在 `warning_items` 记录未勾选项(`{category:"task_completion", description:"N 项验收未勾选", target:"tasks.md:行号"}`)。不阻断 apply(P4 已与 fixRate 解耦),但反映真实完成度。
263
295
 
@@ -274,9 +306,9 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --type=conformance_revie
274
306
  > - `assertions[].judge_status` 枚举:`matched` / `partial` / `missed`
275
307
  > - `assertions[].human_status` 枚举:`matched` / `partial` / `missed` / 省略(默认跟随 judge_status)
276
308
 
277
- > **reviewer 与 reviewer_independence 说明(check_result)**:执行 check 前先读取文档作者/阶段会话信息;**能使用独立 evaluator 时必须使用**。`reviewer_independence=independent-review` 且 `review_session_id` 与 `author_session_id` 不同时,Q3 `verified`;自评或无法确认时为 `self-review` `unknown`,Q3 标 `provisional` 但仍可计算分数。
309
+ > **reviewer 与 reviewer_independence 说明(check_result)**:执行 check 前先读取文档作者/阶段会话信息;默认启动且只启动一个独立子代理。仅当 `review_execution_mode=subagent`、`reviewer_agent_id` 存在、`reviewer_independence=independent-review` 且 `review_session_id` 与 `author_session_id` 不同时,Q3 才为 `verified`;主 Agent 回退或无法确认时 Q3 标 `provisional` 但仍可计算分数。
278
310
 
279
- > **报告用语**:`verified` 展示为“已验证”,表示有独立复核;`provisional` 展示为“临时”,表示已有数值但仍需独立复核。不得仅用颜色区分,也不得把临时结果写成最终可信结论。
311
+ > **报告用语**:`verified` 展示为“已独立验证”;`provisional` 展示为“已有计算结果,尚未独立验证”。不要使用 “self-review” 作为用户可见说明;应写成“由主 Agent 自查,未经过独立复核”。不得仅用颜色区分,也不得把尚未独立验证的结果写成最终可信结论。
280
312
 
281
313
  > **reviewer 与 reviewer_independence 说明(conformance_review)**:`reviewer` 用于标识实际执行本次符合度评审的代理或会话(例如 agent 名称、会话 ID)。渲染报告时会比较 `reviewer` 与 apply 阶段记录的 `apply_agent`:若两者相同,则 `reviewer_independence` 显示为 `self-review`;否则显示为 `independent-review`。建议尽可能由独立评审方执行 check,以提升结果可信度。
282
314
 
@@ -310,7 +342,7 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --type=conformance_revie
310
342
  - 决议缺失 / pending / 与产物不一致 → `CONTINUITY_DECISION_REQUIRED`
311
343
  - **编号诊断码**(并入五维报告与 apply gate):
312
344
  - `EXTERNAL_KEY_FORMAT_INVALID` — external_id / feature_id 不合规
313
- - `EXTERNAL_KEY_SCOPE_MISMATCH` — 场景键 REQ 前缀不在 `requirement-refs`
345
+ - `EXTERNAL_KEY_SCOPE_MISMATCH` — 场景键需求编号前缀不在 `requirement-refs`
314
346
  - `EXTERNAL_KEY_FEATURE_UNDECLARED` — feature↔requirement.`feature_id` 配对断裂
315
347
  - `EXTERNAL_KEY_SEQ_REUSED` — 本 Change 内 SCN 重复或复用 removed 墓碑号
316
348
  - `NUMBERING_WAIVER_ACTIVE`(warning)— 豁免生效,本轮不种桥