kld-sdd 2.7.8 → 2.8.1

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 (75) hide show
  1. package/README.md +26 -0
  2. package/USABILITY.md +72 -0
  3. package/bin/kld-sdd-init.js +718 -34
  4. package/lib/command-bridge.js +26 -17
  5. package/lib/deploy-codebuddy-hooks.js +19 -26
  6. package/lib/deploy-strategy.js +293 -0
  7. package/lib/hook-gate-core.js +7 -8
  8. package/lib/hook-install.js +75 -0
  9. package/lib/init.js +507 -726
  10. package/lib/maintenance.js +221 -0
  11. package/lib/managed-hook-hashes.json +24 -0
  12. package/lib/settings-merge.js +102 -25
  13. package/lib/skills-bundle.js +5 -5
  14. package/lib/spec-choice.js +85 -0
  15. package/lib/tool-profiles.js +2 -2
  16. package/lib/uninstall.js +453 -0
  17. package/package.json +7 -4
  18. package/skywalk-sdd/context-client.cjs +38 -7
  19. package/skywalk-sdd/index.cjs +153 -27
  20. package/skywalk-sdd/kb-sync-identity.cjs +1 -1
  21. package/skywalk-sdd/kb-upload.cjs +242 -85
  22. package/skywalk-sdd/lib/check-review.cjs +41 -0
  23. package/skywalk-sdd/lib/shared.cjs +62 -41
  24. package/skywalk-sdd/lib/test-execution.cjs +130 -0
  25. package/skywalk-sdd/lib/usage-reporter.cjs +17 -8
  26. package/skywalk-sdd/ontology/archive-package.cjs +141 -0
  27. package/skywalk-sdd/ontology/artifact-parser.cjs +24 -3
  28. package/skywalk-sdd/ontology/cli.cjs +53 -0
  29. package/skywalk-sdd/ontology/id.cjs +1 -1
  30. package/skywalk-sdd/ontology/identity-index.cjs +5 -1
  31. package/skywalk-sdd/ontology/resolve-spec-root.cjs +49 -0
  32. package/skywalk-sdd/ontology/schema.cjs +6 -0
  33. package/skywalk-sdd/ontology/sdd-config.cjs +33 -5
  34. package/skywalk-sdd/ontology/spec-detect.cjs +421 -0
  35. package/skywalk-sdd/ontology/spec-ontology.cjs +507 -0
  36. package/skywalk-sdd/ontology/workspace-layout.cjs +65 -17
  37. package/templates/git-hooks/commit-msg +17 -85
  38. package/templates/git-hooks/commit-msg-runner.cjs +44 -0
  39. package/templates/git-hooks/commit-msg-sdd-trailer.cjs +60 -69
  40. package/templates/git-hooks/consistency-check-core.cjs +92 -261
  41. package/templates/git-hooks/delivery-check.cjs +231 -0
  42. package/templates/git-hooks/delivery-snapshot.cjs +181 -0
  43. package/templates/git-hooks/hooks.config +8 -6
  44. package/templates/git-hooks/pre-commit +19 -5
  45. package/templates/git-hooks/pre-commit-consistency-check.cjs +13 -31
  46. package/templates/git-hooks/pre-push +19 -5
  47. package/templates/git-hooks/pre-push-consistency-check.cjs +36 -83
  48. package/templates/hooks/claude/hooks/sdd-post-tool.cjs +2 -2
  49. package/templates/hooks/codebuddy/hooks/hook-gate-core.cjs +7 -8
  50. package/templates/hooks/codebuddy/hooks/sdd-post-tool.cjs +2 -2
  51. package/templates/openspec/proposal.md +1 -1
  52. package/templates/openspec/spec.md +8 -0
  53. package/templates/skills/kld-sdd/opsx-apply/SKILL.md +28 -24
  54. package/templates/skills/kld-sdd/opsx-apply/checklist.md +12 -3
  55. package/templates/skills/kld-sdd/opsx-apply/reference.md +21 -1
  56. package/templates/skills/kld-sdd/opsx-archive/SKILL.md +20 -18
  57. package/templates/skills/kld-sdd/opsx-check/SKILL.md +18 -13
  58. package/templates/skills/kld-sdd/opsx-check/reference.md +3 -1
  59. package/templates/skills/kld-sdd/opsx-check/review-template.json +22 -0
  60. package/templates/skills/kld-sdd/opsx-check/reviewer.md +27 -6
  61. package/templates/skills/kld-sdd/opsx-consistency-check/SKILL.md +34 -112
  62. package/templates/skills/kld-sdd/opsx-consistency-check/scripts/scripts.cjs +15 -14
  63. package/templates/skills/kld-sdd/opsx-kb-config/SKILL.md +93 -61
  64. package/templates/skills/kld-sdd/opsx-kb-config/reference.md +14 -12
  65. package/templates/skills/kld-sdd/opsx-kb-ingest/SKILL.md +16 -5
  66. package/templates/skills/kld-sdd/opsx-kb-ingest/reference.md +13 -5
  67. package/templates/skills/kld-sdd/opsx-kb-ingest/state.example.json +18 -0
  68. package/templates/skills/kld-sdd/opsx-ontology-ingest/SKILL.md +77 -0
  69. package/templates/skills/kld-sdd/opsx-ontology-query/SKILL.md +5 -4
  70. package/templates/skills/kld-sdd/opsx-ontology-query/reference.md +14 -1
  71. package/templates/skills/kld-sdd/opsx-propose/SKILL.md +1 -1
  72. package/templates/skills/kld-sdd/opsx-propose/interaction-policy.md +9 -0
  73. package/templates/skills/kld-sdd/opsx-spec/SKILL.md +5 -3
  74. package/templates/skills/kld-sdd/opsx-task/SKILL.md +2 -2
  75. package/index.js +0 -13
@@ -1,88 +1,41 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * pre-push-consistency-check.cjs
4
- *
5
- * Pre-push 轻量门禁:仅检查待推送范围涉及报告的存在性、是否过期。
6
- * - diff 驱动:仅检查待推送文件与报告 coveredFiles 有交集的 change,无关 change 跳过
7
- * - 完整的置信度校验由 pre-commit 完成,push 阶段不再重复。
8
- * - 过期判断读取 HEAD 已提交内容(而非工作区),避免工作区未提交修改造成误判。
9
- *
10
- * 待推送范围采集(逐级降级):
11
- * 1. git diff @{push}..HEAD(本地领先远程的提交)
12
- * 2. git diff origin/HEAD..HEAD
13
- * 3. 远程引用不存在(新分支/新仓库首次推送):git diff <空树>..HEAD,
14
- * 语义 = 首推时 HEAD 全部文件都是新增。空树 SHA 是 git 内置常量,
15
- * 不依赖任何远程引用,避免「首推因无远程引用被拦 → 引用永远建立不起来」的死锁
16
- * 4. 连空树 diff 都失败(如空仓无 HEAD):返回 ok=false,由 core 拦截推送而非静默放行
17
- *
18
- * 通过环境变量控制:
19
- * - SDD_SKIP_CONSISTENCY_CHECK=1 → 跳过校验
20
- * - SDD_WARN_ONLY=1 → 仅告警不拦截
21
- * - 注意:两个环境变量互斥,只能启用一个
22
- *
23
- * 共享逻辑见同目录 consistency-check-core.cjs。
24
- */
25
2
  'use strict';
