kld-sdd 2.6.11 → 2.6.13
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/README.md +20 -0
- package/kld-sdd-guide.html +429 -159
- package/lib/hook-gate-core.js +41 -5
- package/lib/init.js +101 -95
- package/package.json +5 -2
- package/skywalk-sdd/index.cjs +2668 -415
- package/skywalk-sdd/metrics-v3.cjs +1153 -0
- package/skywalk-sdd/ontology/archive-package.cjs +114 -3
- package/skywalk-sdd/ontology/resolve-spec-root.cjs +20 -80
- package/skywalk-sdd/ontology/working-artifacts.cjs +2 -1
- package/templates/hooks/claude/hooks/sdd-apply-test-gate.cjs +39 -9
- package/templates/hooks/claude/hooks/sdd-post-tool.cjs +87 -8
- package/templates/hooks/claude/hooks/sdd-prompt.cjs +25 -5
- package/templates/hooks/codebuddy/hooks/sdd-apply-test-gate.cjs +39 -9
- package/templates/hooks/codebuddy/hooks/sdd-post-tool.cjs +87 -9
- package/templates/hooks/codebuddy/hooks/sdd-prompt.cjs +24 -3
- package/templates/skills/kld-sdd/opsx-apply/SKILL.md +17 -16
- package/templates/skills/kld-sdd/opsx-apply/checklist.md +22 -22
- package/templates/skills/kld-sdd/opsx-apply/implementer-prompt.md +12 -12
- package/templates/skills/kld-sdd/opsx-apply/reference.md +43 -42
- package/templates/skills/kld-sdd/opsx-apply/worktree-setup.md +3 -3
- package/templates/skills/kld-sdd/opsx-archive/SKILL.md +58 -20
- package/templates/skills/kld-sdd/opsx-archive/checklist.md +6 -3
- package/templates/skills/kld-sdd/opsx-check/SKILL.md +30 -22
- package/templates/skills/kld-sdd/opsx-check/checklist.md +7 -6
- package/templates/skills/kld-sdd/opsx-design/SKILL.md +5 -5
- package/templates/skills/kld-sdd/opsx-design/checklist.md +1 -1
- package/templates/skills/kld-sdd/opsx-design/reference.md +2 -2
- package/templates/skills/kld-sdd/opsx-explore/SKILL.md +5 -5
- package/templates/skills/kld-sdd/opsx-propose/SKILL.md +20 -12
- package/templates/skills/kld-sdd/opsx-propose/reference.md +31 -5
- package/templates/skills/kld-sdd/opsx-rules/SKILL.md +3 -3
- package/templates/skills/kld-sdd/opsx-rules/reference.md +3 -1
- package/templates/skills/kld-sdd/opsx-spec/SKILL.md +6 -6
- package/templates/skills/kld-sdd/opsx-spec/checklist.md +1 -1
- package/templates/skills/kld-sdd/opsx-spec/reference.md +2 -2
- package/templates/skills/kld-sdd/opsx-task/SKILL.md +14 -14
- package/templates/skills/kld-sdd/opsx-task/checklist.md +3 -3
- package/templates/skills/kld-sdd/opsx-task/reference.md +5 -5
- package/templates/skills/kld-sdd/opsx-test/SKILL.md +11 -9
- package/templates/skills/kld-sdd/{opsx-tdd-anti-patterns → tdd-anti-patterns}/SKILL.md +4 -4
- package/templates/skills/kld-sdd/{opsx-tdd-anti-patterns → tdd-anti-patterns}/reference.md +4 -4
- package/templates/skills/kld-sdd/{opsx-tdd-core → tdd-core}/SKILL.md +13 -13
- package/templates/skills/kld-sdd/{opsx-tdd-core → tdd-core}/checklist.md +5 -5
- package/templates/skills/kld-sdd/{opsx-tdd-core → tdd-core}/reference.md +12 -12
- package/templates/skills/kld-sdd/{opsx-tdd-metrics → tdd-metrics}/SKILL.md +3 -3
- package/templates/skills/kld-sdd/{opsx-tdd-metrics → tdd-metrics}/checklist.md +2 -2
- package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/SKILL.md +2 -2
- package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/parameterized-testing.md +1 -1
- package/templates/skills/kld-sdd/{opsx-tdd-review → tdd-review}/SKILL.md +5 -5
- package/templates/skills/kld-sdd/{opsx-tdd-review → tdd-review}/checklist.md +5 -5
- package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/SKILL.md +3 -3
- package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/non-tdd-modules.md +1 -1
- package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/refactor-checklist.md +1 -1
- package/templates/skills/kld-sdd/tdd-rules/rules/test-skeleton-telemetry.md +19 -0
- package/templates/skills/kld-sdd/opsx-tdd-rules/rules/test-skeleton-telemetry.md +0 -19
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/cause-effect-clarity.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/clean-test-data.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/existing-test-awareness.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/given-when-then.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/good-test-qualities.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/mock-boundary.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/naming-conventions.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/no-logic-in-tests.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/one-test-one-scenario.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/prefer-public-apis.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/general/test-behaviors-not-methods.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/java/argument-matching.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/java/controller-test-rules.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/java/domain-service-rules.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/java/java-test-template.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/java/json-serialization.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/java/logging-rules.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/post-generation/compilation-verification.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/post-generation/execution-verification.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/python/py-test-template.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-quality → tdd-quality}/rules/typescript/ts-test-template.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/controller-strategy.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/dag-generation-rules.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/des-step-annotation.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/exception-path-coverage.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/green-scope-declaration.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/green-yagni-fence.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/multi-validation-split.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/task-type-definitions.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/tdd-strategy-selection.md +0 -0
- /package/templates/skills/kld-sdd/{opsx-tdd-rules → tdd-rules}/rules/test-execution-gate.md +0 -0
package/lib/hook-gate-core.js
CHANGED
|
@@ -50,16 +50,45 @@ function normalizeHookInput(input) {
|
|
|
50
50
|
return normalized;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
function resolveSkywalkDir(dir) {
|
|
54
|
+
const root = path.resolve(dir || '.');
|
|
55
|
+
const direct = path.join(root, 'skywalk-sdd');
|
|
56
|
+
if (
|
|
57
|
+
fs.existsSync(path.join(direct, 'log.cjs'))
|
|
58
|
+
|| fs.existsSync(path.join(direct, 'log.js'))
|
|
59
|
+
) {
|
|
60
|
+
return direct;
|
|
61
|
+
}
|
|
62
|
+
const hintFile = path.join(root, '.sdd-spec-root');
|
|
63
|
+
if (fs.existsSync(hintFile)) {
|
|
64
|
+
const rel = String(fs.readFileSync(hintFile, 'utf8') || '')
|
|
65
|
+
.trim()
|
|
66
|
+
.split(/\r?\n/)[0]
|
|
67
|
+
.trim();
|
|
68
|
+
if (rel) {
|
|
69
|
+
const nested = path.join(root, rel, 'skywalk-sdd');
|
|
70
|
+
if (
|
|
71
|
+
fs.existsSync(path.join(nested, 'log.cjs'))
|
|
72
|
+
|| fs.existsSync(path.join(nested, 'log.js'))
|
|
73
|
+
) {
|
|
74
|
+
return nested;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
53
81
|
function hasTelemetryCli(dir) {
|
|
54
|
-
return
|
|
55
|
-
fs.existsSync(path.join(dir, 'skywalk-sdd', 'log.js'));
|
|
82
|
+
return Boolean(resolveSkywalkDir(dir));
|
|
56
83
|
}
|
|
57
84
|
|
|
58
85
|
function findProjectRoot(startDir) {
|
|
59
86
|
if (!startDir) return '';
|
|
60
87
|
let current = path.resolve(startDir);
|
|
61
88
|
for (let i = 0; i < 25; i++) {
|
|
62
|
-
if (hasTelemetryCli(current)
|
|
89
|
+
if (hasTelemetryCli(current) || fs.existsSync(path.join(current, '.sdd-spec-root'))) {
|
|
90
|
+
return current;
|
|
91
|
+
}
|
|
63
92
|
const parent = path.dirname(current);
|
|
64
93
|
if (parent === current) return '';
|
|
65
94
|
current = parent;
|
|
@@ -96,7 +125,10 @@ function safeChangeName(name) {
|
|
|
96
125
|
}
|
|
97
126
|
|
|
98
127
|
function findActiveApplyStage(projectRoot) {
|
|
99
|
-
const
|
|
128
|
+
const skywalk = resolveSkywalkDir(projectRoot);
|
|
129
|
+
const stateDir = skywalk
|
|
130
|
+
? path.join(skywalk, 'state')
|
|
131
|
+
: path.join(projectRoot, 'skywalk-sdd', 'state');
|
|
100
132
|
if (!fs.existsSync(stateDir)) return null;
|
|
101
133
|
|
|
102
134
|
let latest = null;
|
|
@@ -118,7 +150,10 @@ function findActiveApplyStage(projectRoot) {
|
|
|
118
150
|
|
|
119
151
|
function hasCompletedCheck(projectRoot, changeName) {
|
|
120
152
|
const safeName = safeChangeName(changeName);
|
|
121
|
-
const
|
|
153
|
+
const skywalk = resolveSkywalkDir(projectRoot);
|
|
154
|
+
const eventsChangeDir = skywalk
|
|
155
|
+
? path.join(skywalk, 'events', safeName)
|
|
156
|
+
: path.join(projectRoot, 'skywalk-sdd', 'events', safeName);
|
|
122
157
|
if (!fs.existsSync(eventsChangeDir)) return false;
|
|
123
158
|
|
|
124
159
|
const jsonlFiles = fs.readdirSync(eventsChangeDir)
|
|
@@ -316,6 +351,7 @@ module.exports = {
|
|
|
316
351
|
readStdin,
|
|
317
352
|
parseHookInput,
|
|
318
353
|
normalizeHookInput,
|
|
354
|
+
resolveSkywalkDir,
|
|
319
355
|
hasTelemetryCli,
|
|
320
356
|
findProjectRoot,
|
|
321
357
|
getProjectRoot,
|
package/lib/init.js
CHANGED
|
@@ -822,6 +822,35 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
822
822
|
console.log(` ⚠️ Telemetry CLI 源文件缺失: ${telemetrySrc}`);
|
|
823
823
|
}
|
|
824
824
|
|
|
825
|
+
const metricsV3Src = path.join(pkgPath, 'skywalk-sdd', 'metrics-v3.cjs');
|
|
826
|
+
const metricsV3Dst = path.join(dataDir, 'metrics-v3.cjs');
|
|
827
|
+
if (fs.existsSync(metricsV3Src)) {
|
|
828
|
+
fs.copyFileSync(metricsV3Src, metricsV3Dst);
|
|
829
|
+
console.log(' ✓ 部署 skywalk-sdd/metrics-v3.cjs(V3 指标运行时)');
|
|
830
|
+
} else {
|
|
831
|
+
console.log(` ⚠️ V3 指标模块源文件缺失: ${metricsV3Src}(report/metrics 可能无法加载 metrics-v3)`);
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const runtimeMetadataSrc = path.join(pkgPath, 'skywalk-sdd', 'runtime-metadata.cjs');
|
|
835
|
+
const runtimeMetadataDst = path.join(dataDir, 'runtime-metadata.cjs');
|
|
836
|
+
if (fs.existsSync(runtimeMetadataSrc)) {
|
|
837
|
+
fs.copyFileSync(runtimeMetadataSrc, runtimeMetadataDst);
|
|
838
|
+
const packageVersion = require(path.join(pkgPath, 'package.json')).version;
|
|
839
|
+
fs.writeFileSync(path.join(dataDir, 'runtime-metadata.json'), `${JSON.stringify({
|
|
840
|
+
schema_version: 'kld-sdd-runtime-metadata/v1',
|
|
841
|
+
package_name: '@hunterzheng/kld-sdd',
|
|
842
|
+
version: packageVersion,
|
|
843
|
+
}, null, 2)}\n`, 'utf8');
|
|
844
|
+
console.log(` ✓ 部署 kld-sdd 运行时身份(${packageVersion})`);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
const reportingSrc = path.join(pkgPath, 'skywalk-sdd', 'reporting');
|
|
848
|
+
const reportingDst = path.join(dataDir, 'reporting');
|
|
849
|
+
if (fs.existsSync(reportingSrc)) {
|
|
850
|
+
copyDir(reportingSrc, reportingDst);
|
|
851
|
+
console.log(' ✓ 部署 skywalk-sdd/reporting/(V3 单次变更报告)');
|
|
852
|
+
}
|
|
853
|
+
|
|
825
854
|
const contextClientSrc = path.join(pkgPath, 'skywalk-sdd', 'context-client.cjs');
|
|
826
855
|
const contextClientDst = path.join(dataDir, 'context-client.cjs');
|
|
827
856
|
if (fs.existsSync(contextClientSrc)) {
|
|
@@ -873,16 +902,20 @@ function installGitHookShim(cwd, hookName, scriptPath, options = {}) {
|
|
|
873
902
|
// Git 把 commit-msg 文件路径放在 $1;--project 等额外参数必须跟在 "$@" 后面,
|
|
874
903
|
// 否则 trailer 脚本会把 --project=… 误当成 message 文件(argv[2])。
|
|
875
904
|
const extraArgs = options.extraArgs || '';
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
905
|
+
// Windows 反斜杠路径在 #!/bin/sh(Git for Windows MSYS2)中不被 [ -f ] 和 node 识别,
|
|
906
|
+
// 统一转为正斜杠,确保 hook shim 跨平台可执行。
|
|
907
|
+
const shScriptPath = scriptPath.replace(/\\/g, '/');
|
|
908
|
+
const shExtraArgs = extraArgs.replace(/\\/g, '/');
|
|
909
|
+
const nodeLine = shExtraArgs
|
|
910
|
+
? ` node "${shScriptPath}" "$@" ${shExtraArgs}`
|
|
911
|
+
: ` node "${shScriptPath}" "$@"`;
|
|
879
912
|
const shim = [
|
|
880
913
|
'#!/bin/sh',
|
|
881
914
|
`# ${marker}`,
|
|
882
|
-
`if [ -f "${
|
|
915
|
+
`if [ -f "${shScriptPath}" ]; then`,
|
|
883
916
|
nodeLine,
|
|
884
917
|
'else',
|
|
885
|
-
` echo "[kld-sdd] Hook 脚本不存在: ${
|
|
918
|
+
` echo "[kld-sdd] Hook 脚本不存在: ${shScriptPath}" >&2`,
|
|
886
919
|
' exit 1',
|
|
887
920
|
'fi',
|
|
888
921
|
'',
|
|
@@ -892,7 +925,7 @@ function installGitHookShim(cwd, hookName, scriptPath, options = {}) {
|
|
|
892
925
|
const existing = fs.readFileSync(hookPath, 'utf8');
|
|
893
926
|
if (existing.includes(marker)) {
|
|
894
927
|
// 已是 SDD shim:若指向路径变化(如改为引用 spec 仓),允许覆盖升级
|
|
895
|
-
if (existing.includes(
|
|
928
|
+
if (existing.includes(shScriptPath) && (!shExtraArgs || existing.includes(shExtraArgs.trim()))) {
|
|
896
929
|
console.log(` ✓ .git/hooks/${hookName} 已包含 SDD 质量门禁`);
|
|
897
930
|
return;
|
|
898
931
|
}
|
|
@@ -951,7 +984,7 @@ function installCodeRepoCommitMsgHook(codeRepoRoot, specRepoRoot, options = {})
|
|
|
951
984
|
return false;
|
|
952
985
|
}
|
|
953
986
|
installGitHookShim(cwd, 'commit-msg', ensured.scriptPath, {
|
|
954
|
-
extraArgs:
|
|
987
|
+
extraArgs: `"--project=${cwd}"`,
|
|
955
988
|
});
|
|
956
989
|
return true;
|
|
957
990
|
}
|
|
@@ -1208,94 +1241,62 @@ function writeSddSpecRootHint(anchorDir, specPackageAbs) {
|
|
|
1208
1241
|
}
|
|
1209
1242
|
|
|
1210
1243
|
/**
|
|
1211
|
-
*
|
|
1212
|
-
*
|
|
1213
|
-
*
|
|
1244
|
+
* 移除工作区 / Git 根上多余的 skywalk-sdd(符号链接或旧完整副本)。
|
|
1245
|
+
* 唯一实体只保留在 *-sdd-specs/skywalk-sdd/。
|
|
1246
|
+
*
|
|
1247
|
+
* 触发条件(满足其一即可):
|
|
1248
|
+
* - 存在 .sdd-spec-root
|
|
1249
|
+
* - 同级已有 *-sdd-specs/skywalk-sdd(多仓/单仓包裹包)
|
|
1214
1250
|
*/
|
|
1215
|
-
function
|
|
1216
|
-
const anchor = path.resolve(anchorDir);
|
|
1217
|
-
const specAbs = path.resolve(specPackageAbs);
|
|
1218
|
-
const relSpec = path.relative(anchor, specAbs).replace(/\\/g, '/');
|
|
1219
|
-
const skywalkDir = path.join(anchor, 'skywalk-sdd');
|
|
1220
|
-
const targetSkywalk = path.join(specAbs, 'skywalk-sdd');
|
|
1221
|
-
fs.mkdirSync(path.join(skywalkDir, 'ontology'), { recursive: true });
|
|
1222
|
-
|
|
1223
|
-
const writeForwarder = (destRel, targetAbsPath) => {
|
|
1224
|
-
const dest = path.join(skywalkDir, destRel);
|
|
1225
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
1226
|
-
const relFromDestDir = path.relative(path.dirname(dest), targetAbsPath).replace(/\\/g, '/');
|
|
1227
|
-
const body = [
|
|
1228
|
-
'#!/usr/bin/env node',
|
|
1229
|
-
"'use strict';",
|
|
1230
|
-
"const { spawnSync } = require('child_process');",
|
|
1231
|
-
"const path = require('path');",
|
|
1232
|
-
`const target = path.resolve(__dirname, ${JSON.stringify(relFromDestDir)});`,
|
|
1233
|
-
'const r = spawnSync(process.execPath, [target, ...process.argv.slice(2)], { stdio: \'inherit\' });',
|
|
1234
|
-
'process.exit(r.status === null ? 1 : r.status);',
|
|
1235
|
-
'',
|
|
1236
|
-
].join('\n');
|
|
1237
|
-
fs.writeFileSync(dest, body, 'utf8');
|
|
1238
|
-
};
|
|
1239
|
-
|
|
1240
|
-
const entries = [
|
|
1241
|
-
'log.cjs',
|
|
1242
|
-
'openspec-shim.cjs',
|
|
1243
|
-
'context-client.cjs',
|
|
1244
|
-
'apply-worktree-finish.cjs',
|
|
1245
|
-
];
|
|
1246
|
-
for (const name of entries) {
|
|
1247
|
-
writeForwarder(name, path.join(targetSkywalk, name));
|
|
1248
|
-
}
|
|
1249
|
-
writeForwarder(path.join('ontology', 'cli.cjs'), path.join(targetSkywalk, 'ontology', 'cli.cjs'));
|
|
1250
|
-
console.log(` ✓ skywalk-sdd/ 转发脚本 → ${relSpec}/skywalk-sdd/(实体在包裹包)`);
|
|
1251
|
-
return { ok: true, mode: 'forwarders', relSpec };
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
function linkSkywalkToSpecPackage(anchorDir, specPackageAbs) {
|
|
1251
|
+
function removeOuterSkywalk(anchorDir) {
|
|
1255
1252
|
const anchor = path.resolve(anchorDir);
|
|
1256
|
-
const
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
return { ok:
|
|
1253
|
+
const outer = path.join(anchor, 'skywalk-sdd');
|
|
1254
|
+
let st = null;
|
|
1255
|
+
try {
|
|
1256
|
+
st = fs.lstatSync(outer);
|
|
1257
|
+
} catch (err) {
|
|
1258
|
+
if (err && err.code === 'ENOENT') return { ok: true, removed: false };
|
|
1259
|
+
throw err;
|
|
1262
1260
|
}
|
|
1263
1261
|
|
|
1262
|
+
const hint = path.join(anchor, '.sdd-spec-root');
|
|
1263
|
+
const hasHint = fs.existsSync(hint);
|
|
1264
|
+
let hasNestedEntity = false;
|
|
1264
1265
|
try {
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
if (st) {
|
|
1272
|
-
if (st.isSymbolicLink()) {
|
|
1273
|
-
const current = fs.realpathSync(linkAbs);
|
|
1274
|
-
if (current === fs.realpathSync(targetAbs)) {
|
|
1275
|
-
console.log(' ✓ skywalk-sdd/ 已链接到包裹包(唯一实体)');
|
|
1276
|
-
return { ok: true, mode: 'symlink', linkAbs, targetAbs };
|
|
1277
|
-
}
|
|
1278
|
-
fs.unlinkSync(linkAbs);
|
|
1279
|
-
} else if (st.isDirectory()) {
|
|
1280
|
-
// 旧完整副本 → 删除后改链接(权威数据在包裹包)
|
|
1281
|
-
fs.rmSync(linkAbs, { recursive: true, force: true });
|
|
1282
|
-
} else {
|
|
1283
|
-
fs.unlinkSync(linkAbs);
|
|
1266
|
+
for (const name of fs.readdirSync(anchor)) {
|
|
1267
|
+
if (!/-sdd-specs$/i.test(name)) continue;
|
|
1268
|
+
const entity = path.join(anchor, name, 'skywalk-sdd', 'log.cjs');
|
|
1269
|
+
if (fs.existsSync(entity)) {
|
|
1270
|
+
hasNestedEntity = true;
|
|
1271
|
+
break;
|
|
1284
1272
|
}
|
|
1285
1273
|
}
|
|
1286
|
-
} catch
|
|
1287
|
-
|
|
1288
|
-
|
|
1274
|
+
} catch {
|
|
1275
|
+
// ignore
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
if (!hasHint && !hasNestedEntity) {
|
|
1279
|
+
// 无包裹包迹象时不贸然删除(可能是旧平铺布局)
|
|
1280
|
+
return { ok: true, removed: false, skipped: true };
|
|
1289
1281
|
}
|
|
1290
1282
|
|
|
1291
|
-
const rel = path.relative(anchor, targetAbs);
|
|
1292
1283
|
try {
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1284
|
+
if (st.isSymbolicLink()) {
|
|
1285
|
+
fs.unlinkSync(outer);
|
|
1286
|
+
console.log(' ✓ 已移除 Git/工作区根多余的 skywalk-sdd 符号链接(实体在包裹包)');
|
|
1287
|
+
return { ok: true, removed: true, mode: 'symlink' };
|
|
1288
|
+
}
|
|
1289
|
+
if (st.isDirectory()) {
|
|
1290
|
+
fs.rmSync(outer, { recursive: true, force: true });
|
|
1291
|
+
console.log(' ✓ 已移除 Git/工作区根多余的 skywalk-sdd/(实体在包裹包)');
|
|
1292
|
+
return { ok: true, removed: true, mode: 'directory' };
|
|
1293
|
+
}
|
|
1294
|
+
fs.unlinkSync(outer);
|
|
1295
|
+
console.log(' ✓ 已移除 Git/工作区根多余的 skywalk-sdd');
|
|
1296
|
+
return { ok: true, removed: true, mode: 'file' };
|
|
1296
1297
|
} catch (err) {
|
|
1297
|
-
console.log(` ⚠️
|
|
1298
|
-
return
|
|
1298
|
+
console.log(` ⚠️ 未能移除根目录 skywalk-sdd/: ${err.message}`);
|
|
1299
|
+
return { ok: false, message: err.message };
|
|
1299
1300
|
}
|
|
1300
1301
|
}
|
|
1301
1302
|
|
|
@@ -1519,8 +1520,7 @@ async function main() {
|
|
|
1519
1520
|
asIndependentGit: true,
|
|
1520
1521
|
});
|
|
1521
1522
|
writeSddSpecRootHint(workspaceRoot, specPackage.abs);
|
|
1522
|
-
|
|
1523
|
-
linkSkywalkToSpecPackage(workspaceRoot, specPackage.abs);
|
|
1523
|
+
removeOuterSkywalk(workspaceRoot);
|
|
1524
1524
|
|
|
1525
1525
|
// 重新探测,刷新 layout.specRepo / codeRepos
|
|
1526
1526
|
layout = workspaceLayout.detectWorkspaceLayout(workspaceRoot);
|
|
@@ -1549,11 +1549,11 @@ async function main() {
|
|
|
1549
1549
|
asIndependentGit: false,
|
|
1550
1550
|
});
|
|
1551
1551
|
writeSddSpecRootHint(workspaceRoot, specPackage.abs);
|
|
1552
|
-
|
|
1552
|
+
removeOuterSkywalk(workspaceRoot);
|
|
1553
1553
|
|
|
1554
1554
|
deployMonoSddYaml(workspaceRoot, { specPathRelative: specPackage.name });
|
|
1555
|
-
// Hook 装在 Git
|
|
1556
|
-
|
|
1555
|
+
// Hook 装在 Git 根,脚本在包裹包内(Git 根不落 skywalk-sdd/)
|
|
1556
|
+
installCodeRepoCommitMsgHook(workspaceRoot, specPackage.abs);
|
|
1557
1557
|
const linked = sddConfig.setSpecPath(workspaceRoot, specPackage.abs, {
|
|
1558
1558
|
allowNestedPackage: true,
|
|
1559
1559
|
});
|
|
@@ -1571,7 +1571,7 @@ async function main() {
|
|
|
1571
1571
|
asIndependentGit: false,
|
|
1572
1572
|
});
|
|
1573
1573
|
writeSddSpecRootHint(workspaceRoot, specPackage.abs);
|
|
1574
|
-
|
|
1574
|
+
removeOuterSkywalk(workspaceRoot);
|
|
1575
1575
|
deployDotSddYaml(workspaceRoot);
|
|
1576
1576
|
}
|
|
1577
1577
|
}
|
|
@@ -1603,6 +1603,12 @@ async function main() {
|
|
|
1603
1603
|
// 7. 更新工作目录 .gitignore
|
|
1604
1604
|
updateGitignore();
|
|
1605
1605
|
|
|
1606
|
+
// 8. 收尾:无论前面是否走过 symlink/旧副本路径,强制清掉工作区/Git 根多余 skywalk-sdd/
|
|
1607
|
+
if (specPackage && fs.existsSync(specPackage.abs)) {
|
|
1608
|
+
writeSddSpecRootHint(workspaceRoot, specPackage.abs);
|
|
1609
|
+
}
|
|
1610
|
+
removeOuterSkywalk(workspaceRoot);
|
|
1611
|
+
|
|
1606
1612
|
const selectedNames = selectedTools.map(t => TOOL_CONFIGS[t].name).join(', ');
|
|
1607
1613
|
|
|
1608
1614
|
console.log();
|
|
@@ -1616,7 +1622,8 @@ async function main() {
|
|
|
1616
1622
|
console.log('工作区部署结果:');
|
|
1617
1623
|
console.log(' 🎯 工作目录 .*/skills/opsx-*/ # skills 只装这一份');
|
|
1618
1624
|
console.log(' 📋 .sdd-workspace.yaml # 子仓编排清单');
|
|
1619
|
-
console.log('
|
|
1625
|
+
console.log(' 📌 .sdd-spec-root # 指向包裹包;CLI 用 $(cat .sdd-spec-root)/skywalk-sdd/…');
|
|
1626
|
+
console.log(' ✗ 工作区根无 skywalk-sdd/ # 实体只在包裹包内');
|
|
1620
1627
|
if (specPackage) {
|
|
1621
1628
|
console.log(` 📄 ${specPackage.name}/ # 统一 SDD 包裹包(独立 Git)`);
|
|
1622
1629
|
console.log(' modules.yaml / sdd.config.yaml / openspec / openspec-templates / skywalk-sdd');
|
|
@@ -1635,8 +1642,8 @@ async function main() {
|
|
|
1635
1642
|
console.log(` 📄 ${specPackage.name}/ # 统一 SDD 包裹包(仓内子目录)`);
|
|
1636
1643
|
console.log(' modules.yaml / sdd.config.yaml / openspec / openspec-templates / skywalk-sdd');
|
|
1637
1644
|
}
|
|
1638
|
-
console.log(' 🔗 .sdd.yaml (layout: mono) + commit-msg Hook');
|
|
1639
|
-
console.log('
|
|
1645
|
+
console.log(' 🔗 .sdd.yaml (layout: mono) + commit-msg Hook(脚本在包裹包)');
|
|
1646
|
+
console.log(' 📌 .sdd-spec-root → 包裹包;无根目录 skywalk-sdd/');
|
|
1640
1647
|
}
|
|
1641
1648
|
if (selectedTools.includes('kunlunzhima')) {
|
|
1642
1649
|
console.log(' 📎 .kunlunzhima/commands/opsx/ # KunlunZhima OPSX command bridge(11 个)');
|
|
@@ -1712,8 +1719,7 @@ module.exports = {
|
|
|
1712
1719
|
deployMonoSddYaml,
|
|
1713
1720
|
populateSpecPackage,
|
|
1714
1721
|
writeSddSpecRootHint,
|
|
1715
|
-
|
|
1716
|
-
deploySkywalkForwarders,
|
|
1722
|
+
removeOuterSkywalk,
|
|
1717
1723
|
deployQualityGateTemplates,
|
|
1718
1724
|
deployTelemetryDataDir,
|
|
1719
1725
|
attachCodeRepoLite,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kld-sdd",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.13",
|
|
4
4
|
"description": "KLD SDD OpenSpec 项目初始化工具 - 一键部署 SDD skills",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"kld-sdd-init": "bin/kld-sdd-init.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "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/workspace-layout.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/validate-skills-bundle.cjs && node test/tool-profiles.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"
|
|
11
|
+
"test": "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/workspace-layout.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/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/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"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"kld",
|
|
@@ -32,6 +32,9 @@
|
|
|
32
32
|
"templates/",
|
|
33
33
|
"kld-sdd-guide.html",
|
|
34
34
|
"skywalk-sdd/index.cjs",
|
|
35
|
+
"skywalk-sdd/metrics-v3.cjs",
|
|
36
|
+
"skywalk-sdd/runtime-metadata.cjs",
|
|
37
|
+
"skywalk-sdd/reporting/",
|
|
35
38
|
"skywalk-sdd/context-client.cjs",
|
|
36
39
|
"skywalk-sdd/ontology/",
|
|
37
40
|
"skywalk-sdd/apply-worktree-finish.cjs",
|