kld-sdd 2.6.17 → 2.7.3
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 +4 -0
- package/kld-sdd-guide.html +22 -0
- package/lib/init.js +160 -73
- package/package.json +3 -3
- package/skywalk-sdd/index.cjs +155 -25
- package/skywalk-sdd/lib/git-identity.cjs +270 -0
- package/skywalk-sdd/lib/shared.cjs +150 -2
- package/skywalk-sdd/lib/usage-contract.cjs +207 -0
- package/skywalk-sdd/lib/usage-reporter.cjs +460 -0
- package/skywalk-sdd/lib/user-config.cjs +132 -0
- package/skywalk-sdd/ontology/artifact-parser.cjs +1 -2
- package/templates/git-hooks/commit-msg +58 -15
- package/templates/git-hooks/hooks.config +19 -0
- package/templates/git-hooks/pre-commit +45 -11
- package/templates/git-hooks/pre-commit-consistency-check.cjs +271 -116
- package/templates/git-hooks/pre-push +53 -11
- package/templates/git-hooks/pre-push-consistency-check.cjs +357 -118
- package/templates/skills/kld-sdd/opsx-check/SKILL.md +1 -1
- package/templates/skills/kld-sdd/opsx-consistency-check/SKILL.md +187 -257
- package/templates/skills/kld-sdd/opsx-consistency-check/reference.md +129 -0
- package/templates/skills/kld-sdd/opsx-kb-config/SKILL.md +27 -6
- package/templates/skills/kld-sdd/opsx-kb-config/reference.md +12 -1
package/bin/kld-sdd-init.js
CHANGED
|
@@ -50,6 +50,10 @@ if (args[0] === 'log') {
|
|
|
50
50
|
process.exit(1);
|
|
51
51
|
}
|
|
52
52
|
console.log(`✅ sync-repos 完成,接入 ${result.attached.length} 个代码仓`);
|
|
53
|
+
} else if (args[0] === 'auth') {
|
|
54
|
+
// 登录体系已随 2.7.0 移除:仅保留 deprecation 提示,不进入 init 向导
|
|
55
|
+
console.log('ℹ️ auth 子命令已于 2.7.0 移除:使用统计按本机 git 身份(user.name/user.email)上报,无需绑定。');
|
|
56
|
+
process.exit(0);
|
|
53
57
|
} else {
|
|
54
58
|
// 正常初始化模式
|
|
55
59
|
const { main } = require('../lib/init');
|
package/kld-sdd-guide.html
CHANGED
|
@@ -1116,6 +1116,28 @@ node skywalk-sdd/log.cjs semantic-observe --project=. --change=add-user-auth">
|
|
|
1116
1116
|
<div class="metric reveal"><div class="key">P-H</div><h4>Telemetry 健康度</h4><div class="value">doctor health × 100</div><p>与 P-C 阶段闭合率一起判断数据是否足够可信。</p></div>
|
|
1117
1117
|
</div>
|
|
1118
1118
|
|
|
1119
|
+
<p class="lead reveal" style="margin-top:32px"><b>KB 实时进度同步(Progress Agent)</b>:本地 JSONL 事实经 canonical CloudEvent 适配后发送到 Engineering KB;仅 durable ACK(accepted / duplicate_accepted)且仍 active 的 Run 才会发送 heartbeat。Agent 是<strong>事件触发、有限会话</strong>的用户级单实例——<strong>不再默认开机自启动/长期驻留</strong>:每条新 SDD 事实 durable append 后自动拉起(<code>ensureAgentRunning</code> 按 <code>agent.lock</code> 探测避免重复 spawn),按 5/15/10 分钟三档租约(clean idle / active silence / retry budget)自行退出;旧版开机自启动会在 init/config 时被幂等迁移移除。</p>
|
|
1120
|
+
<div class="codeblock reveal">
|
|
1121
|
+
<button type="button" class="copy" data-copy="# 配置 KB(需 progress:write scope)后 init 会自动 register,best-effort 迁移旧自启动 + 拉起当前会话 Agent
|
|
1122
|
+
npx kld-sdd --tool codex
|
|
1123
|
+
|
|
1124
|
+
# 手动单次同步(强制 batch → ACK 落盘 → heartbeat,不进入有限会话循环)
|
|
1125
|
+
node skywalk-sdd/progress/agent-main.cjs --once --user-state-root=%LOCALAPPDATA%/kld-sdd/progress
|
|
1126
|
+
|
|
1127
|
+
# 手动触发有限会话(正常由新 SDD 事实自动拉起,一般无需手动执行)
|
|
1128
|
+
node skywalk-sdd/progress/agent-main.cjs --user-state-root=%LOCALAPPDATA%/kld-sdd/progress
|
|
1129
|
+
|
|
1130
|
+
# 查看自启动/迁移状态(degraded 时可再次 config/init 恢复)
|
|
1131
|
+
node -e "require('./skywalk-sdd/progress/autostart.cjs').statusAutostart({testMode:true}).then(console.log)"">复制</button>
|
|
1132
|
+
<pre><span class="k-c"># apiBase 必须包含 /api,例如 http://host:8090/api</span>
|
|
1133
|
+
<span class="k-c"># 状态目录:%LOCALAPPDATA%/kld-sdd/progress(Windows)或 ~/.local/state/kld-sdd/progress</span>
|
|
1134
|
+
<span class="k-p">➜</span> <span class="k-s">node</span> skywalk-sdd/progress/agent-main.cjs <span class="k-f">--once</span> --user-state-root=<USER_STATE_ROOT>
|
|
1135
|
+
<span class="k-p">➜</span> <span class="k-s">node</span> skywalk-sdd/progress/agent-main.cjs --user-state-root=<USER_STATE_ROOT> <span class="k-o">(triggered finite session)</span>
|
|
1136
|
+
<span class="k-p">➜</span> <span class="k-s">node</span> skywalk-sdd/progress/autostart.cjs <span class="k-f">status</span> <span class="k-o">(platform adapter)</span></pre>
|
|
1137
|
+
</div>
|
|
1138
|
+
<div class="callout reveal"><b>破坏性对齐(CloudEvent 出站):</b>出站 envelope 已与 KB canonical 契约对齐——<code>type</code> 为 <code>com.kunlunzhima.sdd.<event_kind>.v1</code>,<code>source</code> 为 <code>urn:kld-sdd:installation:…:workspace:…</code>,payload 含 <code>seq</code>/<code>change_key</code>,哈希模式 <code>canonical-json-v1</code>。旧版自定义 type/source/外壳<strong>不再兼容</strong>;升级后请以 KB schema/fixture 为准,勿依赖旧出站字段。</div>
|
|
1139
|
+
<div class="callout reveal"><b>排障:</b>401/403 或 rejected_scope → 检查 API Key 是否含 <code>progress:write</code>;schema 拒绝只隔离单条事件;<code>autostart=degraded</code> 不破坏 kb-state,可重跑 config/init;heartbeat 不含 <code>active</code> 字段,资格来自 durable ACK + 本地 active Run 交集;可选 <code>agent_state</code>(<code>active</code>/<code>sleeping</code>/<code>terminal</code>)仅在会话启动/唤醒与计划退出前 best-effort 上报。</div>
|
|
1140
|
+
|
|
1119
1141
|
<p class="lead reveal" style="margin-top:32px"><b>事件与单变更报告</b>:事件落 <code>skywalk-sdd/events/</code>、活跃状态落 <code>skywalk-sdd/state/</code>(均 gitignored);归档报告落 <code>openspec/changes/archive/<date>-<name>/reports/</code>。</p>
|
|
1120
1142
|
<div class="codeblock reveal">
|
|
1121
1143
|
<button type="button" class="copy" data-copy="node skywalk-sdd/log.cjs start --command=propose --project=. --change=add-user-auth --agent=codex --source=opsx-skill --session-id=sess_001
|
package/lib/init.js
CHANGED
|
@@ -31,10 +31,24 @@ const { deployCodebuddyHookPack } = require('./deploy-codebuddy-hooks');
|
|
|
31
31
|
const workspaceLayout = require('./workspace-layout');
|
|
32
32
|
const sddConfig = require('../skywalk-sdd/ontology/sdd-config.cjs');
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
let rl = null;
|
|
35
|
+
|
|
36
|
+
function getRl() {
|
|
37
|
+
if (!rl) {
|
|
38
|
+
rl = readline.createInterface({
|
|
39
|
+
input: process.stdin,
|
|
40
|
+
output: process.stdout,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return rl;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function closeRl() {
|
|
47
|
+
if (rl) {
|
|
48
|
+
rl.close();
|
|
49
|
+
rl = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
38
52
|
|
|
39
53
|
// 工具类型配置(路径字段从 TOOL_PROFILES 派生,避免双份漂移)
|
|
40
54
|
const TOOL_CONFIGS = buildToolConfigs();
|
|
@@ -44,10 +58,30 @@ const TOOL_CONFIGS = buildToolConfigs();
|
|
|
44
58
|
*/
|
|
45
59
|
function ask(question) {
|
|
46
60
|
return new Promise(resolve => {
|
|
47
|
-
|
|
61
|
+
getRl().question(question, answer => resolve(answer.trim()));
|
|
48
62
|
});
|
|
49
63
|
}
|
|
50
64
|
|
|
65
|
+
/**
|
|
66
|
+
* 输出详细度判定(惰性读取,便于测试在运行期注入)
|
|
67
|
+
* 触发条件:argv 含 --verbose,或 KLD_SDD_VERBOSE 为 1/true(大小写不敏感)
|
|
68
|
+
* 注意:-v 已被 --version 占用,不复用
|
|
69
|
+
*/
|
|
70
|
+
function isVerbose() {
|
|
71
|
+
if (process.argv.includes('--verbose')) return true;
|
|
72
|
+
const env = process.env.KLD_SDD_VERBOSE;
|
|
73
|
+
return typeof env === 'string' && /^(1|true)$/i.test(env);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* verbose 模式下的明细日志;默认模式静默
|
|
78
|
+
*/
|
|
79
|
+
function vlog(...args) {
|
|
80
|
+
if (isVerbose()) {
|
|
81
|
+
console.log(...args);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
51
85
|
/**
|
|
52
86
|
* 从命令行参数读取指定编辑器
|
|
53
87
|
* 支持:--tool codex、--tool=codex、--tool cursor,codex、--tool all
|
|
@@ -496,7 +530,7 @@ function deployOpsxSkills(selectedTools = Object.keys(TOOL_CONFIGS)) {
|
|
|
496
530
|
|
|
497
531
|
if (fs.existsSync(sourceDir)) {
|
|
498
532
|
copyDirRendered(sourceDir, targetDir, config, toolKey);
|
|
499
|
-
|
|
533
|
+
vlog(` ✓ ${skillDir}/`);
|
|
500
534
|
}
|
|
501
535
|
}
|
|
502
536
|
}
|
|
@@ -706,14 +740,14 @@ function copyTemplatesToProject(cwd = process.cwd()) {
|
|
|
706
740
|
}
|
|
707
741
|
|
|
708
742
|
copyDir(templatePath, targetDir);
|
|
709
|
-
|
|
710
|
-
console.log(`✅ 标准文档模版已复制到: ${targetDir}`);
|
|
711
|
-
console.log(' 包含文件:');
|
|
743
|
+
|
|
712
744
|
const files = fs.readdirSync(targetDir);
|
|
745
|
+
console.log(`✅ 标准文档模版已复制到: ${targetDir}(${files.length} 个文件)`);
|
|
746
|
+
vlog(' 包含文件:');
|
|
713
747
|
files.forEach(file => {
|
|
714
|
-
|
|
748
|
+
vlog(` - ${file}`);
|
|
715
749
|
});
|
|
716
|
-
|
|
750
|
+
|
|
717
751
|
return true;
|
|
718
752
|
}
|
|
719
753
|
|
|
@@ -803,13 +837,15 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
803
837
|
// 创建本地数据目录(事件和活跃状态存储;报告落 change 子目录,不在此创建)
|
|
804
838
|
const eventsDir = path.join(dataDir, 'events');
|
|
805
839
|
const stateDir = path.join(dataDir, 'state');
|
|
840
|
+
// 成功部署的模块计数(用于默认模式单行摘要)
|
|
841
|
+
let deployedModules = 0;
|
|
806
842
|
if (!fs.existsSync(eventsDir)) {
|
|
807
843
|
fs.mkdirSync(eventsDir, { recursive: true });
|
|
808
|
-
|
|
844
|
+
vlog(' ✓ 创建 skywalk-sdd/events/ 数据目录');
|
|
809
845
|
}
|
|
810
846
|
if (!fs.existsSync(stateDir)) {
|
|
811
847
|
fs.mkdirSync(stateDir, { recursive: true });
|
|
812
|
-
|
|
848
|
+
vlog(' ✓ 创建 skywalk-sdd/state/ 活跃阶段状态目录');
|
|
813
849
|
}
|
|
814
850
|
|
|
815
851
|
// 部署项目内 Telemetry CLI(不依赖 npm 发布)
|
|
@@ -817,7 +853,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
817
853
|
const telemetryDst = path.join(dataDir, 'log.cjs');
|
|
818
854
|
if (fs.existsSync(telemetrySrc)) {
|
|
819
855
|
fs.copyFileSync(telemetrySrc, telemetryDst);
|
|
820
|
-
|
|
856
|
+
deployedModules += 1;
|
|
857
|
+
vlog(' ✓ 部署 skywalk-sdd/log.cjs(本地 Telemetry CLI)');
|
|
821
858
|
} else {
|
|
822
859
|
console.log(` ⚠️ Telemetry CLI 源文件缺失: ${telemetrySrc}`);
|
|
823
860
|
}
|
|
@@ -826,7 +863,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
826
863
|
const metricsV3Dst = path.join(dataDir, 'metrics-v3.cjs');
|
|
827
864
|
if (fs.existsSync(metricsV3Src)) {
|
|
828
865
|
fs.copyFileSync(metricsV3Src, metricsV3Dst);
|
|
829
|
-
|
|
866
|
+
deployedModules += 1;
|
|
867
|
+
vlog(' ✓ 部署 skywalk-sdd/metrics-v3.cjs(V3 指标运行时)');
|
|
830
868
|
} else {
|
|
831
869
|
console.log(` ⚠️ V3 指标模块源文件缺失: ${metricsV3Src}(report/metrics 可能无法加载 metrics-v3)`);
|
|
832
870
|
}
|
|
@@ -836,7 +874,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
836
874
|
const specRootDst = path.join(dataDir, 'spec-root.cjs');
|
|
837
875
|
if (fs.existsSync(specRootSrc)) {
|
|
838
876
|
fs.copyFileSync(specRootSrc, specRootDst);
|
|
839
|
-
|
|
877
|
+
deployedModules += 1;
|
|
878
|
+
vlog(' ✓ 部署 skywalk-sdd/spec-root.cjs(CWD 无关的 spec 根路径解析器)');
|
|
840
879
|
} else {
|
|
841
880
|
console.log(' ⚠️ spec-root.cjs 源文件缺失,$(cat .sdd-spec-root) 模式可能受影响');
|
|
842
881
|
}
|
|
@@ -850,11 +889,35 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
850
889
|
const sharedDst = path.join(sharedLibDir, 'shared.cjs');
|
|
851
890
|
if (fs.existsSync(sharedSrc)) {
|
|
852
891
|
fs.copyFileSync(sharedSrc, sharedDst);
|
|
853
|
-
|
|
892
|
+
deployedModules += 1;
|
|
893
|
+
vlog(' ✓ 部署 skywalk-sdd/lib/shared.cjs(共用工具:parseArgs/JSON/BOM/HTTP/specRoot/KB)');
|
|
854
894
|
} else {
|
|
855
895
|
console.log(' ⚠️ lib/shared.cjs 源文件缺失,多个脚本将缺少共用工具依赖');
|
|
856
896
|
}
|
|
857
897
|
|
|
898
|
+
// kld-fixback: 部署使用统计上报模块(usage-contract/usage-reporter/user-config/git-identity)
|
|
899
|
+
// 这些模块被部署后的 skywalk-sdd/log.cjs(即 index.cjs 副本)在 cmdStart 中 require,
|
|
900
|
+
// 缺失时会上报静默失效。四件套必须同时部署,路径与 npm 包内布局一致。
|
|
901
|
+
// ⚠️ usage-reporter.cjs 顶层 require('./git-identity.cjs'):缺它时模块加载即抛
|
|
902
|
+
// MODULE_NOT_FOUND,被 cmdStart try/catch 吞掉后上报 100% 静默丢失。
|
|
903
|
+
const usageModules = [
|
|
904
|
+
{ src: 'usage-contract.cjs', desc: '使用统计契约(七值/ApiResponse/HTTP)' },
|
|
905
|
+
{ src: 'usage-reporter.cjs', desc: '使用事件上报器(git 身份缓存 + 3s deadline + pending 队列)' },
|
|
906
|
+
{ src: 'user-config.cjs', desc: '用户级配置(~/.kld-sdd/config.json,仅 server)' },
|
|
907
|
+
{ src: 'git-identity.cjs', desc: 'git 身份持久缓存与后台刷新(usage-reporter 的硬依赖)' },
|
|
908
|
+
];
|
|
909
|
+
for (const mod of usageModules) {
|
|
910
|
+
const src = path.join(pkgPath, 'skywalk-sdd', 'lib', mod.src);
|
|
911
|
+
const dst = path.join(sharedLibDir, mod.src);
|
|
912
|
+
if (fs.existsSync(src)) {
|
|
913
|
+
fs.copyFileSync(src, dst);
|
|
914
|
+
deployedModules += 1;
|
|
915
|
+
vlog(` ✓ 部署 skywalk-sdd/lib/${mod.src}(${mod.desc})`);
|
|
916
|
+
} else {
|
|
917
|
+
console.log(` ⚠️ ${mod.src} 源文件缺失,使用统计上报将不可用`);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
858
921
|
const packageVersion = require(path.join(pkgPath, 'package.json')).version;
|
|
859
922
|
const runtimeMetadataDst = path.join(dataDir, 'runtime-metadata.cjs');
|
|
860
923
|
fs.writeFileSync(
|
|
@@ -862,13 +925,15 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
862
925
|
`'use strict';\nmodule.exports = { resolveRuntimeMetadata() { return { version: '${packageVersion}', producer: 'kld-sdd@${packageVersion}' }; } };\n`,
|
|
863
926
|
'utf8',
|
|
864
927
|
);
|
|
865
|
-
|
|
928
|
+
deployedModules += 1;
|
|
929
|
+
vlog(` ✓ 部署 kld-sdd 运行时身份(${packageVersion})`);
|
|
866
930
|
|
|
867
931
|
const reportingSrc = path.join(pkgPath, 'skywalk-sdd', 'reporting');
|
|
868
932
|
const reportingDst = path.join(dataDir, 'reporting');
|
|
869
933
|
if (fs.existsSync(reportingSrc)) {
|
|
870
934
|
copyDir(reportingSrc, reportingDst);
|
|
871
|
-
|
|
935
|
+
deployedModules += 1;
|
|
936
|
+
vlog(' ✓ 部署 skywalk-sdd/reporting/(V3 单次变更报告)');
|
|
872
937
|
} else {
|
|
873
938
|
throw new Error(`E_INIT_MISSING_CRITICAL: reporting/ 目录缺失: ${reportingSrc}(归档报告生成将失败)`);
|
|
874
939
|
}
|
|
@@ -877,7 +942,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
877
942
|
const contextClientDst = path.join(dataDir, 'context-client.cjs');
|
|
878
943
|
if (fs.existsSync(contextClientSrc)) {
|
|
879
944
|
fs.copyFileSync(contextClientSrc, contextClientDst);
|
|
880
|
-
|
|
945
|
+
deployedModules += 1;
|
|
946
|
+
vlog(' ✓ 部署 skywalk-sdd/context-client.cjs(工程 Spec 上下文客户端)');
|
|
881
947
|
} else {
|
|
882
948
|
console.log(` ⚠️ 工程 Spec 上下文客户端缺失: ${contextClientSrc}`);
|
|
883
949
|
}
|
|
@@ -886,7 +952,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
886
952
|
const ontologyDst = path.join(dataDir, 'ontology');
|
|
887
953
|
if (fs.existsSync(ontologySrc)) {
|
|
888
954
|
copyDir(ontologySrc, ontologyDst);
|
|
889
|
-
|
|
955
|
+
deployedModules += 1;
|
|
956
|
+
vlog(' ✓ 部署 skywalk-sdd/ontology/(本地本体语义运行时)');
|
|
890
957
|
} else {
|
|
891
958
|
console.log(` ⚠️ 本体语义运行时缺失: ${ontologySrc}`);
|
|
892
959
|
}
|
|
@@ -895,7 +962,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
895
962
|
const worktreeFinishDst = path.join(dataDir, 'apply-worktree-finish.cjs');
|
|
896
963
|
if (fs.existsSync(worktreeFinishSrc)) {
|
|
897
964
|
fs.copyFileSync(worktreeFinishSrc, worktreeFinishDst);
|
|
898
|
-
|
|
965
|
+
deployedModules += 1;
|
|
966
|
+
vlog(' ✓ 部署 skywalk-sdd/apply-worktree-finish.cjs(Apply 收尾脚本)');
|
|
899
967
|
} else {
|
|
900
968
|
console.log(' ⚠️ apply-worktree-finish.cjs 源文件缺失,Apply 阶段收尾需要手动执行');
|
|
901
969
|
}
|
|
@@ -904,7 +972,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
904
972
|
const openspecShimDst = path.join(dataDir, 'openspec-shim.cjs');
|
|
905
973
|
if (fs.existsSync(openspecShimSrc)) {
|
|
906
974
|
fs.copyFileSync(openspecShimSrc, openspecShimDst);
|
|
907
|
-
|
|
975
|
+
deployedModules += 1;
|
|
976
|
+
vlog(' ✓ 部署 skywalk-sdd/openspec-shim.cjs(openspec 包裹包路径 shim)');
|
|
908
977
|
} else {
|
|
909
978
|
console.log(' ⚠️ openspec-shim.cjs 源文件缺失,openspec 命令需要手动 cd 到 spec 包执行');
|
|
910
979
|
}
|
|
@@ -914,7 +983,8 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
914
983
|
const kbUploadDst = path.join(dataDir, 'kb-upload.cjs');
|
|
915
984
|
if (fs.existsSync(kbUploadSrc)) {
|
|
916
985
|
fs.copyFileSync(kbUploadSrc, kbUploadDst);
|
|
917
|
-
|
|
986
|
+
deployedModules += 1;
|
|
987
|
+
vlog(' ✓ 部署 skywalk-sdd/kb-upload.cjs(知识库上传:文件夹/zip 双模式)');
|
|
918
988
|
} else {
|
|
919
989
|
console.log(' ⚠️ kb-upload.cjs 源文件缺失,随时入库功能不可用');
|
|
920
990
|
}
|
|
@@ -924,16 +994,18 @@ function deployTelemetryDataDir(targetCwd = process.cwd()) {
|
|
|
924
994
|
const kbSyncIdentityDst = path.join(dataDir, 'kb-sync-identity.cjs');
|
|
925
995
|
if (fs.existsSync(kbSyncIdentitySrc)) {
|
|
926
996
|
fs.copyFileSync(kbSyncIdentitySrc, kbSyncIdentityDst);
|
|
927
|
-
|
|
997
|
+
deployedModules += 1;
|
|
998
|
+
vlog(' ✓ 部署 skywalk-sdd/kb-sync-identity.cjs(KB 身份同步:重新入库前同步 version-id)');
|
|
928
999
|
} else {
|
|
929
1000
|
console.log(' ⚠️ kb-sync-identity.cjs 源文件缺失,重新入库身份同步不可用');
|
|
930
1001
|
}
|
|
931
1002
|
|
|
932
|
-
console.log(
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1003
|
+
console.log(` ✓ 部署 skywalk-sdd/ 运行时(events/state 数据目录 + ${deployedModules} 个模块)`);
|
|
1004
|
+
vlog(' ✓ 调用方式: node skywalk-sdd/log.cjs start|end|metrics|semantic-identity|semantic-reconcile|semantic-check');
|
|
1005
|
+
vlog(' ✓ openspec: node skywalk-sdd/openspec-shim.cjs list(自动 cd 到 *-sdd-specs)');
|
|
1006
|
+
vlog(' ✓ Spec Context: node skywalk-sdd/context-client.cjs --query="<自然语言需求>" --target-stage=spec');
|
|
1007
|
+
vlog(' ✓ Apply worktree: record-base 在 §1.5;收尾 apply-worktree-finish.cjs --change=<name>');
|
|
1008
|
+
vlog(' ℹ️ project-identity.json 将在首次配置 KB(opsx-kb-config)时自动创建');
|
|
937
1009
|
console.log('✅ Telemetry 已就绪(数据存储在 skywalk-sdd/,无需配置 MCP)');
|
|
938
1010
|
return true;
|
|
939
1011
|
}
|
|
@@ -1025,22 +1097,17 @@ function deployCodeRepoHooks(codeRepoRoot, specRepoRoot, options = {}) {
|
|
|
1025
1097
|
if (!fs.existsSync(specHooksDir)) {
|
|
1026
1098
|
fs.mkdirSync(specHooksDir, { recursive: true });
|
|
1027
1099
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
'
|
|
1031
|
-
|
|
1032
|
-
'pre-push-consistency-check.cjs',
|
|
1033
|
-
];
|
|
1100
|
+
// 复制全部 .cjs 脚本 + hooks.config 配置文件
|
|
1101
|
+
const hookScripts = fs.existsSync(gitHooksTemplateDir)
|
|
1102
|
+
? fs.readdirSync(gitHooksTemplateDir).filter(f => f.endsWith('.cjs') || f === 'hooks.config')
|
|
1103
|
+
: [];
|
|
1034
1104
|
for (const script of hookScripts) {
|
|
1035
1105
|
const src = path.join(gitHooksTemplateDir, script);
|
|
1036
1106
|
const dst = path.join(specHooksDir, script);
|
|
1037
|
-
//
|
|
1038
|
-
|
|
1039
|
-
if (fs.existsSync(src)) {
|
|
1040
|
-
fs.copyFileSync(src, dst);
|
|
1041
|
-
}
|
|
1107
|
+
// 始终覆盖,与 shell hook 的 marker 覆盖策略保持一致
|
|
1108
|
+
fs.copyFileSync(src, dst);
|
|
1042
1109
|
}
|
|
1043
|
-
console.log(` ✓ 确保 spec 仓 skywalk-sdd/git-hooks/
|
|
1110
|
+
console.log(` ✓ 确保 spec 仓 skywalk-sdd/git-hooks/ 脚本齐全(${hookScripts.length} 个文件)`);
|
|
1044
1111
|
|
|
1045
1112
|
// ── 2. 安装三个 shell hooks 到代码仓 .git/hooks/ ──
|
|
1046
1113
|
// 模板 hook 运行时自动定位 spec 仓的 .cjs 脚本
|
|
@@ -1099,16 +1166,17 @@ function deployQualityGateTemplates(targetCwd = process.cwd(), options = {}) {
|
|
|
1099
1166
|
const targetCiDir = path.join(dataDir, 'ci');
|
|
1100
1167
|
|
|
1101
1168
|
if (fs.existsSync(gitHooksTemplateDir)) {
|
|
1102
|
-
//
|
|
1169
|
+
// 复制 .cjs 脚本 + hooks.config 到 skywalk-sdd/git-hooks/
|
|
1170
|
+
// shell hook 模板(commit-msg/pre-commit/pre-push)不落此目录
|
|
1103
1171
|
if (!fs.existsSync(targetGitHooksDir)) {
|
|
1104
1172
|
fs.mkdirSync(targetGitHooksDir, { recursive: true });
|
|
1105
1173
|
}
|
|
1106
1174
|
for (const file of fs.readdirSync(gitHooksTemplateDir)) {
|
|
1107
|
-
if (file.endsWith('.cjs')) {
|
|
1175
|
+
if (file.endsWith('.cjs') || file === 'hooks.config') {
|
|
1108
1176
|
fs.copyFileSync(path.join(gitHooksTemplateDir, file), path.join(targetGitHooksDir, file));
|
|
1109
1177
|
}
|
|
1110
1178
|
}
|
|
1111
|
-
console.log(' ✓ 部署 skywalk-sdd/git-hooks/(.cjs
|
|
1179
|
+
console.log(' ✓ 部署 skywalk-sdd/git-hooks/(.cjs 脚本 + hooks.config)');
|
|
1112
1180
|
} else {
|
|
1113
1181
|
console.log(` ⚠️ Git hooks 模板缺失: ${gitHooksTemplateDir}`);
|
|
1114
1182
|
}
|
|
@@ -1408,10 +1476,11 @@ function detectTools() {
|
|
|
1408
1476
|
|
|
1409
1477
|
/**
|
|
1410
1478
|
* 创建 / 更新 .gitignore
|
|
1479
|
+
* @param {string} [cwd=process.cwd()]
|
|
1411
1480
|
*/
|
|
1412
|
-
function updateGitignore() {
|
|
1413
|
-
const
|
|
1414
|
-
const gitignorePath = path.join(
|
|
1481
|
+
function updateGitignore(cwd = process.cwd()) {
|
|
1482
|
+
const root = path.resolve(cwd);
|
|
1483
|
+
const gitignorePath = path.join(root, '.gitignore');
|
|
1415
1484
|
const requiredLines = [
|
|
1416
1485
|
'.cursor/commands/personal-*',
|
|
1417
1486
|
'.claude/commands/personal-*',
|
|
@@ -1420,6 +1489,10 @@ function updateGitignore() {
|
|
|
1420
1489
|
'.kunlunzhima/commands/personal-*',
|
|
1421
1490
|
'.workbuddy/commands/personal-*',
|
|
1422
1491
|
'.agents/commands/personal-*',
|
|
1492
|
+
'kb-state.json',
|
|
1493
|
+
'**/kb-state.json',
|
|
1494
|
+
'skywalk-sdd/kb-state.json',
|
|
1495
|
+
'**/skywalk-sdd/kb-state.json',
|
|
1423
1496
|
'skywalk-sdd/events/',
|
|
1424
1497
|
'skywalk-sdd/state/',
|
|
1425
1498
|
'**/skywalk-sdd/events/',
|
|
@@ -1437,6 +1510,12 @@ function updateGitignore() {
|
|
|
1437
1510
|
.workbuddy/commands/personal-*
|
|
1438
1511
|
.agents/commands/personal-*
|
|
1439
1512
|
|
|
1513
|
+
# KB 绑定状态(含 API Key,勿提交)
|
|
1514
|
+
kb-state.json
|
|
1515
|
+
**/kb-state.json
|
|
1516
|
+
skywalk-sdd/kb-state.json
|
|
1517
|
+
**/skywalk-sdd/kb-state.json
|
|
1518
|
+
|
|
1440
1519
|
# SDD Telemetry 数据(实体在 *-sdd-specs/skywalk-sdd/;工作区可能是 symlink)
|
|
1441
1520
|
skywalk-sdd/events/
|
|
1442
1521
|
skywalk-sdd/state/
|
|
@@ -1480,6 +1559,7 @@ KLD SDD 项目初始化工具
|
|
|
1480
1559
|
选项:
|
|
1481
1560
|
-h, --help 显示帮助信息
|
|
1482
1561
|
-v, --version 显示版本号
|
|
1562
|
+
--verbose 输出每个安装文件/目录的明细日志(默认仅摘要,亦可用 KLD_SDD_VERBOSE=1)
|
|
1483
1563
|
--skip-openspec 跳过 openspec init 步骤
|
|
1484
1564
|
--skip-template 跳过复制内置模版
|
|
1485
1565
|
--tool <name> 指定编辑器,可用值: cursor, claude, codebuddy, qoder, opencode, kunlunzhima, workbuddy, codex, all
|
|
@@ -1548,14 +1628,14 @@ async function main() {
|
|
|
1548
1628
|
// 解析参数
|
|
1549
1629
|
if (args.includes('-h') || args.includes('--help')) {
|
|
1550
1630
|
showHelp();
|
|
1551
|
-
|
|
1631
|
+
closeRl();
|
|
1552
1632
|
return;
|
|
1553
1633
|
}
|
|
1554
1634
|
|
|
1555
1635
|
if (args.includes('-v') || args.includes('--version')) {
|
|
1556
1636
|
const pkg = require('../package.json');
|
|
1557
1637
|
console.log(pkg.version);
|
|
1558
|
-
|
|
1638
|
+
closeRl();
|
|
1559
1639
|
return;
|
|
1560
1640
|
}
|
|
1561
1641
|
|
|
@@ -1574,7 +1654,7 @@ async function main() {
|
|
|
1574
1654
|
selectedTools = parseSelectedTools(args) || await selectEditor();
|
|
1575
1655
|
} catch (error) {
|
|
1576
1656
|
console.error(`❌ ${error.message}`);
|
|
1577
|
-
|
|
1657
|
+
closeRl();
|
|
1578
1658
|
process.exit(1);
|
|
1579
1659
|
}
|
|
1580
1660
|
|
|
@@ -1694,7 +1774,7 @@ async function main() {
|
|
|
1694
1774
|
}
|
|
1695
1775
|
|
|
1696
1776
|
// 7. 更新工作目录 .gitignore
|
|
1697
|
-
updateGitignore();
|
|
1777
|
+
updateGitignore(workspaceRoot);
|
|
1698
1778
|
|
|
1699
1779
|
// 8. 收尾:无论前面是否走过 symlink/旧副本路径,强制清掉工作区/Git 根多余 skywalk-sdd/
|
|
1700
1780
|
if (specPackage && fs.existsSync(specPackage.abs)) {
|
|
@@ -1750,23 +1830,23 @@ async function main() {
|
|
|
1750
1830
|
}
|
|
1751
1831
|
console.log();
|
|
1752
1832
|
|
|
1753
|
-
// 统一的 skill
|
|
1754
|
-
console.log('可用 skills
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1833
|
+
// 统一的 skill 格式说明(默认单行指引,完整列表走 --verbose)
|
|
1834
|
+
console.log('可用 skills:opsx-* 系列 15 个 SDD skills(--verbose 查看完整列表,或见 openspec/kld-sdd操作手册.html)');
|
|
1835
|
+
vlog(' opsx-propose - 创建业务意图文档(Why)');
|
|
1836
|
+
vlog(' opsx-spec - 创建技术契约文档(What)');
|
|
1837
|
+
vlog(' opsx-design - 创建技术实现方案(How)');
|
|
1838
|
+
vlog(' opsx-task - 拆解AI编码任务(Do)');
|
|
1839
|
+
vlog(' opsx-check - 质量门禁检查(Verify)');
|
|
1840
|
+
vlog(' opsx-apply - 申请变更实施(Apply)');
|
|
1841
|
+
vlog(' opsx-test - 执行单元测试(Test)');
|
|
1842
|
+
vlog(' opsx-archive - 归档变更(Archive)');
|
|
1843
|
+
vlog(' opsx-explore - 浏览变更状态(Explore)');
|
|
1844
|
+
vlog(' opsx-knowledge - 业务知识库检索(辅助)');
|
|
1845
|
+
vlog(' opsx-rules - 生成/更新 Agent 规则(辅助)');
|
|
1846
|
+
vlog(' opsx-consistency-check - Spec 一致性校验(代码 vs spec)');
|
|
1847
|
+
vlog(' opsx-kb-config - 知识库配置(API Key + Space/KB 选择)');
|
|
1848
|
+
vlog(' opsx-ontology-query - 本体知识库查询');
|
|
1849
|
+
vlog(' opsx-kb-ingest - 知识库入库(zip / 文件夹上传)');
|
|
1770
1850
|
|
|
1771
1851
|
console.log();
|
|
1772
1852
|
console.log('后续步骤:');
|
|
@@ -1782,13 +1862,13 @@ async function main() {
|
|
|
1782
1862
|
console.log(' 5. 随时入库:node skywalk-sdd/kb-upload.cjs --folder=<变更目录> --minimum-level=propose-spec');
|
|
1783
1863
|
console.log(' (需先运行 /opsx-kb-config 配置知识库)');
|
|
1784
1864
|
if (selectedTools.includes('codebuddy')) {
|
|
1785
|
-
console.log('
|
|
1865
|
+
console.log(' - CodeBuddy 用户:SDD Hook Pack 已随初始化自动部署,门禁自动生效,无需手动配置');
|
|
1786
1866
|
}
|
|
1787
1867
|
if (selectedTools.includes('kunlunzhima')) {
|
|
1788
|
-
console.log('
|
|
1868
|
+
console.log(' - KunlunZhima 用户:在 Craft 模式使用 /opsx:propose 等 OPSX 命令(.kunlunzhima/commands/opsx/)');
|
|
1789
1869
|
}
|
|
1790
1870
|
if (selectedTools.includes('opencode')) {
|
|
1791
|
-
console.log('
|
|
1871
|
+
console.log(' - OpenCode 用户:用 /opsx-propose 或 /skills 启动 SDD(.opencode/skills/opsx-*/,skill 即斜杠命令)');
|
|
1792
1872
|
}
|
|
1793
1873
|
console.log();
|
|
1794
1874
|
console.log('📊 SDD Telemetry(嵌入在 skill 流程中,自动执行,无需配置):');
|
|
@@ -1800,16 +1880,22 @@ async function main() {
|
|
|
1800
1880
|
console.log(' - 运行 node skywalk-sdd/log.cjs metrics --project=<包裹包> 查看四维度指标');
|
|
1801
1881
|
console.log();
|
|
1802
1882
|
|
|
1803
|
-
|
|
1883
|
+
closeRl();
|
|
1804
1884
|
}
|
|
1805
1885
|
|
|
1886
|
+
// kld-T06: Progress Runtime 已删除,用户级 workspace 注册函数一并移除。
|
|
1887
|
+
// 使用统计按本机 git 身份(user.name/user.email)上报,无需任何账号绑定。
|
|
1888
|
+
|
|
1806
1889
|
module.exports = {
|
|
1807
1890
|
main,
|
|
1808
1891
|
detectTools,
|
|
1809
1892
|
getTemplatePath,
|
|
1810
1893
|
getPackagePath,
|
|
1811
1894
|
selectEditor,
|
|
1895
|
+
isVerbose,
|
|
1896
|
+
vlog,
|
|
1812
1897
|
deployOpsxSkills,
|
|
1898
|
+
copyTemplatesToProject,
|
|
1813
1899
|
deployProfileArtifacts,
|
|
1814
1900
|
deploySddGuideManual,
|
|
1815
1901
|
deployModulesYaml,
|
|
@@ -1821,6 +1907,7 @@ module.exports = {
|
|
|
1821
1907
|
removeOuterSkywalk,
|
|
1822
1908
|
deployQualityGateTemplates,
|
|
1823
1909
|
deployTelemetryDataDir,
|
|
1910
|
+
updateGitignore,
|
|
1824
1911
|
attachCodeRepoLite,
|
|
1825
1912
|
syncWorkspaceRepos,
|
|
1826
1913
|
copyDirRendered,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kld-sdd",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.3",
|
|
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 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/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"
|
|
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/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/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 skywalk-sdd/usage-reporter.test.cjs skywalk-sdd/usage-reporting.test.cjs && node test/progress-package-artifact.test.cjs && node --test test/progress-package-install.e2e.cjs"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"kld",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"author": "KLD Team",
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=14.
|
|
27
|
+
"node": ">=14.18.0"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
30
|
"bin/",
|