26
-
27
- const core = require('./consistency-check-core.cjs');
28
- const { gitDiffNameStatus } = core;
29
- const { execFileSync } = require('child_process');
30
-
31
- // git 内置空树对象 SHA(SHA-1 仓库恒定不变)
32
- const EMPTY_TREE_SHA = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
33
-
34
- /**
35
- * 单仓待推送范围采集:本地领先远程的提交所涉及的文件。
36
- * files=修改/新增(排除删除);deleted=删除文件。
37
- * @returns {{files: string[], deleted: string[], ok: boolean}}
38
- */
39
- function gitPushRangeDiff(repoRoot) {
40
- const ranges = ['@{push}..HEAD', 'origin/HEAD..HEAD'];
41
- for (const range of ranges) {
42
- const r = gitDiffNameStatus(repoRoot, ['diff', range]);
43
- if (r.ok) return r;
44
- }
45
- // 首推降级:远程引用不存在(@{push}/origin/HEAD 均无法解析)时,
46
- // 用 git 内置空树 SHA 做 diff —— 语义为「首推 = HEAD 全部文件都是新增」。
47
- // 空树对象不依赖任何远程引用,打破「首推被拦 → 远程引用永远建立不起来」的死锁。
48
- const emptyTree = gitEmptyTreeSha(repoRoot);
49
- if (emptyTree) {
50
- const r = gitDiffNameStatus(repoRoot, ['diff', `${emptyTree}..HEAD`]);
51
- if (r.ok) return r;
52
- }
53
- // 连空树 diff 都失败(如空仓无 HEAD):返回失败,由 core 拦截而非静默放行
54
- return { files: [], deleted: [], ok: false };
3
+ // Optional legacy integration. New installs do not validate on every push.
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const snap = require('./delivery-snapshot.cjs');
7
+ const delivery = require('./delivery-check.cjs');
8
+ const mode = require('./consistency-check-core.cjs').loadConsistencyMode();
9
+ const skip = process.env.SDD_SKIP_CONSISTENCY_CHECK === undefined ? mode.skip : process.env.SDD_SKIP_CONSISTENCY_CHECK === '1';
10
+ const warnOnly = process.env.SDD_WARN_ONLY === undefined ? mode.warnOnly : process.env.SDD_WARN_ONLY === '1';
11
+ const strict = process.env.SDD_STRICT_CONSISTENCY === undefined ? mode.strict : process.env.SDD_STRICT_CONSISTENCY === '1';
12
+ if ([skip, warnOnly, strict].filter(Boolean).length > 1) {
13
+ console.error('[SDD] skip / warn_only / strict 互斥'); process.exit(1);
55
14
  }
56
-
57
- /**
58
- * 读取 git 内置空树 SHA(4b825dc642cb6eb9a060e54bf8d69288fbee4904)。
59
- * 优先用 git mktree 动态计算(兼容 SHA-256 仓库),失败时回退内置常量。
60
- * @param {string} repoRoot
61
- * @returns {string|null}
62
- */
63
- function gitEmptyTreeSha(repoRoot) {
64
- try {
65
- const sha = execFileSync('git', ['mktree'], {
66
- cwd: repoRoot, encoding: 'utf8', input: '', stdio: ['pipe', 'pipe', 'ignore'],
67
- }).trim();
68
- if (/^[0-9a-f]{40,64}$/.test(sha)) return sha;
69
- } catch {
70
- // 降级到内置常量
15
+ if (skip) { console.log('[SDD] 按显式配置跳过推送检查(未验证)'); process.exit(0); }
16
+ try {
17
+ const project = path.resolve(process.argv.find(a => a.startsWith('--project='))?.slice(10) || process.cwd());
18
+ const specRoot = path.resolve(__dirname, '..', '..');
19
+ const changes = String(process.env.KLD_SDD_CHANGE || '').split(/[,\s]+/).filter(Boolean);
20
+ const refs = (process.env.SDD_PRE_PUSH_REFS || (process.stdin.isTTY ? '' : fs.readFileSync(0, 'utf8'))).replace(/\\n/g, '\n').trim();
21
+ if (!refs) throw new Error('PUSH_REFS_REQUIRED: 需要真实 pre-push refs;手动验证请运行 delivery-check verify');
22
+ for (const line of refs.split(/\r?\n/)) {
23
+ const fields = line.trim().split(/\s+/);
24
+ if (fields.length !== 4 || fields.some((f, i) => i % 2 === 1 && !/^[a-f0-9]{40}$|^[a-f0-9]{64}$/.test(f))) throw new Error('PUSH_REFS_INVALID');
25
+ const [, localSha, , remoteSha] = fields;
26
+ if (/^0+$/.test(localSha)) continue;
27
+ if (!changes.length) throw new Error('CHANGE_REQUIRED: 严格推送检查需要 KLD_SDD_CHANGE 明确关联');
28
+ const base = /^0+$/.test(remoteSha) ? snap.git(project, ['mktree'], { input: '' }).trim() : remoteSha;
29
+ const revisions = snap.git(project, ['show', '-s', '--format=%(trailers:key=Spec-Revision,valueonly)', localSha]).trim().split(/\s+/).filter(Boolean);
30
+ for (const change of changes) {
31
+ const result = delivery.verify({ project, 'spec-root': specRoot, change, scope: 'commit', ref: localSha, base,
32
+ 'spec-ref': revisions.length === 1 ? revisions[0] : undefined });
33
+ if (!result.ok) throw new Error(result.errors.join('; '));
34
+ }
71
35
  }
72
- return /^[0-9a-f]{40}$/.test(EMPTY_TREE_SHA) ? EMPTY_TREE_SHA : null;
73
- }
74
-
75
- // strict 模式仅 pre-commit 支持:显式提示而非静默忽略
76
- const _mode = core.loadConsistencyMode();
77
- if (process.env.SDD_STRICT_CONSISTENCY === '1' || _mode.strict) {
78
- console.log('[SDD push-consistency-check] ℹ️ SDD_STRICT_CONSISTENCY 仅在 pre-commit 阶段生效,push 阶段忽略');
36
+ console.log('[SDD] 指定推送提交的交付证据验证通过');
37
+ } catch (error) {
38
+ console.error(`[SDD] ${error.message}`);
39
+ if (warnOnly) console.error('[SDD] 仅告警模式,推送继续(交付仍未验证)');
40
+ process.exitCode = warnOnly ? 0 : 1;
79
41
  }
80
-
81
- core.runConsistencyCheck({
82
- label: '[SDD push-consistency-check]',
83
- actionNoun: '推送',
84
- diffFn: gitPushRangeDiff,
85
- checkConfidence: false, // 置信度校验由 pre-commit 完成,push 阶段不重复
86
- includeUntracked: false, // untracked 文件不在任何 commit 中,不会被推送
87
- staleFromHead: true, // 过期判断读 HEAD 已提交内容,避免工作区未提交修改误判
88
- });
@@ -171,8 +171,8 @@ function recordTelemetry(projectRoot, activeStage, record, result, exitCodeKnown
171
171
  skipped: counts.skipped,
172
172
  } : {}),
173
173
  duration_ms: Number.isFinite(toolResponse.duration_ms) ? toolResponse.duration_ms : 0,
174
- failure_type: result === 'failure' ? (exitCode == null ? 'infrastructure' : 'assertion') : 'none',
175
- expected_failure: tddPhase === 'red' && result === 'failure' && exitCode != null,
174
+ failure_type: result === 'failure' ? (exitCode != null && /ERR_ASSERTION|AssertionError|AssertionFailedError/.test(output) ? 'assertion' : 'infrastructure') : 'none',
175
+ expected_failure: tddPhase === 'red' && result === 'failure' && exitCode != null && /ERR_ASSERTION|AssertionError|AssertionFailedError/.test(output),
176
176
  };
177
177
  strictTestEvent = exitCode != null && Boolean(activeStage.task_id);
178
178
  runId = stableRunId(input || {}, activeStage, details.test_results.command);
@@ -1,7 +1,13 @@
1
1
  /**
2
2
  * Shared SDD hook gate utilities for Claude and CodeBuddy adapters.
3
+ *
4
+ * 注意:本文件在 templates/hooks/codebuddy/hooks/hook-gate-core.cjs 有一份
5
+ * 逐字节相同的副本(模板 hook 以 ./hook-gate-core.cjs 相对引用,需可就地 require)。
6
+ * 修改本文件后必须同步副本,否则 test/codebuddy-hooks.cjs UT-022 漂移守卫会失败。
3
7
  */
4
8
 
9
+ 'use strict';
10
+
5
11
  const fs = require('fs');
6
12
  const path = require('path');
7
13
 
@@ -666,7 +672,6 @@ function detectTddBatchPattern(events, sinceTimestamp, tasksMdContent) {
666
672
  }
667
673
 
668
674
  module.exports = {
669
- PROJECT_ENV_KEYS,
670
675
  readStdin,
671
676
  parseHookInput,
672
677
  normalizeHookInput,
@@ -685,12 +690,6 @@ module.exports = {
685
690
  evaluateApplyWriteGate,
686
691
  evaluateSkillApplyGate,
687
692
  evaluatePreToolDangerGate,
688
- // TDD 批量执行检测
689
- extractTddTestEvents,
690
- buildPairMap,
691
- detectConsecutiveReds,
692
- detectInterleavingViolation,
693
- detectTimestampClustering,
694
- detectRapidPairing,
693
+ // TDD 批量执行检测(子检测器仅内部使用,对外只暴露聚合入口)
695
694
  detectTddBatchPattern,
696
695
  };
@@ -160,8 +160,8 @@ function recordTelemetry(projectRoot, activeStage, record, result, exitCodeKnown
160
160
  skipped: counts.skipped,
161
161
  } : {}),
162
162
  duration_ms: Number.isFinite(toolResponse.duration_ms) ? toolResponse.duration_ms : 0,
163
- failure_type: result === 'failure' ? (exitCode == null ? 'infrastructure' : 'assertion') : 'none',
164
- expected_failure: tddPhase === 'red' && result === 'failure' && exitCode != null,
163
+ failure_type: result === 'failure' ? (exitCode != null && /ERR_ASSERTION|AssertionError|AssertionFailedError/.test(output) ? 'assertion' : 'infrastructure') : 'none',
164
+ expected_failure: tddPhase === 'red' && result === 'failure' && exitCode != null && /ERR_ASSERTION|AssertionError|AssertionFailedError/.test(output),
165
165
  };
