kld-sdd 2.7.8-5 → 2.7.8-7
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/bin/kld-sdd-init.js +86 -1
- package/lib/init.js +13 -1
- package/lib/maintenance.js +126 -1
- package/lib/skills-bundle.js +2 -0
- package/package.json +2 -2
- package/skywalk-sdd/context-client.cjs +38 -7
- package/skywalk-sdd/index.cjs +30 -3
- package/skywalk-sdd/kb-upload.cjs +160 -33
- package/skywalk-sdd/ontology/archive-package.cjs +141 -0
- package/skywalk-sdd/ontology/artifact-parser.cjs +24 -3
- package/skywalk-sdd/ontology/cli.cjs +53 -0
- package/skywalk-sdd/ontology/id.cjs +1 -1
- package/skywalk-sdd/ontology/schema.cjs +6 -0
- package/skywalk-sdd/ontology/spec-ontology.cjs +507 -0
- package/templates/openspec/spec.md +8 -0
- package/templates/skills/kld-sdd/opsx-archive/SKILL.md +10 -10
- package/templates/skills/kld-sdd/opsx-check/SKILL.md +11 -8
- package/templates/skills/kld-sdd/opsx-check/reviewer.md +2 -1
- package/templates/skills/kld-sdd/opsx-kb-ingest/SKILL.md +3 -2
- package/templates/skills/kld-sdd/opsx-ontology-ingest/SKILL.md +77 -0
- package/templates/skills/kld-sdd/opsx-ontology-query/SKILL.md +5 -4
- package/templates/skills/kld-sdd/opsx-ontology-query/reference.md +14 -1
- package/templates/skills/kld-sdd/opsx-spec/SKILL.md +5 -3
package/bin/kld-sdd-init.js
CHANGED
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
const path = require('path');
|
|
21
21
|
const { listToolProfileIds, buildToolConfigs } = require('../lib/tool-profiles');
|
|
22
22
|
const { MODE, OP, modeLabel } = require('../lib/uninstall');
|
|
23
|
-
const
|
|
23
|
+
const specDetect = require('../skywalk-sdd/ontology/spec-detect.cjs');
|
|
24
|
+
const { specSourceLabel } = specDetect;
|
|
24
25
|
// spec 候选单选交互(唯一实现,与 lib/init.js 共用)
|
|
25
26
|
const { selectSpecRoot: selectSpecChoice } = require('../lib/spec-choice');
|
|
26
27
|
|
|
@@ -125,6 +126,9 @@ function parseInitArgs(argv = cliArgs(), env = process.env) {
|
|
|
125
126
|
verbose: isVerbose(argv, env),
|
|
126
127
|
skipOpenspec: argv.includes('--skip-openspec'),
|
|
127
128
|
skipTemplate: argv.includes('--skip-template'),
|
|
129
|
+
repairGit: argv[0] === 'repair-git' || argv.includes('--repair-git'),
|
|
130
|
+
applyRepair: argv.includes('--apply'),
|
|
131
|
+
json: argv.includes('--json'),
|
|
128
132
|
tools,
|
|
129
133
|
// 显式给了 --tool 即自动化场景:lib 据此抑制 spec 路径的交互询问
|
|
130
134
|
hasToolArg: tools !== null,
|
|
@@ -357,6 +361,7 @@ KLD SDD 项目初始化工具
|
|
|
357
361
|
kld-sdd-init [选项]
|
|
358
362
|
npx kld-sdd [选项]
|
|
359
363
|
kld-sdd sync-repos # 工作目录下发现新增代码仓并轻量接入(多 spec 候选时单选)
|
|
364
|
+
kld-sdd repair-git # 检查并清理旧 Spec 仓的工具跟踪噪声(默认只预览)
|
|
360
365
|
kld-sdd uninstall [选项] # 卸载 SDD 产物(渐进式:预览工具范围 → 确认)
|
|
361
366
|
kld-sdd uninstall --help # 查看工具卸载与保留范围
|
|
362
367
|
|
|
@@ -366,6 +371,9 @@ KLD SDD 项目初始化工具
|
|
|
366
371
|
--verbose 输出每个安装文件/目录的明细日志(默认仅摘要,亦可用 KLD_SDD_VERBOSE=1)
|
|
367
372
|
--skip-openspec 跳过 openspec init 步骤
|
|
368
373
|
--skip-template 跳过复制内置模版
|
|
374
|
+
--repair-git 检查 Spec 仓中被 Git 跟踪的安装器工具(默认只预览)
|
|
375
|
+
--apply 与 --repair-git 同用:保留本地文件,仅从 Git 索引移除工具
|
|
376
|
+
--json --repair-git 输出机器可读 JSON,供托盘健康检查使用
|
|
369
377
|
--tool <name> 指定编辑器,可用值: cursor, claude, codebuddy, qoder, opencode, kunlunzhima, workbuddy, codex, all
|
|
370
378
|
--spec-path <dir> 指定 spec 包裹包目录(必须是当前目录的子目录)。
|
|
371
379
|
不指定时(交互终端):自动检测已有 spec 目录(目录名 *-sdd-specs,
|
|
@@ -385,6 +393,8 @@ KLD SDD 项目初始化工具
|
|
|
385
393
|
kld-sdd-init --skip-openspec # 跳过 openspec,直接部署 skills
|
|
386
394
|
kld-sdd-init --tool codex # 仅部署 Codex 配置
|
|
387
395
|
kld-sdd-init --spec-path erp-sdd-specs # 指定 spec 目录(当前目录的子目录)
|
|
396
|
+
kld-sdd repair-git --spec-path=. # 预览旧仓工具跟踪问题
|
|
397
|
+
kld-sdd repair-git --apply --spec-path=. # 一次迁出工具,文件仍留在磁盘
|
|
388
398
|
kld-sdd sync-repos # 新代码仓加入后同步接入
|
|
389
399
|
`);
|
|
390
400
|
}
|
|
@@ -393,6 +403,72 @@ KLD SDD 项目初始化工具
|
|
|
393
403
|
// 子命令路由:解析参数后调用 lib/ 业务实现
|
|
394
404
|
// ═══════════════════════════════════════════════════════════════
|
|
395
405
|
|
|
406
|
+
function resolveRepairSpecRoot(parsed, cwd = process.cwd()) {
|
|
407
|
+
const root = path.resolve(cwd);
|
|
408
|
+
if (parsed.specPath) {
|
|
409
|
+
const explicit = path.resolve(root, parsed.specPath);
|
|
410
|
+
if (!specDetect.isSpecPackageRoot(explicit)) {
|
|
411
|
+
throw new Error(`指定目录不是有效的 Spec 包裹包: ${explicit}`);
|
|
412
|
+
}
|
|
413
|
+
return explicit;
|
|
414
|
+
}
|
|
415
|
+
if (specDetect.isSpecPackageRoot(root)) return root;
|
|
416
|
+
const candidates = specDetect.detectSpecCandidatesWithGit(root);
|
|
417
|
+
if (candidates.length === 1) return candidates[0].abs;
|
|
418
|
+
if (candidates.length === 0) throw new Error('未发现 Spec 包裹包,请用 --spec-path=<dir> 指定');
|
|
419
|
+
throw new Error(`发现 ${candidates.length} 个 Spec 包裹包,请用 --spec-path=<dir> 指定,不自动猜测`);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function runGitRepair(parsed) {
|
|
423
|
+
const init = require('../lib/init');
|
|
424
|
+
const maintenance = require('../lib/maintenance');
|
|
425
|
+
const specRoot = resolveRepairSpecRoot(parsed);
|
|
426
|
+
const plan = maintenance.trackedManagedSpecTools(specRoot);
|
|
427
|
+
if (!plan.ok) throw new Error(plan.error);
|
|
428
|
+
|
|
429
|
+
if (!parsed.applyRepair) {
|
|
430
|
+
const payload = {
|
|
431
|
+
mode: 'preview',
|
|
432
|
+
specRoot,
|
|
433
|
+
trackedToolCount: plan.files.length,
|
|
434
|
+
trackedTools: plan.files.map((file) => file.relative),
|
|
435
|
+
businessFilesAffected: 0,
|
|
436
|
+
};
|
|
437
|
+
if (parsed.json) {
|
|
438
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
console.log(`🧹 Spec Git 清洁度检查: ${path.basename(specRoot)}`);
|
|
442
|
+
console.log(` 被 Git 跟踪的可再生成工具: ${plan.files.length} 个`);
|
|
443
|
+
for (const file of plan.files.slice(0, 8)) console.log(` - ${file.relative}`);
|
|
444
|
+
if (plan.files.length > 8) console.log(` … 其余 ${plan.files.length - 8} 个`);
|
|
445
|
+
console.log(' 业务 Spec、配置、项目身份与 Hook 参数: 不处理');
|
|
446
|
+
if (plan.files.length) console.log(' 执行 --repair-git --apply 可一次迁出工具;不会删除磁盘文件。');
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const existingBefore = plan.files.filter((file) => require('fs').existsSync(path.join(specRoot, file.relative)));
|
|
451
|
+
init.updateGitignore(specRoot, { specPackage: true });
|
|
452
|
+
const result = maintenance.untrackManagedSpecTools(specRoot);
|
|
453
|
+
if (!result.ok) throw new Error(result.error);
|
|
454
|
+
const payload = {
|
|
455
|
+
mode: 'applied',
|
|
456
|
+
specRoot,
|
|
457
|
+
untrackedToolCount: result.files.length,
|
|
458
|
+
filesRemainOnDisk: existingBefore.every((file) => require('fs').existsSync(path.join(specRoot, file.relative))),
|
|
459
|
+
retainedLocalToolCount: existingBefore.length,
|
|
460
|
+
alreadyMissingToolCount: result.files.length - existingBefore.length,
|
|
461
|
+
businessFilesAffected: 0,
|
|
462
|
+
};
|
|
463
|
+
if (parsed.json) {
|
|
464
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
console.log(`✅ 已将 ${result.files.length} 个安装器工具移出 Git 跟踪,现存的 ${existingBefore.length} 个本地文件全部保留`);
|
|
468
|
+
if (payload.alreadyMissingToolCount) console.log(` ℹ️ 其中 ${payload.alreadyMissingToolCount} 个文件在修复前已从磁盘删除`);
|
|
469
|
+
console.log(' 请审阅一次 git status 并提交迁移;以后升级不再污染业务改动列表。');
|
|
470
|
+
}
|
|
471
|
+
|
|
396
472
|
async function runInit() {
|
|
397
473
|
let parsed;
|
|
398
474
|
try {
|
|
@@ -412,6 +488,15 @@ async function runInit() {
|
|
|
412
488
|
return;
|
|
413
489
|
}
|
|
414
490
|
|
|
491
|
+
if (parsed.repairGit) {
|
|
492
|
+
try {
|
|
493
|
+
runGitRepair(parsed);
|
|
494
|
+
} catch (error) {
|
|
495
|
+
fail(`Git 清洁度修复失败: ${error.message}`);
|
|
496
|
+
}
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
|
|
415
500
|
const init = require('../lib/init');
|
|
416
501
|
init.setVerbose(parsed.verbose);
|
|
417
502
|
|
package/lib/init.js
CHANGED
|
@@ -1282,6 +1282,9 @@ async function populateSpecPackage(specRoot, options = {}) {
|
|
|
1282
1282
|
copyTemplatesToProject(root);
|
|
1283
1283
|
initGlobalOverview(root);
|
|
1284
1284
|
deploySddGuideManual(root);
|
|
1285
|
+
// Spec 包可能是独立 Git 仓或单仓内的子目录;忽略规则必须落在它自身,
|
|
1286
|
+
// 不能只写工作区根,否则升级会把整套可再生成运行时显示为业务改动。
|
|
1287
|
+
updateGitignore(root, { specPackage: true });
|
|
1285
1288
|
console.log(`✅ SDD 包裹包已就绪: ${path.basename(root)}`);
|
|
1286
1289
|
return { ok: true, path: root };
|
|
1287
1290
|
}
|
|
@@ -1376,7 +1379,7 @@ function removeOuterSkywalk(anchorDir) {
|
|
|
1376
1379
|
* 创建 / 更新 .gitignore
|
|
1377
1380
|
* @param {string} [cwd=process.cwd()]
|
|
1378
1381
|
*/
|
|
1379
|
-
function updateGitignore(cwd = process.cwd()) {
|
|
1382
|
+
function updateGitignore(cwd = process.cwd(), options = {}) {
|
|
1380
1383
|
const root = path.resolve(cwd);
|
|
1381
1384
|
const gitignorePath = path.join(root, '.gitignore');
|
|
1382
1385
|
const requiredLines = [
|
|
@@ -1395,6 +1398,10 @@ function updateGitignore(cwd = process.cwd()) {
|
|
|
1395
1398
|
'**/skywalk-sdd/state/',
|
|
1396
1399
|
'.worktrees/'
|
|
1397
1400
|
];
|
|
1401
|
+
const specPackageLines = options.specPackage ? maintenance.specPackageIgnoreLines() : [];
|
|
1402
|
+
if (options.specPackage) {
|
|
1403
|
+
requiredLines.push(...specPackageLines);
|
|
1404
|
+
}
|
|
1398
1405
|
|
|
1399
1406
|
const sddConfig = `
|
|
1400
1407
|
# KLD SDD AI 编辑器个人配置(请勿提交)
|
|
@@ -1418,6 +1425,10 @@ skywalk-sdd/state/
|
|
|
1418
1425
|
|
|
1419
1426
|
# SDD Apply 隔离 worktree(本地临时目录)
|
|
1420
1427
|
.worktrees/
|
|
1428
|
+
${options.specPackage ? `
|
|
1429
|
+
# KLD SDD 安装器工具(可由 init/升级重新生成,不属于业务 Spec)
|
|
1430
|
+
${specPackageLines.join('\n')}
|
|
1431
|
+
` : ''}
|
|
1421
1432
|
`;
|
|
1422
1433
|
|
|
1423
1434
|
const result = deployFile(null, gitignorePath, {
|
|
@@ -1868,4 +1879,5 @@ module.exports = {
|
|
|
1868
1879
|
promptSpecPath,
|
|
1869
1880
|
listSpecCandidatesForInit,
|
|
1870
1881
|
deployCodeRepoHooks,
|
|
1882
|
+
updateGitignore,
|
|
1871
1883
|
};
|
package/lib/maintenance.js
CHANGED
|
@@ -3,11 +3,124 @@
|
|
|
3
3
|
// 安装、升级、卸载共用的边界;业务文档和关联配置不属于可清理的工具文件。
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
|
+
const { spawnSync } = require('child_process');
|
|
6
7
|
const sdd = require('../skywalk-sdd/ontology/sdd-config.cjs');
|
|
7
8
|
const layout = require('./workspace-layout');
|
|
8
9
|
const detect = require('../skywalk-sdd/ontology/spec-detect.cjs');
|
|
9
10
|
const pkg = path.resolve(__dirname, '..');
|
|
10
11
|
|
|
12
|
+
function posix(relative) {
|
|
13
|
+
return String(relative || '').replace(/\\/g, '/').replace(/^\.\//, '');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const MANAGED_ROOT_TOOLS = new Set([
|
|
17
|
+
'apply-worktree-finish.cjs',
|
|
18
|
+
'context-client.cjs',
|
|
19
|
+
'kb-sync-identity.cjs',
|
|
20
|
+
'kb-upload.cjs',
|
|
21
|
+
'log.cjs',
|
|
22
|
+
'metrics-v3.cjs',
|
|
23
|
+
'openspec-shim.cjs',
|
|
24
|
+
'runtime-metadata.cjs',
|
|
25
|
+
'spec-root.cjs',
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
const MANAGED_HOOK_TOOLS = new Set([
|
|
29
|
+
'commit-msg-runner.cjs',
|
|
30
|
+
'commit-msg-sdd-trailer.cjs',
|
|
31
|
+
'consistency-check-core.cjs',
|
|
32
|
+
'delivery-check.cjs',
|
|
33
|
+
'delivery-snapshot.cjs',
|
|
34
|
+
'pre-commit-consistency-check.cjs',
|
|
35
|
+
'pre-commit-sdd-check.cjs',
|
|
36
|
+
'pre-push-consistency-check.cjs',
|
|
37
|
+
'pre-push-sdd-check.cjs',
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
function specPackageIgnoreLines() {
|
|
41
|
+
return [
|
|
42
|
+
...[...MANAGED_ROOT_TOOLS].sort().map((name) => `/skywalk-sdd/${name}`),
|
|
43
|
+
'/skywalk-sdd/lib/',
|
|
44
|
+
'/skywalk-sdd/ontology/',
|
|
45
|
+
'/skywalk-sdd/reporting/',
|
|
46
|
+
'/skywalk-sdd/ci/github-actions-sdd.yml',
|
|
47
|
+
'/skywalk-sdd/ci/gitlab-ci-sdd.yml',
|
|
48
|
+
...[...MANAGED_HOOK_TOOLS].sort().map((name) => `/skywalk-sdd/git-hooks/${name}`),
|
|
49
|
+
'/openspec-templates/',
|
|
50
|
+
'/openspec/kld-sdd操作手册.html',
|
|
51
|
+
'/_tmp_*',
|
|
52
|
+
'/*-start.log',
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 只识别能够由 kld-sdd 安装器重新生成的文件。
|
|
58
|
+
* 业务 Spec、项目身份、Hook 参数、KB 配置和历史数据都不属于工具文件。
|
|
59
|
+
*/
|
|
60
|
+
function isManagedSpecToolPath(relative) {
|
|
61
|
+
const rel = posix(relative);
|
|
62
|
+
if (rel === 'openspec/kld-sdd操作手册.html' || rel.startsWith('openspec-templates/')) return true;
|
|
63
|
+
if (rel.startsWith('skywalk-sdd/') && MANAGED_ROOT_TOOLS.has(rel.slice('skywalk-sdd/'.length))) return true;
|
|
64
|
+
if (/^skywalk-sdd\/(?:lib|ontology|reporting)\//.test(rel)) return true;
|
|
65
|
+
if (/^skywalk-sdd\/ci\/(?:github-actions-sdd|gitlab-ci-sdd)\.yml$/.test(rel)) return true;
|
|
66
|
+
const hookPrefix = 'skywalk-sdd/git-hooks/';
|
|
67
|
+
return rel.startsWith(hookPrefix) && MANAGED_HOOK_TOOLS.has(rel.slice(hookPrefix.length));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function git(cwd, args) {
|
|
71
|
+
const result = spawnSync('git', args, {
|
|
72
|
+
cwd,
|
|
73
|
+
encoding: 'utf8',
|
|
74
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
75
|
+
});
|
|
76
|
+
if (result.status !== 0) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
error: String(result.stderr || result.stdout || 'git 命令失败').trim(),
|
|
80
|
+
output: '',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return { ok: true, output: String(result.stdout || '') };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** 列出当前 Spec 包中仍被 Git 跟踪的安装器工具文件。 */
|
|
87
|
+
function trackedManagedSpecTools(specRoot) {
|
|
88
|
+
const requestedRoot = path.resolve(specRoot);
|
|
89
|
+
const root = fs.existsSync(requestedRoot) ? fs.realpathSync(requestedRoot) : requestedRoot;
|
|
90
|
+
const top = git(root, ['rev-parse', '--show-toplevel']);
|
|
91
|
+
if (!top.ok) return { ok: false, specRoot: root, files: [], error: '当前 Spec 目录不在 Git 仓库中' };
|
|
92
|
+
const gitRoot = path.resolve(top.output.trim());
|
|
93
|
+
const rootRelative = posix(path.relative(gitRoot, root));
|
|
94
|
+
if (rootRelative.startsWith('../') || path.isAbsolute(rootRelative)) {
|
|
95
|
+
return { ok: false, specRoot: root, gitRoot, files: [], error: 'Spec 目录不属于检测到的 Git 仓库' };
|
|
96
|
+
}
|
|
97
|
+
const pathspec = rootRelative ? `${rootRelative}/` : '.';
|
|
98
|
+
const listed = git(gitRoot, ['ls-files', '-z', '--', pathspec]);
|
|
99
|
+
if (!listed.ok) return { ok: false, specRoot: root, gitRoot, files: [], error: listed.error };
|
|
100
|
+
const prefix = rootRelative ? `${rootRelative}/` : '';
|
|
101
|
+
const files = listed.output.split('\0').filter(Boolean).map(posix).flatMap((gitPath) => {
|
|
102
|
+
if (prefix && !gitPath.startsWith(prefix)) return [];
|
|
103
|
+
const relative = prefix ? gitPath.slice(prefix.length) : gitPath;
|
|
104
|
+
return isManagedSpecToolPath(relative) ? [{ gitPath, relative }] : [];
|
|
105
|
+
});
|
|
106
|
+
return { ok: true, specRoot: root, gitRoot, files };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 将安装器工具从 Git 索引移除,文件仍留在磁盘供本地运行。
|
|
111
|
+
* 调用方必须先把对应规则写入 Spec 根 .gitignore。
|
|
112
|
+
*/
|
|
113
|
+
function untrackManagedSpecTools(specRoot) {
|
|
114
|
+
const plan = trackedManagedSpecTools(specRoot);
|
|
115
|
+
if (!plan.ok || plan.files.length === 0) return plan;
|
|
116
|
+
for (let offset = 0; offset < plan.files.length; offset += 100) {
|
|
117
|
+
const batch = plan.files.slice(offset, offset + 100).map((file) => file.gitPath);
|
|
118
|
+
const removed = git(plan.gitRoot, ['update-index', '--force-remove', '--', ...batch]);
|
|
119
|
+
if (!removed.ok) return { ...plan, ok: false, error: removed.error };
|
|
120
|
+
}
|
|
121
|
+
return { ...plan, untracked: plan.files.length };
|
|
122
|
+
}
|
|
123
|
+
|
|
11
124
|
function filesUnder(root, prefix = '') {
|
|
12
125
|
if (!fs.existsSync(root) || !fs.lstatSync(root).isDirectory()) return [];
|
|
13
126
|
return fs.readdirSync(root).flatMap(name => {
|
|
@@ -93,4 +206,16 @@ function maintenanceConflicts(root, spec, repos) {
|
|
|
93
206
|
return failures;
|
|
94
207
|
}
|
|
95
208
|
|
|
96
|
-
module.exports = {
|
|
209
|
+
module.exports = {
|
|
210
|
+
filesUnder,
|
|
211
|
+
regularFileWithin,
|
|
212
|
+
runtimeToolFiles,
|
|
213
|
+
specPackageIgnoreLines,
|
|
214
|
+
isManagedSpecToolPath,
|
|
215
|
+
trackedManagedSpecTools,
|
|
216
|
+
untrackManagedSpecTools,
|
|
217
|
+
samePath,
|
|
218
|
+
associationConflict,
|
|
219
|
+
workspaceCodeRepos,
|
|
220
|
+
maintenanceConflicts,
|
|
221
|
+
};
|
package/lib/skills-bundle.js
CHANGED
|
@@ -40,6 +40,7 @@ const OPSX_SKILL_DIRS = [
|
|
|
40
40
|
// Engineering KB 依赖技能(随 init 部署;propose/spec/archive 硬依赖)
|
|
41
41
|
'opsx-kb-config',
|
|
42
42
|
'opsx-ontology-query',
|
|
43
|
+
'opsx-ontology-ingest',
|
|
43
44
|
'opsx-kb-ingest',
|
|
44
45
|
// Spec 一致性校验技能
|
|
45
46
|
'opsx-consistency-check',
|
|
@@ -122,6 +123,7 @@ const KUNLUN_SLASH_COMMANDS = [
|
|
|
122
123
|
'archive',
|
|
123
124
|
'explore',
|
|
124
125
|
'ontology-query',
|
|
126
|
+
'ontology-ingest',
|
|
125
127
|
'kb-ingest',
|
|
126
128
|
'kb-config',
|
|
127
129
|
'consistency-check',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kld-sdd",
|
|
3
|
-
"version": "2.7.8-
|
|
3
|
+
"version": "2.7.8-7",
|
|
4
4
|
"description": "KLD SDD OpenSpec 项目初始化工具 - 一键部署 SDD skills",
|
|
5
5
|
"main": "lib/init.js",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"bench:check": "node test/benchmark-check.cjs",
|
|
12
|
-
"test": "node --test test/delivery-hooks.test.cjs test/execution-friction.test.cjs test/kb-fact-lifecycle.test.cjs test/workflow-usability.test.cjs test/check-efficiency.test.cjs && node test/external-key.cjs && node test/change-key.cjs && node test/modules-and-sdd-config.cjs && node test/active-changes.cjs && node test/hook-layouts.cjs && node test/spec-package-init.cjs && node test/prompt-spec-path.cjs && node test/spec-detect.cjs && node test/workspace-layout.cjs && node test/sync-repos-spec-choice.cjs && node test/ontology-release-blockers.cjs && node test/ontology-semantic-core.cjs && node test/ontology-identity-versioning.cjs && node test/ontology-identity-continuity.cjs && node test/ontology-state-transaction.cjs && node test/ontology-process-concurrency.cjs && node test/ontology-observer-convergence.cjs && node test/ontology-working-runtime.cjs && node test/ontology-stage-materialization.cjs && node test/ontology-template-contract.cjs && node test/ontology-cli-archive.cjs && node test/archive-package-producer.cjs && node --test test/evidence-integrity-oracle.cjs test/evidence-integrity-wiring.cjs test/change-report-correctness.cjs test/report-metrics-correctness.cjs test/change-report-model-ui.cjs && node test/validate-skills-bundle.cjs && node test/tool-profiles.cjs && node test/deploy-strategy.cjs && node test/uninstall.cjs && node --test test/maintenance.test.cjs && node test/settings-merge.cjs && node test/command-bridge.cjs && node test/codebuddy-hooks.cjs && node test/skill-content-contract.cjs && node test/init-agent-profiles.cjs && node test/init-report-runtime.cjs && node test/init-output-verbosity.cjs && node --test test/usage-contract.test.cjs test/user-config.test.cjs test/usage-runtime-removal.test.cjs test/runtime/usage-reporter.test.cjs test/runtime/usage-reporting.test.cjs test/runtime/git-identity.test.cjs test/runtime/kb-state-location.test.cjs && node test/runtime/metrics-v3.test.cjs && node test/runtime/fixback.test.cjs && node test/progress-package-artifact.test.cjs && node --test test/progress-package-install.e2e.cjs && node test/consistency-check-core.cjs"
|
|
12
|
+
"test": "node --test test/delivery-hooks.test.cjs test/execution-friction.test.cjs test/kb-fact-lifecycle.test.cjs test/workflow-usability.test.cjs test/check-efficiency.test.cjs && node test/external-key.cjs && node test/change-key.cjs && node test/modules-and-sdd-config.cjs && node test/active-changes.cjs && node test/hook-layouts.cjs && node test/spec-package-init.cjs && node test/prompt-spec-path.cjs && node test/spec-detect.cjs && node test/workspace-layout.cjs && node test/sync-repos-spec-choice.cjs && node test/ontology-release-blockers.cjs && node test/ontology-semantic-core.cjs && node test/ontology-identity-versioning.cjs && node test/ontology-identity-continuity.cjs && node test/ontology-state-transaction.cjs && node test/ontology-process-concurrency.cjs && node test/ontology-observer-convergence.cjs && node test/ontology-working-runtime.cjs && node test/ontology-stage-materialization.cjs && node test/ontology-template-contract.cjs && node test/ontology-cli-archive.cjs && node test/spec-ontology-compatibility.cjs && node test/archive-package-producer.cjs && node --test test/evidence-integrity-oracle.cjs test/evidence-integrity-wiring.cjs test/change-report-correctness.cjs test/report-metrics-correctness.cjs test/change-report-model-ui.cjs && node test/validate-skills-bundle.cjs && node test/tool-profiles.cjs && node test/deploy-strategy.cjs && node test/uninstall.cjs && node --test test/maintenance.test.cjs && node test/settings-merge.cjs && node test/command-bridge.cjs && node test/codebuddy-hooks.cjs && node test/skill-content-contract.cjs && node test/init-agent-profiles.cjs && node test/init-report-runtime.cjs && node test/init-output-verbosity.cjs && node --test test/usage-contract.test.cjs test/user-config.test.cjs test/usage-runtime-removal.test.cjs test/runtime/usage-reporter.test.cjs test/runtime/usage-reporting.test.cjs test/runtime/git-identity.test.cjs test/runtime/kb-state-location.test.cjs && node test/runtime/metrics-v3.test.cjs && node test/runtime/fixback.test.cjs && node test/progress-package-artifact.test.cjs && node --test test/progress-package-install.e2e.cjs && node test/consistency-check-core.cjs"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
15
15
|
"kld",
|
|
@@ -37,6 +37,9 @@ function buildEndpoint(apiBase, spaceId, kbId, mode) {
|
|
|
37
37
|
if (mode === 'resolve') {
|
|
38
38
|
return `${base}/v1/spaces/${space}/knowledge-bases/${kb}/entities/resolve`;
|
|
39
39
|
}
|
|
40
|
+
if (mode === 'spec-generation') {
|
|
41
|
+
return `${base}/v1/spaces/${space}/knowledge-bases/${kb}/context/spec-generation`;
|
|
42
|
+
}
|
|
40
43
|
return `${base}/v1/spaces/${space}/knowledge-bases/${kb}/context/match-requirement`;
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -61,7 +64,14 @@ function compactContext(data, includeCandidates, mode = 'match') {
|
|
|
61
64
|
warnings: data.warnings,
|
|
62
65
|
clarificationQuestions: data.clarificationQuestions,
|
|
63
66
|
specGenerationContext: data.specGenerationContext,
|
|
67
|
+
matchedCapabilities: data.matchedCapabilities,
|
|
68
|
+
matchedScenarios: data.matchedScenarios,
|
|
69
|
+
businessObjects: data.businessObjects,
|
|
70
|
+
rules: data.rules,
|
|
71
|
+
specPatterns: data.specPatterns,
|
|
72
|
+
compatibilityMode: data.compatibilityMode,
|
|
64
73
|
supportEvidence: data.supportEvidence,
|
|
74
|
+
candidateEvidence: data.candidateEvidence,
|
|
65
75
|
oppositionEvidence: data.oppositionEvidence,
|
|
66
76
|
};
|
|
67
77
|
// Continuity resolve 必须透出 candidates;match 默认隐藏内部候选除非 --include-candidates
|
|
@@ -171,19 +181,40 @@ async function retrieveContext(args = parseArgs(process.argv), env = process.env
|
|
|
171
181
|
return { ...unavailableContext('engineering_kb_not_configured', 'KB 尚未配置,本地工作可以继续'), configured: false };
|
|
172
182
|
}
|
|
173
183
|
|
|
174
|
-
const
|
|
184
|
+
const requestedMode = String(args.mode || 'match').trim().toLowerCase();
|
|
185
|
+
const mode = requestedMode === 'resolve'
|
|
186
|
+
? 'resolve'
|
|
187
|
+
: (['spec-generation', 'spec_generation', 'generation'].includes(requestedMode)
|
|
188
|
+
? 'spec-generation' : 'match');
|
|
175
189
|
const timeoutMs = contextTimeout(args, env, 5000);
|
|
176
190
|
const payload = buildPayload(args, mode);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
191
|
+
let responseMode = mode;
|
|
192
|
+
let data;
|
|
193
|
+
try {
|
|
194
|
+
data = await requestJson(
|
|
195
|
+
buildEndpoint(apiBase, spaceId, kbId, mode),
|
|
196
|
+
payload,
|
|
197
|
+
token,
|
|
198
|
+
timeoutMs,
|
|
199
|
+
);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
const endpointUnavailable = /Not Found|HTTP 404/i.test(error.message);
|
|
202
|
+
if (mode !== 'spec-generation' || !endpointUnavailable) throw error;
|
|
203
|
+
data = await requestJson(
|
|
204
|
+
buildEndpoint(apiBase, spaceId, kbId, 'match'),
|
|
205
|
+
payload,
|
|
206
|
+
token,
|
|
207
|
+
timeoutMs,
|
|
208
|
+
);
|
|
209
|
+
responseMode = 'match';
|
|
210
|
+
}
|
|
183
211
|
return {
|
|
184
212
|
available: true,
|
|
185
213
|
mode,
|
|
214
|
+
responseMode,
|
|
215
|
+
remoteContextVerified: true,
|
|
186
216
|
...compactContext(data, Boolean(args['include-candidates']), mode),
|
|
217
|
+
compatibilityMode: responseMode === mode ? (data.compatibilityMode || 'NATIVE') : 'LEGACY_V2',
|
|
187
218
|
};
|
|
188
219
|
}
|
|
189
220
|
|
package/skywalk-sdd/index.cjs
CHANGED
|
@@ -7706,7 +7706,11 @@ function cmdCheckRecord(args) {
|
|
|
7706
7706
|
const preflight = JSON.parse(fs.readFileSync(path.resolve(args['preflight-file']), 'utf8'));
|
|
7707
7707
|
const review = JSON.parse(fs.readFileSync(path.resolve(args['review-file']), 'utf8'));
|
|
7708
7708
|
const state = require('./ontology/runtime.cjs').reconcileChange(projectRoot, args.change, { profile: preflight.profile || 'auto', markPending: true });
|
|
7709
|
-
|
|
7709
|
+
const { splitCheckDiagnostics } = require('./ontology/spec-ontology.cjs');
|
|
7710
|
+
const preflightBlocked = preflight.product_valid === false
|
|
7711
|
+
|| (preflight.product_valid == null && !splitCheckDiagnostics(preflight.diagnostics).product_valid);
|
|
7712
|
+
const stateBlocked = !splitCheckDiagnostics(state.diagnostics).product_valid;
|
|
7713
|
+
if (preflightBlocked || stateBlocked || preflight.revision !== state.revision
|
|
7710
7714
|
|| preflight.review_inputs?.identity_history_hash !== state.state.identity_history_hash
|
|
7711
7715
|
|| JSON.stringify(preflight.review_inputs?.files) !== JSON.stringify(state.state.files)) {
|
|
7712
7716
|
throw new Error('CHECK_REVIEW_STALE: 文档或历史身份已变化,重新预检并评审受影响内容');
|
|
@@ -8239,16 +8243,20 @@ function cmdSemanticIdentity(args) {
|
|
|
8239
8243
|
}
|
|
8240
8244
|
|
|
8241
8245
|
function semanticResultPayload(result) {
|
|
8246
|
+
const split = require('./ontology/spec-ontology.cjs').splitCheckDiagnostics(result.diagnostics);
|
|
8242
8247
|
return {
|
|
8243
8248
|
change: result.state.change,
|
|
8244
8249
|
profile: result.profile,
|
|
8245
8250
|
valid: result.valid,
|
|
8251
|
+
product_valid: split.product_valid,
|
|
8246
8252
|
review_status: result.state.review_status,
|
|
8247
8253
|
revision: result.revision,
|
|
8248
8254
|
changed: Boolean(result.changed),
|
|
8249
8255
|
counts: result.counts,
|
|
8250
8256
|
paths: result.paths,
|
|
8251
8257
|
diagnostics: result.diagnostics,
|
|
8258
|
+
tool_diagnostics: split.tool_diagnostics,
|
|
8259
|
+
product_diagnostics: split.product_diagnostics,
|
|
8252
8260
|
};
|
|
8253
8261
|
}
|
|
8254
8262
|
|
|
@@ -8290,13 +8298,32 @@ function cmdSemanticReconcile(args, options = {}) {
|
|
|
8290
8298
|
total: Number(finished - started) / 1e6,
|
|
8291
8299
|
};
|
|
8292
8300
|
}
|
|
8301
|
+
if (options.productGate && payload.tool_diagnostics.length > 0) {
|
|
8302
|
+
try {
|
|
8303
|
+
const repair = require('./ontology/spec-ontology.cjs').materializeChangeSpecOntology(
|
|
8304
|
+
context.projectRoot,
|
|
8305
|
+
context.changeName,
|
|
8306
|
+
);
|
|
8307
|
+
payload.tool_repair = {
|
|
8308
|
+
repaired: repair.validation.valid,
|
|
8309
|
+
output_path: repair.output_path,
|
|
8310
|
+
mapping_path: repair.mapping_path,
|
|
8311
|
+
};
|
|
8312
|
+
} catch (error) {
|
|
8313
|
+
payload.tool_repair = { repaired: false };
|
|
8314
|
+
}
|
|
8315
|
+
}
|
|
8293
8316
|
console.log(JSON.stringify(payload, null, 2));
|
|
8294
|
-
if (
|
|
8317
|
+
if (options.productGate) {
|
|
8318
|
+
if (!payload.product_valid) process.exitCode = 1;
|
|
8319
|
+
} else if (!result.valid) {
|
|
8320
|
+
process.exitCode = 1;
|
|
8321
|
+
}
|
|
8295
8322
|
return result;
|
|
8296
8323
|
}
|
|
8297
8324
|
|
|
8298
8325
|
function cmdSemanticCheck(args) {
|
|
8299
|
-
return cmdSemanticReconcile(args, { markPending: true, includeTasks: Boolean(args['include-tasks']) });
|
|
8326
|
+
return cmdSemanticReconcile(args, { markPending: true, includeTasks: Boolean(args['include-tasks']), productGate: true });
|
|
8300
8327
|
}
|
|
8301
8328
|
|
|
8302
8329
|
function cmdSemanticStatus(args) {
|