kld-sdd 2.7.3 → 2.7.8
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 +12 -5
- package/USABILITY.md +84 -0
- package/kld-sdd-guide.html +16 -4
- package/lib/hook-gate-core.js +327 -0
- package/lib/init.js +221 -37
- package/lib/scale-thresholds.json +19 -0
- package/lib/skills-bundle.js +2 -1
- package/package.json +5 -3
- package/skywalk-sdd/context-client.cjs +50 -30
- package/skywalk-sdd/index.cjs +36 -16
- package/skywalk-sdd/kb-sync-identity.cjs +99 -451
- package/skywalk-sdd/kb-upload.cjs +67 -44
- package/skywalk-sdd/lib/usage-contract.cjs +3 -2
- package/skywalk-sdd/lib/usage-reporter.cjs +27 -2
- package/skywalk-sdd/metrics-v3.cjs +2 -2
- package/skywalk-sdd/ontology/active-changes.cjs +2 -1
- package/skywalk-sdd/ontology/archive-package.cjs +1 -1
- package/skywalk-sdd/ontology/artifact-parser.cjs +7 -4
- package/skywalk-sdd/ontology/id.cjs +5 -4
- package/skywalk-sdd/ontology/identity-index.cjs +4 -3
- package/skywalk-sdd/ontology/list-changes.cjs +1 -1
- package/skywalk-sdd/ontology/runtime.cjs +7 -3
- package/skywalk-sdd/ontology/schema.cjs +2 -0
- package/skywalk-sdd/ontology/traceability-validator.cjs +74 -4
- package/skywalk-sdd/ontology/workspace-layout.cjs +25 -5
- package/skywalk-sdd/reporting/change-report-model.cjs +4 -3
- package/templates/git-hooks/commit-msg +22 -21
- package/templates/git-hooks/consistency-check-core.cjs +1087 -0
- package/templates/git-hooks/hooks.config +20 -1
- package/templates/git-hooks/pre-commit +22 -21
- package/templates/git-hooks/pre-commit-consistency-check.cjs +29 -332
- package/templates/git-hooks/pre-commit-sdd-check.cjs +98 -0
- package/templates/git-hooks/pre-push +22 -21
- package/templates/git-hooks/pre-push-consistency-check.cjs +58 -406
- package/templates/hooks/codebuddy/hooks/sdd-tdd-rhythm-gate.cjs +1 -1
- package/templates/openspec/tasks.md +3 -3
- package/templates/skills/kld-sdd/opsx-apply/SKILL.md +43 -6
- package/templates/skills/kld-sdd/opsx-apply/checklist.md +1 -1
- package/templates/skills/kld-sdd/opsx-apply/reference.md +1 -1
- package/templates/skills/kld-sdd/opsx-archive/SKILL.md +9 -13
- package/templates/skills/kld-sdd/opsx-check/SKILL.md +54 -328
- package/templates/skills/kld-sdd/opsx-check/checklist.md +7 -4
- package/templates/skills/kld-sdd/opsx-check/reference.md +58 -0
- package/templates/skills/kld-sdd/opsx-check/result-template.json +52 -0
- package/templates/skills/kld-sdd/opsx-check/reviewer.md +100 -0
- package/templates/skills/kld-sdd/opsx-consistency-check/SKILL.md +82 -451
- package/templates/skills/kld-sdd/opsx-consistency-check/{reference.md → references/reference.md} +0 -1
- package/templates/skills/kld-sdd/opsx-consistency-check/scripts/scripts.cjs +517 -0
- package/templates/skills/kld-sdd/opsx-design/SKILL.md +10 -30
- package/templates/skills/kld-sdd/opsx-design/checklist.md +3 -4
- package/templates/skills/kld-sdd/opsx-design/reference.md +1 -1
- package/templates/skills/kld-sdd/opsx-kb-ingest/SKILL.md +12 -74
- package/templates/skills/kld-sdd/opsx-ontology-query/SKILL.md +7 -5
- package/templates/skills/kld-sdd/opsx-ontology-query/phase-1-prechange.md +2 -2
- package/templates/skills/kld-sdd/opsx-ontology-query/reference.md +1 -1
- package/templates/skills/kld-sdd/opsx-propose/SKILL.md +28 -73
- package/templates/skills/kld-sdd/opsx-propose/checklist.md +8 -8
- package/templates/skills/kld-sdd/opsx-propose/interaction-policy.md +28 -0
- package/templates/skills/kld-sdd/opsx-propose/reference.md +12 -46
- package/templates/skills/kld-sdd/opsx-spec/SKILL.md +14 -61
- package/templates/skills/kld-sdd/opsx-spec/checklist.md +3 -3
- package/templates/skills/kld-sdd/opsx-task/SKILL.md +38 -32
- package/templates/skills/kld-sdd/opsx-task/checklist.md +5 -6
- package/templates/skills/kld-sdd/opsx-test/SKILL.md +2 -0
- package/templates/skills/kld-sdd/tdd-rules/rules/tdd-strategy-selection.md +1 -1
package/skywalk-sdd/index.cjs
CHANGED
|
@@ -244,7 +244,7 @@ function findActiveStage(projectRoot, criteria) {
|
|
|
244
244
|
const matchingStarts = [];
|
|
245
245
|
for (const changeDir of changeDirs) {
|
|
246
246
|
const dir = path.join(eventsDir, changeDir);
|
|
247
|
-
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort().reverse();
|
|
247
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).reverse();
|
|
248
248
|
for (const file of files) {
|
|
249
249
|
const lines = fs.readFileSync(path.join(dir, file), 'utf-8').split('\n').filter(Boolean);
|
|
250
250
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -357,7 +357,7 @@ function discoverTaskFiles(projectRoot, changeName) {
|
|
|
357
357
|
return walkFiles(changeDir, filePath => {
|
|
358
358
|
const fileName = path.basename(filePath).toLowerCase();
|
|
359
359
|
return fileName === 'tasks.md' || fileName === 'task.md';
|
|
360
|
-
}).sort();
|
|
360
|
+
}).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
function checklistEntriesOutsideCodeFences(lines) {
|
|
@@ -587,7 +587,7 @@ function scanTaskCompletionForArchiveDir(projectRoot, changeName, archiveDir) {
|
|
|
587
587
|
const taskFiles = walkFiles(archiveDir, filePath => {
|
|
588
588
|
const fileName = path.basename(filePath).toLowerCase();
|
|
589
589
|
return fileName === 'tasks.md' || fileName === 'task.md';
|
|
590
|
-
}).sort();
|
|
590
|
+
}).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
591
591
|
return scanTaskCompletionFromFiles(normalizedRoot, changeName, taskFiles);
|
|
592
592
|
}
|
|
593
593
|
|
|
@@ -796,7 +796,7 @@ function collectSpecFiles(changeRoot) {
|
|
|
796
796
|
if (!changeRoot || !fs.existsSync(changeRoot)) return [];
|
|
797
797
|
const specsDir = path.join(changeRoot, 'specs');
|
|
798
798
|
if (fs.existsSync(specsDir) && fs.statSync(specsDir).isDirectory()) {
|
|
799
|
-
return walkFiles(specsDir, filePath => path.basename(filePath).toLowerCase() === 'spec.md').sort();
|
|
799
|
+
return walkFiles(specsDir, filePath => path.basename(filePath).toLowerCase() === 'spec.md').sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
800
800
|
}
|
|
801
801
|
const rootSpec = path.join(changeRoot, 'spec.md');
|
|
802
802
|
if (fs.existsSync(rootSpec)) return [rootSpec];
|
|
@@ -1503,7 +1503,7 @@ function readEventsRaw(dataDir, changeName) {
|
|
|
1503
1503
|
if (!fs.existsSync(dir)) return [];
|
|
1504
1504
|
|
|
1505
1505
|
const events = [];
|
|
1506
|
-
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort();
|
|
1506
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
1507
1507
|
for (const file of files) {
|
|
1508
1508
|
const lines = fs.readFileSync(path.join(dir, file), 'utf-8').split('\n').filter(Boolean);
|
|
1509
1509
|
for (const line of lines) {
|
|
@@ -4859,7 +4859,7 @@ function buildReport(projectRoot, events, options = {}) {
|
|
|
4859
4859
|
const scopedReport = scopeEventsForChangeReport(events, options.change);
|
|
4860
4860
|
events = scopedReport.events;
|
|
4861
4861
|
const archiveEvent = latestByTimestamp(events.filter(e => {
|
|
4862
|
-
return e.command === 'archive' && e.type === 'stage_end';
|
|
4862
|
+
return e.command === 'archive' && e.type === 'stage_end' && e.details?.archive_result;
|
|
4863
4863
|
}));
|
|
4864
4864
|
const gitCommitTimeline = resolveGitCommitTimeline(
|
|
4865
4865
|
events,
|
|
@@ -5475,7 +5475,8 @@ function cmdEnd(args, options = {}) {
|
|
|
5475
5475
|
command: args.command,
|
|
5476
5476
|
agent_type: args.agent || args['agent-type'],
|
|
5477
5477
|
};
|
|
5478
|
-
|
|
5478
|
+
// let:下方占位 change 迁移逻辑需要重新赋值 startEvent(const 会在运行时抛 TypeError)
|
|
5479
|
+
let startEvent = eventId
|
|
5479
5480
|
? searchEventInDataDir(dataDir, eventId)
|
|
5480
5481
|
: findActiveStage(projectRoot, activeCriteria);
|
|
5481
5482
|
if (!eventId && startEvent) {
|
|
@@ -5960,7 +5961,7 @@ function normalizeRepositoryRelativeFiles(files, {
|
|
|
5960
5961
|
}
|
|
5961
5962
|
normalized.push(raw);
|
|
5962
5963
|
}
|
|
5963
|
-
return [...new Set(normalized)].sort();
|
|
5964
|
+
return [...new Set(normalized)].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
5964
5965
|
}
|
|
5965
5966
|
|
|
5966
5967
|
function normalizeStrictCheckResult(details, result) {
|
|
@@ -6412,13 +6413,13 @@ function normalizeStrictTestResult(args, details) {
|
|
|
6412
6413
|
|
|
6413
6414
|
const taskId = String(args['task-id'] || args.task_id || input.task_id || '').trim();
|
|
6414
6415
|
const verifiedTaskIds = Array.isArray(input.verified_task_ids)
|
|
6415
|
-
? [...new Set(input.verified_task_ids.map(value => String(value || '').trim()).filter(Boolean))].sort()
|
|
6416
|
+
? [...new Set(input.verified_task_ids.map(value => String(value || '').trim()).filter(Boolean))].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
|
|
6416
6417
|
: [];
|
|
6417
6418
|
if (!taskId && verifiedTaskIds.length === 0) {
|
|
6418
6419
|
fail('E_STRICT_FIELD_REQUIRED: strict test_result 必须提供 task_id 或 verified_task_ids');
|
|
6419
6420
|
}
|
|
6420
6421
|
if (taskId && !verifiedTaskIds.includes(taskId)) verifiedTaskIds.push(taskId);
|
|
6421
|
-
verifiedTaskIds.sort();
|
|
6422
|
+
verifiedTaskIds.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
6422
6423
|
|
|
6423
6424
|
const normalized = {
|
|
6424
6425
|
run_id: requireStrictString(args['run-id'] || args.run_id || input.run_id, 'EVENT_RUN_ID_REQUIRED', 'run_id'),
|
|
@@ -7859,7 +7860,7 @@ function searchEventInDataDir(dataDir, eventId) {
|
|
|
7859
7860
|
|
|
7860
7861
|
for (const changeDir of changeDirs) {
|
|
7861
7862
|
const dir = path.join(eventsDir, changeDir);
|
|
7862
|
-
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort().reverse();
|
|
7863
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).reverse();
|
|
7863
7864
|
for (const file of files) {
|
|
7864
7865
|
const lines = fs.readFileSync(path.join(dir, file), 'utf-8').split('\n').filter(Boolean);
|
|
7865
7866
|
for (const line of lines) {
|
|
@@ -7885,7 +7886,7 @@ function readAllEventEndsById(dataDir, eventId, changeName) {
|
|
|
7885
7886
|
|
|
7886
7887
|
const scanDir = (dir) => {
|
|
7887
7888
|
if (!fs.existsSync(dir)) return;
|
|
7888
|
-
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort().reverse();
|
|
7889
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.jsonl')).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0)).reverse();
|
|
7889
7890
|
for (const file of files) {
|
|
7890
7891
|
const lines = fs.readFileSync(path.join(dir, file), 'utf-8').split('\n').filter(Boolean);
|
|
7891
7892
|
for (const line of lines) {
|
|
@@ -8174,18 +8175,37 @@ function cmdSemanticScan(args) {
|
|
|
8174
8175
|
|
|
8175
8176
|
function cmdSemanticReconcile(args, options = {}) {
|
|
8176
8177
|
const context = semanticCommandContext(args);
|
|
8178
|
+
const started = process.hrtime.bigint();
|
|
8177
8179
|
const result = require('./ontology/runtime.cjs').reconcileChange(
|
|
8178
8180
|
context.projectRoot,
|
|
8179
8181
|
context.changeName,
|
|
8180
8182
|
{ profile: context.profile, markPending: Boolean(options.markPending) },
|
|
8181
8183
|
);
|
|
8182
|
-
|
|
8184
|
+
const payload = semanticResultPayload(result);
|
|
8185
|
+
if (options.includeTasks) {
|
|
8186
|
+
const semanticFinished = process.hrtime.bigint();
|
|
8187
|
+
// A review packet avoids another CLI launch and a parent-agent document scan.
|
|
8188
|
+
// It is fresh input metadata, never a cached approval or a substitute for review.
|
|
8189
|
+
payload.task_completion = scanTaskCompletion(context.projectRoot, context.changeName);
|
|
8190
|
+
payload.review_inputs = {
|
|
8191
|
+
change_dir: path.join(context.projectRoot, 'openspec', 'changes', context.changeName),
|
|
8192
|
+
files: result.state.files,
|
|
8193
|
+
identity_history_hash: result.state.identity_history_hash,
|
|
8194
|
+
};
|
|
8195
|
+
const finished = process.hrtime.bigint();
|
|
8196
|
+
payload.timings_ms = {
|
|
8197
|
+
semantic: Number(semanticFinished - started) / 1e6,
|
|
8198
|
+
tasks: Number(finished - semanticFinished) / 1e6,
|
|
8199
|
+
total: Number(finished - started) / 1e6,
|
|
8200
|
+
};
|
|
8201
|
+
}
|
|
8202
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
8183
8203
|
if (!result.valid) process.exitCode = 1;
|
|
8184
8204
|
return result;
|
|
8185
8205
|
}
|
|
8186
8206
|
|
|
8187
8207
|
function cmdSemanticCheck(args) {
|
|
8188
|
-
return cmdSemanticReconcile(args, { markPending: true });
|
|
8208
|
+
return cmdSemanticReconcile(args, { markPending: true, includeTasks: Boolean(args['include-tasks']) });
|
|
8189
8209
|
}
|
|
8190
8210
|
|
|
8191
8211
|
function cmdSemanticStatus(args) {
|
|
@@ -8476,7 +8496,7 @@ SDD Telemetry CLI - 流程度量采集工具
|
|
|
8476
8496
|
node skywalk-sdd/log.cjs semantic-identity --delta-state=modified --entity-id=<uuid> --predecessor-version=<uuid>
|
|
8477
8497
|
node skywalk-sdd/log.cjs semantic-identity --delta-state=unchanged --entity-id=<uuid> --version-id=<uuid>
|
|
8478
8498
|
node skywalk-sdd/log.cjs semantic-reconcile --project=<path> --change=<name> [--profile=auto|simple|full|strict]
|
|
8479
|
-
node skywalk-sdd/log.cjs semantic-check --project=<path> --change=<name> [--profile=...]
|
|
8499
|
+
node skywalk-sdd/log.cjs semantic-check --project=<path> --change=<name> [--profile=...] [--include-tasks]
|
|
8480
8500
|
node skywalk-sdd/log.cjs semantic-status --project=<path> --change=<name>
|
|
8481
8501
|
node skywalk-sdd/log.cjs semantic-observe --project=<path> --change=<name> [--interval=1500]
|
|
8482
8502
|
|
|
@@ -8494,7 +8514,7 @@ SDD Telemetry CLI - 流程度量采集工具
|
|
|
8494
8514
|
semantic-identity 生成或复用实体/版本 ID(8 位十六进制);无需网络和中央 ID 服务
|
|
8495
8515
|
semantic-scan 只读解析并校验当前 Change
|
|
8496
8516
|
semantic-reconcile 全量对账文件与本地工作态本体实例
|
|
8497
|
-
semantic-check 全量对账并在通过时标记 pending
|
|
8517
|
+
semantic-check 全量对账并在通过时标记 pending;--include-tasks 同时返回任务状态、评审输入清单和程序耗时
|
|
8498
8518
|
semantic-status 读取当前工作态本体实例
|
|
8499
8519
|
semantic-observe 观察文件变化并同步;不提供 Hook 式控制,Check/Archive 仍会全量对账
|
|
8500
8520
|
|