166
166
  strictTestEvent = exitCode != null && Boolean(activeStage.task_id);
167
167
  runId = stableRunId(input || {}, activeStage, details.test_results.command);
@@ -7,7 +7,7 @@ module: "<module>" # modules.yaml 中的模块代号;跨模块用 cross
7
7
  # affected-modules: # 仅 module=cross 时必填,至少两个已注册模块
8
8
  # - fi
9
9
  # - mm
10
- entity-id: "<8位十六进制ID>" # Change 的全局逻辑实体 ID,added 时生成
10
+ entity-id: "<完整UUID>" # Change 的全局逻辑实体 ID,added 时生成
11
11
  version-id: "<UUID>" # 本次 Change 版本 UUID
12
12
  delta-state: "added"
13
13
  predecessor-version: "" # added 留空;modified/removed 指向直接前序版本
@@ -20,6 +20,14 @@ capability-id: "CAP-<CAPABILITY>" # 必须与 proposal.md 中的 Capability ID
20
20
 
21
21
  <!-- 新增实体按当前最大序号 + 1 分配 ID;已有实体修改时复用原 ID -->
22
22
 
23
+ <!-- 只写本能力直接使用、且对规则或场景有意义的业务对象;普通技术 DTO 不写 -->
24
+ #### 业务对象:[OBJ-<CAPABILITY>-NNN] <!-- 业务对象名称 -->
25
+ - **entity-id**: <UUID>
26
+ - **version-id**: <UUID>
27
+ - **delta-state**: added
28
+ - **predecessor-version**: 无
29
+ - **关键状态/属性**: <!-- 只列影响业务判断的字段 -->
30
+
23
31
  #### 需求项:[STMT-<CAPABILITY>-NNN] <!-- 需求名称 -->
24
32
  - **entity-id**: <UUID>
25
33
  - **version-id**: <UUID>
@@ -40,6 +40,7 @@ allowed-tools:
40
40
  > - 较大的 `--details-json` 负载可先写入文件,再通过 `--details-file="$(cat .sdd-spec-root)/skywalk-sdd/state/<变更名称>-<type>.json"` 传递(例如 `task_update` 对应 `<变更名称>-task-update.json`)。
41
41
  > - `task_update` 记录成功后会自动调用 `check-task` 更新 `tasks.md` 中的 checkbox;录入成功后,agent 可以通过 `check-task` 命令验证该 checkbox 已更新。
42
42
  > - **⚠️ 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」。
43
+ > - **默认测试入口**:使用 reference.md 中的 test-run 执行、采集和关联真实证据;可用 completion-file 同步已验证任务。不手填退出码、测试计数和耗时。
43
44
  > - **严格证据链**:一次真实测试执行只写一条严格 `test_result`;任务完成事件只通过 `test_event_id` 引用成功的 green/refactor/regression 测试,并明确 `tdd_required=true/false`,不复制测试计数。测试不适用时必须写明原因。完整 schema 见 `./reference.md`。
44
45
  > - **任务涉及文件必记**:每条严格 `task_update` 必须在 `task_update.files` 写本任务实际修改的仓库相对路径;本任务确实没有改文件时,改填具体的 `no_file_change_reason`。两者至少有一个。
45
46
  > - **最终交付文件必记**:apply 所有文件就绪后记录严格 `final_output_snapshot`,其中 `final_output_snapshot.files` 是最终交付文件的仓库相对路径清单。报告把它与逐任务文件分开说明;旧 `ai_adoption_review.ai_diff.files` 只作兼容来源。
@@ -292,33 +293,35 @@ g. **继续下一个层级** — 重新检查 DAG,找出依赖已满足的下
292
293
 
293
294
  ### 6. 完成或暂停时显示状态
294
295
 
295
- 展示 DAG 执行摘要,引导下一步:
296
- > "📊 **实施进度摘要**:
297
- > - 已完成:[N/M] 任务
298
- > - 当前层级:Layer [X]
299
- > - 下一步建议:[继续实施 / 运行测试 / 归档]"
300
-
301
- **【已授权连续处理完成】**
302
- 若本次为用户已授权的连续处理,完成时展示一次整体交付结果:
303
- > "✅ **本轮连续处理完成**
304
- > - propose → spec → design → task → check → apply 已全部执行完毕
305
- > - 各阶段文档已生成,质量门禁已执行
306
- > - 建议下一步:运行测试 / 归档变更"
307
-
308
- > **💡 代码评审提示**:
309
- > 建议执行 `/kld-review --local` 对本次变更的代码进行评审。
310
- > 该技能可在公司内部 SkillHub 下载安装。
311
- >
312
- > **🧹 Worktree 收尾**:若本次使用了 worktree,见 **§6.1**;若判定未建 worktree,跳过 §6.1。
313
- > **其他 capability**:若并行 apply 中仍有未 finish 的 worktree,提示按 proposal 依赖顺序继续 `finish`。
296
+ 先执行下面的收尾验证,再展示实施摘要。验证未完成时显示「代码已保存,交付待验证」并列出缺口,不展示「全部完成」或把测试留给用户手动执行。
297
+
298
+ ### 6.0 实施收尾:自动检查、测试与就绪判定
299
+
300
+ 此节由 Agent 在当前授权范围内连续执行,无需用户串联多个 Skills。`opsx-check` 的文档结果不替代代码检查。
301
+
302
+ 1. 整理任务状态和最终 Spec 后,调用 `opsx-consistency-check`,明确本次 Change、代码仓以及实施前基线。回执有效则复用;失效时定向重查。多仓只检查本次涉及的仓,每仓独立保留证据。
303
+ 2. 使用下列入口执行最终回归测试;它内部调用原 `test-run`,保留严格测试事件、原始日志和任务关联,不重复手写相同测试事件。已有任务级 RED/GREEN 证据继续保留。命令必须是真实测试或项目认可的验证命令,不能用 `echo`、空测试冒充验证。
304
+
305
+ ```bash
306
+ node "<spec-root>/skywalk-sdd/git-hooks/delivery-check.cjs" test --project="<代码仓>" --change=<change> --session-id=<会话ID> --task-ids=<任务ID列表> --command-file="<测试命令JSON数组文件>"
307
+ ```
308
+
309
+ 命令文件放在 prepare 输出的状态目录,内容如 `["node","--test","test/order.test.cjs"]`。脚本取证前后核对输入;测试修改代码或 Spec 时,本次回执失效。详细 RED/GREEN 与任务完成证据仍见 `./reference.md`「§6.0」和 `./checklist.md`。
310
+ 3. 执行就绪判断,失败就修复并补足对应证据;正常 Git 保存和本地编辑仍可继续。
311
+
312
+ ```bash
313
+ node "<spec-root>/skywalk-sdd/git-hooks/delivery-check.cjs" verify --project="<代码仓>" --change=<change>
314
+ ```
315
+
316
+ `status=ready` 只表示该快照的本地检查和测试证据完整。不得把它表述为已入库、已发布或已合并。只有本次无业务代码变化、四个检查维度均有依据判为不适用,且检查回执显式写入 `tests: {"status":"na","reason":"具体理由"}` 时,工具才允许省略测试并显示 `testStatus=not_applicable`。其余缺少可执行验证命令的项目标记待验证,不凭模型文字造测试。`test-strategy=none` 免除任务级 TDD,不自动证明交付验证通过。
314
317
 
315
- ### 6.0 【条件必做】单元测试真实执行(`test-strategy` 非 `none`)
318
+ 收尾合并或提交后,若需验证最终提交,运行 `verify --scope=commit --ref=<目标SHA> --base=<实施前SHA>`;多仓再提供 `--spec-ref=<实际验证的完整Spec提交SHA>`。工具读取指定 Git 对象,不读取别的 HEAD 或工作区替代。冲突修复改变内容时重新检查和测试。
316
319
 
317
- 当 `proposal.md` 的 `test-strategy` 为 **`tdd`** 或 **`impl-first`** 时,在结束 apply 或执行 §6.1 收尾之前,必须真实运行单元测试并留 telemetry 证据。**详细执行要求与证据形式见 `./reference.md`「§6.0」+ `./checklist.md`「§6.0 单元测试真实执行自检」**。${HOOK_GATE_DESCRIPTION}
320
+ 所有涉及仓验证完成后,才输出整体结果:完成范围、真实验证结果、知识发布状态和剩余问题。现有 start/end、final_output_snapshot、使用上报照常执行。没有自动启用 CI;团队可将同一严格命令接入实际合并流程,并提供对应回执和测试原始日志。
318
321
 
319
322
  ### 6.1 【条件必做】Worktree 收尾(仅当 §1.5 已创建 worktree)
320
323
 
321
- > **⛔ 本次 Apply 若创建了 worktree**:DAG 全部完成且 §6.0 测试门禁(若适用)通过后,必须在**主仓库根目录**执行收尾脚本(禁止在 `.worktrees/...` 内执行)。
324
+ > **⛔ 本次 Apply 若创建了 worktree**:DAG 全部完成且 §6.0 交付验证通过后,必须在**主仓库根目录**执行收尾脚本(禁止在 `.worktrees/...` 内执行)。
322
325
  > 若 §1.5 判定未建 worktree(串行、强依赖、沙箱回退),跳过本节。
323
326
 
324
327
  **前置条件、执行命令、脚本行为、常用 flags、回退方式见 `./reference.md`「§6.1 Worktree 收尾」+ `./checklist.md`「§6.1 Worktree 收尾前置条件自检」**。
@@ -335,6 +338,7 @@ g. **继续下一个层级** — 重新检查 DAG,找出依赖已满足的下
335
338
  - **⛔ 渐进式加载 + 隔离红线**:只加载当前 Capability 的四文档链,默认聚焦当前 Capability;为核对已声明依赖可读取相关 Capability 契约并注明来源,不全量加载或混写其他能力。
336
339
  - **⛔ DAG 依赖拦截**:执行任务前必须检查依赖,前置未完成必须拦截。
337
340
  - **⛔ 编译检查门禁**:每完成一个任务后必须运行编译检查,编译失败禁止标记已完成。
341
+ - **环境型编译失败不算任务失败**:编译报 403/私服认证/依赖下载超时等环境型失败与代码无关,不回滚任务状态、不标记任务失败;失败时记录 `process_note(kind=api_error, target=compile)` 并附真实报错,用户修复环境(如补 settings.xml)且编译门禁重跑通过后记录 `process_note(kind=recovery, target=compile)`;仅重跑编译门禁,任务实现不重做。环境阻塞的任务保持未完成态:不阻断同层独立任务继续;依赖它的任务等待环境修复,不得抢跑;修复后仅重跑受影响任务的编译门禁。
338
342
  - **⛔ 测试执行门禁**:根据 `test-strategy` 决定(tdd=强制, impl-first=强制补跑, none=跳过);须真实执行并留 telemetry。${HOOK_GATE_DESCRIPTION}
339
343
  - **⛔ 必须实时更新任务状态**:每完成一个任务立即改 tasks.md,两种格式同步。
340
344
  - **⛔ apply 结束前 checkbox 全量同步校验**:`stage_end` 前对比 telemetry `task_update` 记录数与 tasks.md `[x]` 数量,不一致则补齐(见 `./checklist.md` §5f.1)。
@@ -348,13 +352,13 @@ g. **继续下一个层级** — 重新检查 DAG,找出依赖已满足的下
348
352
  - **⛔ 子代理不建分支**:worktree/apply 分支仅在 §1.5(主会话)创建一次,§5 子代理不得再建。
349
353
  - **显示进度反馈**:每完成一个任务显示「✅ [TASK-ID] 已完成 [N/M]」。
350
354
  - **保持任务聚焦**:每次只处理一个任务。
351
- - **遇到问题时暂停**:任务描述模糊、编译失败、测试失败或发现设计问题时暂停询问。
355
+ - **遇到问题时暂停**:任务描述模糊、编译失败、测试失败或发现设计问题时暂停询问;其中环境型编译失败(403/私服认证/依赖下载超时)不按代码型失败暂停,按上文「环境型编译失败不算任务失败」处理。
352
356
 
353
357
  ---
354
358
 
355
359
  ## 渐进披露
356
360
 
357
- - Read `checklist.md` 仅在执行 apply 需要校验门禁/自检时 — 含 §1.2 Check 门禁检查点、§5d/§5e 编译/测试门禁自检、§5e.1 TDD 节奏校验、§5f.1 checkbox 全量同步校验、§6.0 单元测试真实执行自检、§6.1 worktree 收尾前置条件、Guardrails ⛔ 强制项勾选表。
361
+ - Read `checklist.md` 仅在执行 apply 需要校验门禁/自检时 — 含 §1.2 Check 门禁检查点、§5d/§5e 编译/测试门禁自检、§5e.1 TDD 节奏校验、§5f.1 checkbox 全量同步校验、§5f.2 锚点定位失败降级、§6.0 单元测试真实执行自检、§6.1 worktree 收尾前置条件、Guardrails ⛔ 强制项勾选表。
358
362
  - 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 收尾脚本。
359
363
  - `implementer-prompt.md` 为子代理派发提示模板(§5c 派发时组合 tasks/design/overview 上下文使用)。
360
364
  - `worktree-setup.md` 为 worktree 快速参考(§1.5 策略的精简版,与 reference.md §1.5 完整版并存:reference=完整策略,worktree-setup=快速参考)。
@@ -30,7 +30,7 @@ description: opsx-apply 的阶段强制检查点与自检清单。仅在执行 a
30
30
 
31
31
  - [ ] 检测项目类型并执行编译命令
32
32
  - [ ] 编译成功 → 继续下一步
33
- - [ ] 编译失败 → **必须立即修复,禁止标记为已完成!**
33
+ - [ ] 编译失败 → **必须立即修复,禁止标记为已完成!**(例外:403/私服认证/依赖下载超时等环境型失败按 SKILL.md「环境型编译失败不算任务失败」处理,记 `process_note(kind=api_error, target=compile)`,不算代码型失败、不暂停修复代码)
34
34
 
35
35
  ### §5e 测试执行门禁(按 `proposal.md` 的 `test-strategy`)
36
36
 
@@ -95,6 +95,14 @@ description: opsx-apply 的阶段强制检查点与自检清单。仅在执行 a
95
95
  - [ ] 文档更新项(如有)已完成或显式标注推迟
96
96
  - [ ] 所有文件就绪后已记录严格 `final_output_snapshot`:`snapshot_kind=final`,`vcs_mode=readonly|no-git`,`files_changed` 等于 `files` 去重数量,新增/删除行数符合 VCS 模式;无交付文件时 `files=[]`、`files_changed=0` 且有具体 `no_output_reason`
97
97
 
98
+ ### §5f.2 锚点定位失败降级(任务实施中 Edit 失败时)
99
+
100
+ 对 design/tasks 中声明的代码锚点做 Edit 失败时,按序降级;**禁止一次失败即跳过任务、禁止虚构锚点**。任务声明的锚点在目标文件中不存在、或跨文档引用缺失时,同样**禁止静默跳过该任务/步骤**(如跳过 import、跳过调用),按第 3 步暂停上报:
101
+
102
+ 1. **重试**:收窄匹配串(含更多上下文行)或放宽匹配串(去掉行首缩进差异)各重试一次;每次重试记录 `process_note(kind=recovery, target=文件路径)`;
103
+ 2. **行块替换**:读取锚点前后 3 行,用该行块作为 `old_str` 重新定位替换;
104
+ 3. **暂停上报**:连续 3 次失败后**停止修改**,向用户报告目标文件、锚点声明与已尝试的匹配串,等待用户决策;用户给出处理方式后记录 `process_note(kind=user_decision, decision_type=other, target=文件路径)`。⛔ 禁止用整文件重写方式落地任务产出(重写已有代码文件引入的回归风险远大于锚点失败本身)。
105
+
98
106
  ---
99
107
 
100
108
  ### §5g 中途 TDD 节奏检查点(每完成 10 个 TDD 任务后强制执行)
@@ -141,7 +149,7 @@ description: opsx-apply 的阶段强制检查点与自检清单。仅在执行 a
141
149
  - [ ] ⛔ **渐进式加载**:只加载当前 Capability 的四文档链
142
150
  - [ ] ⛔ **隔离红线**:默认聚焦当前 Capability;为核对已声明依赖可读取相关 Capability 契约并注明来源,不全量加载或混写其他能力。
143
151
  - [ ] ⛔ **DAG 依赖拦截**:执行任务前必须检查依赖,前置未完成必须拦截
144
- - [ ] ⛔ **编译检查门禁**:每完成一个任务后必须运行编译检查,编译失败禁止标记已完成
152
+ - [ ] ⛔ **编译检查门禁**:每完成一个任务后必须运行编译检查,编译失败禁止标记已完成(环境型失败例外,见 §5d)
145
153
  - [ ] ⛔ **测试执行门禁**:根据 `test-strategy` 决定(tdd=强制, impl-first=强制补跑, none=跳过);须真实执行并留 telemetry,`sdd-apply-test-gate` 校验非占位数据
146
154
  - [ ] ⛔ **RED 测试质量门禁**:见 §5e.2(引用 tdd-quality + tdd-anti-patterns,不在此内联复制)
147
155
  - [ ] ⛔ **必须实时更新任务状态**:每完成一个任务立即改 tasks.md,两种格式(`- [ ]`→`- [x]` 与 `**状态**: [ ]`→`[x]`)同步
@@ -158,4 +166,5 @@ description: opsx-apply 的阶段强制检查点与自检清单。仅在执行 a
158
166
  - [ ] **Capability 级并行**:多个 `/opsx-apply` 会话 = 多个 worktree;禁止为未解耦的 cap 仅因 full 模式而拆分支
159
167
  - [ ] **显示进度反馈**:每完成一个任务显示「✅ [TASK-ID] 已完成 [N/M]」
160
168
  - [ ] **保持任务聚焦**:每次只处理一个任务
161
- - [ ] **遇到问题时暂停**:任务描述模糊、编译失败、测试失败或发现设计问题时暂停询问
169
+ - [ ] **遇到问题时暂停**:任务描述模糊、编译失败、测试失败或发现设计问题时暂停询问(环境型编译失败除外,见 §5d)
170
+ - [ ] ⛔ **锚点定位失败降级**:见 §5f.2,Edit 失败按重试→行块替换→暂停上报降级,禁止一次失败即跳过任务、禁止整文件重写落地
@@ -2,6 +2,24 @@
2
2
  description: opsx-apply 的详细模板:telemetry 命令、worktree 全套策略、子代理派发、收尾脚本。仅在需要参考详细模板时读取。
3
3
  ---
4
4
 
5
+ ## 自动执行并取证(默认入口)
6
+
7
+ 使用 test-run 运行真实测试并记录同一条严格事件。工具采集命令参数、实际 cwd、退出码、耗时、测试计数和原始输出哈希;不让模型抄写这些字段。测试命令用 JSON 参数数组,无 shell 展开。
8
+
9
+ ```bash
10
+ node "<spec-package>/skywalk-sdd/log.cjs" test-run --project="<spec-package>" --change=<变更名称> --session-id=<会话ID> --task-ids=<TASK-ID列表> --cwd="<代码仓>" --tdd-phase=regression --command-json='["node","--test","--test-reporter=tap","test/order-total.test.js"]'
11
+ ```
12
+
13
+ RED 使用 --tdd-phase=red --expected-failure;真正的断言失败才能形成有效 RED。找不到测试入口/模块、编译/环境错误、超时均不能冒充业务红灯。命令返回实际测试退出码,失败仍保留事件与回执;不要因为 RED 非零就重复执行同一个 run-id。
14
+
15
+ 默认支持 Node TAP/Node 测试汇总。其他运行器输出无法可靠解析时 counts_known=false,不猜计数,不自动完成任务;已有适配器可继续用下方兼容入口提交实际报告。调用方明确声明 task-ids,工具不会把测试通过自动等同于覆盖了任意业务任务。
16
+
17
+ 需要测试成功后同步任务时,增加 --completion-file=<完成信息JSON文件>。内容为数组,每项包含 task_id、实际修改的仓库相对 files、tdd_required;TDD 任务同时写 tdd_pair_id/tdd_role。无文件修改填写 no_file_change_reason。工具将完成事件自动关联本轮 test_event_id 并同步任务勾选;RED、失败或未知计数不会自动完成任务。
18
+
19
+ 回执路径在输出 receipt 字段;原始 stdout/stderr 和执行清单保留在 skywalk-sdd/state/test-runs。记录失败后用原 details.json 重试 record --strict,禁止重写退出码或补造测试数。输出哈希不一致会被拒绝。自动 Hook 仅作补充,不对同一次 test-run 再手写一条 test_result。
20
+
21
+ 以下手写 test_result 模板仅保留给旧集成和已有测试报告适配器,新流程优先用 test-run。
22
+
5
23
  # opsx-apply — 详细参考(reference)
6
24
 
7
25
  > 本文件承载 opsx-apply 的重细节模板:telemetry 命令、§1.5 worktree 全套策略、§5c 子代理派发、§5.1 AI 产出快照、§6.0 单元测试真实执行、§6.1 worktree 收尾脚本。
@@ -95,7 +113,7 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=test_res
95
113
  - `expected_failure=true` 仅允许 `tdd_phase=red`
96
114
  - 有效 RED:`expected_failure=true` + `exit_code≠0` + `failure_type` 为 `assertion` 或 `contract`
97
115
 
98
- > **自动记录**:`sdd-post-tool.cjs` hook 会在 agent 运行 `mvn test`/`npm test` 等命令时自动记录 `test_result`,使用正确的 `test_results` key。但自动记录依赖 `activeStage.task_id`,若未设置则 `tdd_phase` 默认为 `regression`。需要精确标注 RED/GREEN 时建议手动记录。
116
+ > **自动记录**:`sdd-post-tool.cjs` hook 会在 agent 运行 `mvn test`/`npm test` 等命令时自动记录 `test_result`,使用正确的 `test_results` key。但自动记录依赖 `activeStage.task_id`,若未设置则 `tdd_phase` 默认为 `regression`。需要精确标注 RED/GREEN 时使用上方 test-run 自动取证。
99
117
 
100
118
  ### process_note(阶段内过程事件:决策/范围变化/故障与恢复)
101
119
 
@@ -129,6 +147,8 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --strict --type=process_
129
147
  | 编辑失败并重试 | `recovery` | 文件 |
130
148
  | 用户交互决策点(范围/模式/测试策略) | `user_decision` | - |
131
149
  | API 故障 | `api_error` | - |
150
+ | 编译环境失败(403/私服认证/依赖下载超时) | `api_error` | compile |
151
+ | 环境修复后编译门禁重跑通过 | `recovery` | compile |
132
152
  | 模型故障 | `model_error` | - |
133
153
  | 测试环境异常 | `test_exception` | - |
134
154
 
@@ -3,11 +3,11 @@ name: opsx-archive
3
3
  description: "归档变更技能 - 将已结束的 SDD 变更真实移入 archive,并生成最终中文度量报告"
4
4
  argument-hint: "[change-name]"
5
5
  license: MIT
6
- compatibility: Requires skywalk-sdd/log.cjs; depends on opsx-kb-ingest for KB upload.
6
+ compatibility: Requires skywalk-sdd/log.cjs; depends on opsx-kb-ingest and opsx-ontology-ingest for ontology publication.
7
7
  metadata:
8
8
  author: sdd-team
9
9
  version: "3.2"
10
- depends-on: opsx-kb-ingest
10
+ depends-on: opsx-kb-ingest, opsx-ontology-ingest
11
11
  allowed-tools:
12
12
  - Bash
13
13
  - Read
@@ -19,7 +19,7 @@ allowed-tools:
19
19
 
20
20
  你是一个 SDD(Specification-Driven Development)变更归档专家。激活本技能后,你要安全地结束变更生命周期:真实归档文档、同步正式 specs、记录 archive telemetry,并生成最终中文度量报告。
21
21
 
22
- > **硬依赖(收尾入库)**:zip 生成后的上传依赖同级已部署的 **`opsx-kb-ingest`**。用户已授权入库时,进入 §5.5 前读取该技能并检查目标配置;未授权或 KB 不可用时保留本地归档和待入库状态。入库成功后,`Read` `opsx-ontology-query/phase-3-postchange.md` 验证版本生效、AC 保留、关系完整性。缺失则提示用户重新 `kld-sdd-init`,**不要**自造另一套入库协议。
22
+ > **硬依赖(收尾入库)**:zip 生成后通过 **`opsx-ontology-ingest`** 完成本体校验、上传和召回验证;其底层复用 `opsx-kb-ingest`。用户已授权入库时,进入 §5.5 前读取该技能并检查目标配置;未授权或 KB 不可用时保留本地归档和待入库状态。
23
23
 
24
24
  > **跨平台执行规则**
25
25
  > - **SDD 文档根** = `*-sdd-specs` 包裹包(含 `openspec/`、`modules.yaml`),不是 Git 根或工作区根。
@@ -45,7 +45,7 @@ allowed-tools:
45
45
 
46
46
  ## 启动流程
47
47
 
48
- ### 1. 确认变更名称并记录阶段开始
48
+ ### 1. 确认变更名称
49
49
 
50
50
  如果未提供变更名,运行:
51
51
 
@@ -53,13 +53,7 @@ allowed-tools:
53
53
  openspec list
54
54
  ```
55
55
 
56
- 让用户选择现有变更。确认后记录阶段开始:
57
-
58
- ```bash
59
- node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" start --command=archive --project=. --change=<变更名称> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID>
60
- ```
61
-
62
- 保存 `event_id`。
56
+ 按参数、会话或唯一活动变更定位;只有多个候选且无法判断时请用户选择。此时尚未开始 archive 阶段。
63
57
 
64
58
  ### 2. 记录归档原因
65
59
 
@@ -85,6 +79,14 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" doctor --project=. --change=<
85
79
 
86
80
  如果存在 `severe_issues`,暂停归档并说明必须先修复。`superseded_open_stages` 和 `rework_summary` 只作为返工/重复执行展示,不要求用户人工区分测试回滚或真实研发返工。
87
81
 
82
+ 诊断通过后才记录本轮 archive 开始,保存返回的 `event_id`:
83
+
84
+ ```bash
85
+ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" start --command=archive --project=. --change=<变更名称> --agent=<Agent类型> --source=opsx-command --session-id=<会话ID>
86
+ ```
87
+
88
+ 不要在本轮阶段已开始但未结束时再次运行前置 doctor;历史未闭环阶段仍须按真实结果补齐,不得跳过诊断或删除事件。
89
+
88
90
  ### 4. 扫描 tasks 完成状态
89
91
 
90
92
  ```bash
@@ -145,8 +147,8 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" archive-docs --project=. --chan
145
147
 
146
148
  该命令成功后必须已经完成:
147
149
  - 活动目录 `openspec/changes/<name>/` 被移入 `openspec/changes/archive/<日期>-<name>/`。
148
- - 归档目录写入 `archive-ontology.json`、`canonical-facts.json`、`conversion-report.json` 和新版 `archive-manifest.json`。
149
- - 生成知识库可直接消费的 `openspec/changes/archive/<日期>-<name>.zip`(canonical-facts **v2**,含 `external_refs`),包内文件必须由 manifest 完整列举并通过 SHA-256 校验。
150
+ - 归档目录写入 `archive-ontology.json`、`canonical-facts.json`、`spec-ontology.json`、`conversion-report.json` 和新版 `archive-manifest.json`。
151
+ - 生成知识库可直接消费的 `openspec/changes/archive/<日期>-<name>.zip`(canonical-facts **v2** + spec-ontology **v1**),包内文件必须由 manifest 完整列举并通过 SHA-256 校验。
150
152
  - Full Spec 的 `specs/<capability>/spec.md` 同步到 `openspec/specs/<capability>/spec.md`。
151
153
  - archive 阶段写入 `stage_end`。
152
154
  - 未勾选 tasks 被写入 `archive_result.task_completion`。
@@ -164,10 +166,10 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/ontology/cli.cjs" active-change --remove
164
166
 
165
167
  把该 change 从 spec 仓 `sdd.config.yaml` 的 `active_changes` 移除,避免已归档 change 继续被代码 commit 写成 `Spec-Change`。该操作幂等;条目本就不存在时不报错。
166
168
 
167
- ### 5.5 收尾入库(opsx-kb-ingest)
169
+ ### 5.5 收尾入库(opsx-ontology-ingest)
168
170
 
169
- 1. 确认 `${AGENT_SKILL_DIR}/opsx-kb-ingest/SKILL.md` 存在并 Read;KB 配置(API Key / targets / project-identity.json)由 `opsx-kb-config` 统一负责,如未配置则记录待入库原因;用户要求配置时再运行 `/opsx-kb-config`,不阻断已完成的本地归档。
170
- 2. 归档 zip 生成后,若用户已授权入库且目标明确,加载并执行 `opsx-kb-ingest` 上传,也可使用 `kb-upload.cjs --package=<zip路径>`。未授权或断连时保留包并报告待入库,不把本地归档成功写成发布成功。只有真实入库回执成功后才写 `ingest-receipt.json`。
171
+ 1. 确认 `${AGENT_SKILL_DIR}/opsx-ontology-ingest/SKILL.md` 存在并 Read;KB 配置由 `opsx-kb-config` 统一负责。
172
+ 2. 归档 zip 生成后,若用户已授权入库且目标明确,执行 `opsx-ontology-ingest`:先校验 `spec-ontology.json`,再复用 `kb-upload.cjs --package=<zip路径>` 上传,最后用 `--mode=spec-generation` 召回验证。
171
173
  3. 若返回 `EXTERNAL_REF_CONFLICT`,引导回 spec/check 修正后重入,**禁止**在 KB 内现场改绑。
172
174
 
173
175
  > 注意:`archive-docs` 成功执行后已经在内部写入 `stage_end`,因此**不要在成功的归档后再单独运行 `node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" end --command=archive ...`**。仅在第 5 步归档命令失败时,才需要运行下方的失败分支 `end`。
@@ -189,7 +191,7 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" end --event-id=<event_id> --com
189
191
  > - 最终报告(Markdown + HTML + JSON 三产物):`openspec/changes/archive/<日期>-<name>/reports/<name>-report.md`、`<name>-report.html`、`<name>-report.json`
190
192
  > - 执行日志:`openspec/changes/archive/<日期>-<name>/logs/execution-log.md`
191
193
  > - 知识库归档包:`openspec/changes/archive/<日期>-<name>.zip`
192
- > - 本体消费入口:`openspec/changes/archive/<日期>-<name>/canonical-facts.json`
194
+ > - 本体消费入口:`openspec/changes/archive/<日期>-<name>/spec-ontology.json`
193
195
  > - 未勾选任务:X 项,已记录到报告,不阻断归档
194
196
  > - 正式 specs:`openspec/specs/`
195
197
 
@@ -219,7 +221,7 @@ node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" record --type=baseline_record -
219
221
  - 随后必须运行 `node "$(cat .sdd-spec-root)/skywalk-sdd/log.cjs" semantic-check --project=. --change=<变更名称>`;有阻断诊断时禁止移动活动 Change。
220
222
  - Archive 不负责首次生成 propose/spec/design/tasks 的工作态事实;它重新解析原文核对 pending revision,补充 `OntologySnapshot/project_id/archive_id` 后冻结为 confirmed。
221
223
  - `archive-docs` 成功后必须在归档目录生成 `archive-ontology.json`,并将 `review_status` 标记为 `confirmed`。
222
- - 生产端必须把 confirmed 本体转换为 `canonical-facts.json`;实体固定为 `fact_kind=semantic`、`assertion_type=asserted`、`review_status=confirmed`,关系必须补齐对应语义边界字段。
224
+ - 生产端必须同时产出 `canonical-facts/v2` 与 `spec-ontology/v1`;前者用于旧链路兼容,后者是 Spec 生成飞轮的主协议。
223
225
  - `acceptedBy` 在消费协议中归一化为 `verifiedBy`;inferred 关系必须携带 `rule_id`、`generator` 和 `generator_version`。
224
226
  - 每个 canonical 实体和关系的 `source.file` 必须存在于 Archive Package,`source.content_hash` 必须等于该原文文件的 SHA-256。
225
227
  - `archive-manifest.json` 必须使用 `kld-sdd-archive-manifest/v2`,并与 canonical facts 的 project/archive/change 身份一致。
@@ -44,17 +44,20 @@ node "<spec-package>/skywalk-sdd/log.cjs" start --command=check --project="<spec
44
44
  ## 2. 程序预检(在完整文档评审前)
45
45
 
46
46
  ```bash
47
- node "<spec-package>/skywalk-sdd/log.cjs" semantic-check --project="<spec-package>" --change=<变更名称> --profile=auto --include-tasks
47
+ node "<spec-package>/skywalk-sdd/log.cjs" semantic-check --project="<spec-package>" --change=<变更名称> --profile=auto --include-tasks > "<spec-package>/skywalk-sdd/state/<变更名称>-preflight.json"
48
48
  ```
49
49
 
50
- 输出 `profile / valid / revision / counts / diagnostics`、`review_inputs`(文档路径与哈希、历史身份哈希)、`task_completion` 和 `timings_ms`。程序时间不等于模型评审总耗时。
50
+ 输出 `profile / valid / product_valid / revision / counts`、`product_diagnostics`、`tool_diagnostics`、`review_inputs`、`task_completion` 和 `timings_ms`。程序时间不等于模型评审总耗时。
51
51
 
52
- - semantic-check 已包含全量对账、工作态 JSON 原子刷新和 pending 标记;无需再调用 semantic-reconcile。pending 仅表示程序校验通过,不能宣称已完成独立评审或已入库。
52
+ - `product_valid` 只看产物质量。需求没有验收、需求没有设计、设计没有任务、任务没有上游、验收没有归属需求、产物缺失、任务依赖成环,这些进入报告并阻断 Check。
53
+ - `tool_diagnostics` 是工具升级带来的身份、来源、版本谱系和归档诊断。预检已把可物化的部分写入 `ontology/spec-ontology.json` 与 `ontology/legacy-mapping.json`,不改 Markdown。不要向用户展示这些诊断,不要要求用户补 UUID、改锚点或重做归档。
54
+ - 交给独立评审者的程序诊断只使用 `product_diagnostics`。报告只写产物缺口和 design 与 tasks 之间的覆盖缺失。
55
+ - semantic-check 已包含全量对账、工作态 JSON 原子刷新和 pending 标记;无需再调用 semantic-reconcile。`product_valid=true` 只表示产物结构没有阻断,不能宣称已完成独立评审或已入库。
53
56
  - 默认从产物推断 simple/full;用户或项目明确要求 strict 时传 `--profile=strict`,不能为通过而降级。
54
- - `simple` 阻断 STMT 无 AC,未生成 design/tasks 时跳过对应链路;`full` 阻断 STMT→AC→Design→Task 断链;`strict` 还要求完整来源字段。
55
- - 所有模式保留身份合法性、重复锚点、跨 Change/Archive 身份误复用、版本谱系、悬空引用、domain/range 和依赖成环门禁。added 使用新身份;modified/removed 复用实体并指向直接前驱;unchanged 引用历史版本且不复制正文。
56
- - Continuity、external_ref 与 `ontology/continuity-resolution.json` 必须一致。`CONTINUITY_DECISION_REQUIRED` / `CONTINUITY_IDENTITY_MISMATCH` / `EXTERNAL_REF_CONFLICT` 和编号诊断原样进入报告;不得临时改身份来绕过门禁。
57
- - 文件观察结果只作提示,不复用历史“通过”代替本轮全量校验。命令失败、诊断 error 或 valid=false 时先展示具体问题,在授权内修复后重试;无需模型再读全仓来重复确认确定性错误。若缺业务决定则本轮结束为 failure、说明“预检阻断,尚未独立评审”,保留阶段日志,不伪造 check_result。用户明确要求同时审阅其余问题时可继续独立评审,但总体仍失败。
57
+ - `simple` 阻断 STMT 无 AC,未生成 design/tasks 时跳过对应链路;`full` 阻断 STMT→AC→Design→Task 断链;`strict` 还要求完整来源字段,来源缺失按工具诊断自行旁路处理,不单独向用户追问。
58
+ - 产物门禁保留追溯断链、悬空业务引用、domain/range 和任务依赖成环。身份、重复锚点、归档版本和谱系由工具旁路处理。
59
+ - Continuity、external_ref 与 `ontology/continuity-resolution.json` 仍属于产物决定。`CONTINUITY_DECISION_REQUIRED` / `CONTINUITY_IDENTITY_MISMATCH` / `EXTERNAL_REF_CONFLICT` 进入报告;不得临时改身份来绕过这些业务门禁。
60
+ - 只有 `product_diagnostics` 里的 error 才向用户展示并在授权内修复后重试。仅有工具诊断时继续独立评审,不把本轮记成预检失败。缺业务决定时本轮结束为 failure,说明“预检阻断,尚未独立评审”。
58
61
 
59
62
  ### 多仓库关联配置
60
63
 
@@ -75,7 +78,7 @@ node "<spec-package>/skywalk-sdd/log.cjs" semantic-check --project="<spec-packag
75
78
 
76
79
  ## 3. 一次独立评审
77
80
 
78
- 程序预检后交给评审者:`review_inputs` 对应的最终文件路径、profile/test-strategy、任务状态、程序诊断、用户指定的上下文路径、检查范围和作者会话 ID。只传客观输入,不传作者对话或主 Agent 的结论摘要。主 Agent 从 proposal 元数据确定测试策略即可,无需预读正文。
81
+ 程序预检后交给评审者:`review_inputs` 对应的最终文件路径、profile/test-strategy、任务状态、`product_diagnostics`、用户指定的上下文路径、检查范围和作者会话 ID。不传 `tool_diagnostics`,不传作者对话或主 Agent 的结论摘要。评审重点是产物是否完整,以及 spec、design、tasks 之间有没有覆盖缺失。
79
82
 
80
83
  ${CHECK_REVIEW_DELEGATION_GUIDANCE}
81
84
 
@@ -93,16 +96,18 @@ ${CHECK_REVIEW_DELEGATION_GUIDANCE}
93
96
 
94
97
  ## 4. 一次记录与结束
95
98
 
96
- 评审完成后,主 Agent 读取 [reference.md](reference.md),将结构化结果按 [result-template.json](result-template.json) 写入本轮临时 details 文件,执行唯一的 strict check_result 命令,再执行 end。不要在 shell 中手工转义大段 JSON。
99
+ 将实际评审项和真实会话身份保存为 [review-template.json](review-template.json) 格式。每项只写唯一 ID、类别、结论和证据;工具自动计算统计、读取任务状态、判断 partial/failure、关联阶段结束。旧 [result-template.json](result-template.json) 仅保留给已有集成。
97
100
 
98
- 顶层 `total` 必须是大于 0 的整数且来自实测,不能照抄模板的 0。空 details 导致 Q3 不可计算,strict 会拒绝。consistency_score 是 legacy 兼容字段,不可评分填 null。未执行项不能计入通过;warning 记录明细和处置理由。
101
+ 类别:completeness / consistency / executability / tdd_compliance;状态:passed / error / warning / suggestion / na。所有项包含证据或不适用理由,na 不计入通过。不要手填 total、errors、fixed_before_apply 或任务计数,不把模板占位内容当作已评审。
102
+
103
+ 兼容旧集成时,顶层 `total` 必须是大于 0 的整数,且来自实际评审项;空 details 导致记录被拒绝、Q3 不可计算。`consistency_score` 仅为 legacy 字段,不能替代有证据的分类检查。新入口由工具计算这些统计,评审者无需重复填写。
99
104
 
100
105
  ```bash
101
- node "<spec-package>/skywalk-sdd/log.cjs" end --event-id=<event_id> --command=check --project="<spec-package>" --change=<变更名称> --capability=<可选capability-name> --agent=<Agent类型> --source=opsx-command --session-id=<父会话ID> --result=success/partial/failure --summary="本轮实测摘要"
106
+ node "<spec-package>/skywalk-sdd/log.cjs" check-record --project="<spec-package>" --change=<变更名称> --run-id=<本轮Check稳定ID> --session-id=<父会话ID> --agent=<Agent类型> --preflight-file="<spec-package>/skywalk-sdd/state/<变更名称>-preflight.json" --review-file="<spec-package>/skywalk-sdd/state/<变更名称>-review.json" --end-event-id=<event_id>
102
107
  ```
103
108
 
104
- 结束命令仍执行一次全量对账,核验评审期间文件/历史身份的变化;这次复核有时间边界意义,保留它。默认 auto 模式对照返回 semantic_state.revision 与预检 revision;不一致时不能宣称刚审过的版本仍有效,重新预检并复核变动及受影响的依赖,另记新一轮结果。显式 strict 时 end 的 auto revision 不能直接与 strict revision 比较;最终额外运行一次 --profile=strict 的 semantic-check 并比较 strict revision,auto 结果不能替代 strict 门禁。
109
+ check-record 按预检的同一 profile 重新核验正文、文件集合和历史身份。输入变化返回 CHECK_REVIEW_STALE,不写本轮通过记录;重新预检并复核受影响内容。成功时仍通过原 strict 校验和阶段结束入口,不另手动执行 end。评审输入始终保留,记录失败可以修复后重试。未真实开展评审时不用此命令,按原 end 命令记录 failure 和原因。
105
110
 
106
- 报告输出五维结论、多仓配置、KB 状态、证据与未执行项,说明覆盖范围。只请求检查则结束;已授权实现且无阻断项时进入 apply。修复文档后再检查相关依赖,禁止携带旧结论直接通过;不把 Capability 局部评审写成全 Change 通过。
111
+ 报告输出五维结论、多仓配置、KB 状态、产物证据与未执行项。只写需求、设计、任务之间的缺口和质量问题。身份、UUID、归档版本、重复锚点等工具处理结果不写入给用户的报告。只请求检查则结束;已授权实现且没有产物阻断项时进入 apply。修复文档后再检查相关依赖,禁止携带旧结论直接通过;不把 Capability 局部评审写成全 Change 通过。
107
112
 
108
113
  [checklist.md](checklist.md) 仅供日志异常/自检时读取,正常路径不再完整加载一遍。
@@ -1,5 +1,7 @@
1
1
  # Check 结果记录(主 Agent 在评审完成后读取)
2
2
 
3
+ 新流程优先使用 SKILL.md 中的 check-record 与 [review-template.json](review-template.json):工具计算统计、补任务状态、校验评审输入是否过期,并可一次结束阶段。以下完整字段和 record --strict 保留给已有脚本,不要求新流程手填。
4
+
3
5
  收到实际评审结果后,必须把结果转换为 `check_result` 事件,并在 `stage_end` 之前执行成功。禁止用 stage_end 代替已执行评审的证据。程序预检阻断且未开展评审时,只记录阶段 failure 与真实原因,不伪造 reviewer 或零项评审。
4
6
 
5
7
  字段口径:
@@ -21,7 +23,7 @@
21
23
  - `categories`: 必须包含 `completeness`、`consistency`、`executability`、`tdd_compliance`;四类 total 合计等于顶层 total,四类未通过数合计等于 errors。算法正确性计入 consistency,文字报告单列,避免重复计数。
22
24
  - `task_completion`: 复用本轮 `semantic-check --include-tasks` 的输出(使用 tasks-status 同一扫描器),只取模板中的计数字段;未进入 apply 时 `checked_for_archive_readiness=false`。
23
25
 
24
- 将评审结果写为 UTF-8 JSON:`skywalk-sdd/state/<变更名称>-check-<run-id>.json`,结构见 [result-template.json](result-template.json)。其中 `0` 是待替换位置,执行前换成本轮实测值,顶层 `total` 必须是大于 0 的整数。不要直接把安装目录中的模板传给命令(details 文件成功读取后默认清理)。
26
+ 将评审结果写为 UTF-8 JSON:`skywalk-sdd/state/<变更名称>-check-<run-id>.json`,结构见 [result-template.json](result-template.json)。其中 `0` 是待替换位置,执行前换成本轮实测值,顶层 `total` 必须是大于 0 的整数。不要直接把安装目录中的模板传给命令(details 文件仅在校验、记录和投影成功后清理,失败保留)。
25
27
 
26
28
  ```bash
27
29
  node "<spec-package>/skywalk-sdd/log.cjs" record --strict --type=check_result --command=check --project="<spec-package>" --change=<变更名称> --capability=<可选capability-name> --run-id=<本轮Check稳定ID> --agent=<Agent类型> --source=opsx-command --session-id=<父会话ID> --result=success/partial/failure --summary="检查结果摘要" --details-file=skywalk-sdd/state/<变更名称>-check-<run-id>.json