speccore 8.3.121 → 8.3.126
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/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/about.d.ts.map +1 -1
- package/dist/commands/about.js +16 -0
- package/dist/commands/about.js.map +1 -1
- package/dist/commands/analyze.d.ts +1 -0
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +198 -70
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/change.js +14 -7
- package/dist/commands/change.js.map +1 -1
- package/dist/commands/context.js +25 -31
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +6 -1
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/done.js +29 -28
- package/dist/commands/done.js.map +1 -1
- package/dist/commands/execute.d.ts.map +1 -1
- package/dist/commands/execute.js +281 -20
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/import.js +1 -1
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +512 -28
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/iteration/create.js +1 -1
- package/dist/commands/iteration/split.d.ts.map +1 -1
- package/dist/commands/iteration/split.js +158 -70
- package/dist/commands/iteration/split.js.map +1 -1
- package/dist/commands/iteration-from-global.js +1 -2
- package/dist/commands/iteration-from-global.js.map +1 -1
- package/dist/commands/pattern.js +30 -16
- package/dist/commands/pattern.js.map +1 -1
- package/dist/commands/pipeline.d.ts.map +1 -1
- package/dist/commands/pipeline.js +15 -4
- package/dist/commands/pipeline.js.map +1 -1
- package/dist/commands/retro.d.ts.map +1 -1
- package/dist/commands/retro.js +15 -8
- package/dist/commands/retro.js.map +1 -1
- package/dist/commands/status-panel.js +1 -1
- package/dist/commands/status-panel.js.map +1 -1
- package/dist/commands/sync.js +15 -8
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/trace.js +27 -24
- package/dist/commands/trace.js.map +1 -1
- package/dist/commands/update-env-configs.d.ts.map +1 -1
- package/dist/commands/update-env-configs.js +33 -5
- package/dist/commands/update-env-configs.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +29 -0
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/verify.d.ts +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +25 -0
- package/dist/commands/verify.js.map +1 -1
- package/dist/core/ai-context-generator.js +35 -22
- package/dist/core/ai-context-generator.js.map +1 -1
- package/dist/core/ai-impact-analyzer.d.ts.map +1 -1
- package/dist/core/ai-impact-analyzer.js +1 -1
- package/dist/core/ai-impact-analyzer.js.map +1 -1
- package/dist/core/analyze-engine.d.ts +2 -1
- package/dist/core/analyze-engine.d.ts.map +1 -1
- package/dist/core/analyze-engine.js +217 -53
- package/dist/core/analyze-engine.js.map +1 -1
- package/dist/core/ask-engine.d.ts.map +1 -1
- package/dist/core/ask-engine.js +31 -13
- package/dist/core/ask-engine.js.map +1 -1
- package/dist/core/change-detection.d.ts.map +1 -1
- package/dist/core/change-detection.js +21 -5
- package/dist/core/change-detection.js.map +1 -1
- package/dist/core/code-scanner.d.ts +12 -3
- package/dist/core/code-scanner.d.ts.map +1 -1
- package/dist/core/code-scanner.js +376 -10
- package/dist/core/code-scanner.js.map +1 -1
- package/dist/core/context-builder.d.ts +2 -1
- package/dist/core/context-builder.d.ts.map +1 -1
- package/dist/core/context-builder.js +104 -25
- package/dist/core/context-builder.js.map +1 -1
- package/dist/core/deploy/engine.d.ts.map +1 -1
- package/dist/core/deploy/engine.js +21 -6
- package/dist/core/deploy/engine.js.map +1 -1
- package/dist/core/git-integration.d.ts +5 -1
- package/dist/core/git-integration.d.ts.map +1 -1
- package/dist/core/git-integration.js +52 -15
- package/dist/core/git-integration.js.map +1 -1
- package/dist/core/knowledge-graph.d.ts +2 -0
- package/dist/core/knowledge-graph.d.ts.map +1 -1
- package/dist/core/knowledge-graph.js +246 -232
- package/dist/core/knowledge-graph.js.map +1 -1
- package/dist/core/name-validator.js +1 -1
- package/dist/core/name-validator.js.map +1 -1
- package/dist/core/pipeline-test.d.ts.map +1 -1
- package/dist/core/pipeline-test.js +7 -4
- package/dist/core/pipeline-test.js.map +1 -1
- package/dist/core/prompt-builder.d.ts +3 -0
- package/dist/core/prompt-builder.d.ts.map +1 -1
- package/dist/core/prompt-builder.js +629 -77
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/rag-engine.d.ts +10 -5
- package/dist/core/rag-engine.d.ts.map +1 -1
- package/dist/core/rag-engine.js +134 -16
- package/dist/core/rag-engine.js.map +1 -1
- package/dist/core/spec-paths.d.ts +42 -2
- package/dist/core/spec-paths.d.ts.map +1 -1
- package/dist/core/spec-paths.js +207 -11
- package/dist/core/spec-paths.js.map +1 -1
- package/dist/core/structured-extractor.d.ts +67 -0
- package/dist/core/structured-extractor.d.ts.map +1 -1
- package/dist/core/structured-extractor.js +1298 -23
- package/dist/core/structured-extractor.js.map +1 -1
- package/dist/core/test-config.d.ts +1 -1
- package/dist/core/test-config.d.ts.map +1 -1
- package/dist/core/test-config.js +85 -65
- package/dist/core/test-config.js.map +1 -1
- package/dist/core/ui-verify/report-generator.d.ts.map +1 -1
- package/dist/core/ui-verify/report-generator.js +7 -3
- package/dist/core/ui-verify/report-generator.js.map +1 -1
- package/dist/core/ui-verify/smoke-engine.js +7 -1
- package/dist/core/ui-verify/smoke-engine.js.map +1 -1
- package/dist/core/unified-config.d.ts +43 -3
- package/dist/core/unified-config.d.ts.map +1 -1
- package/dist/core/unified-config.js +133 -13
- package/dist/core/unified-config.js.map +1 -1
- package/dist/core/unified-retrieval.d.ts.map +1 -1
- package/dist/core/unified-retrieval.js +41 -15
- package/dist/core/unified-retrieval.js.map +1 -1
- package/dist/core/unit-context-assembler.js +2 -2
- package/dist/core/unit-context-assembler.js.map +1 -1
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +59 -44
- package/dist/core/validator.js.map +1 -1
- package/dist/core/verify-engine.d.ts +9 -2
- package/dist/core/verify-engine.d.ts.map +1 -1
- package/dist/core/verify-engine.js +274 -108
- package/dist/core/verify-engine.js.map +1 -1
- package/dist/core/verify-report-aggregator.js +9 -20
- package/dist/core/verify-report-aggregator.js.map +1 -1
- package/dist/utils/synonyms.d.ts +24 -0
- package/dist/utils/synonyms.d.ts.map +1 -0
- package/dist/utils/synonyms.js +114 -0
- package/dist/utils/synonyms.js.map +1 -0
- package/package.json +1 -1
|
@@ -55,23 +55,68 @@ const logger_1 = require("../utils/logger");
|
|
|
55
55
|
// v6.84.0+: AGENTS 引擎集成
|
|
56
56
|
const agents_1 = require("./agents");
|
|
57
57
|
const spec_skeleton_1 = require("./spec-skeleton");
|
|
58
|
+
// v8.3.125+: 同义词扩展,避免 "登录" 与 "auth" 等跨语言/缩写不匹配导致验证漏检
|
|
59
|
+
const synonyms_1 = require("../utils/synonyms");
|
|
58
60
|
// ============================================================
|
|
59
61
|
// 项目类型检测
|
|
60
62
|
// ============================================================
|
|
63
|
+
/**
|
|
64
|
+
* v8.3.105+: 支持更多工程类型,检测顺序从具体到一般
|
|
65
|
+
*/
|
|
61
66
|
async function detectProjectType(codePath) {
|
|
67
|
+
// 1. Flutter(有 pubspec.yaml,且通常包含 android/ios 目录)
|
|
68
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'pubspec.yaml')))
|
|
69
|
+
return 'flutter';
|
|
70
|
+
// 2. iOS(Podfile / .xcodeproj / .xcworkspace)
|
|
71
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'Podfile')))
|
|
72
|
+
return 'ios';
|
|
73
|
+
try {
|
|
74
|
+
const files = await (0, fs_extra_1.readdir)(codePath);
|
|
75
|
+
if (files.some(f => f.endsWith('.xcodeproj') || f.endsWith('.xcworkspace')))
|
|
76
|
+
return 'ios';
|
|
77
|
+
}
|
|
78
|
+
catch { /* ignore */ }
|
|
79
|
+
// 3. Android(AndroidManifest.xml 或 app/build.gradle)
|
|
80
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'AndroidManifest.xml')))
|
|
81
|
+
return 'android';
|
|
82
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'app', 'build.gradle')))
|
|
83
|
+
return 'android';
|
|
84
|
+
// 4. Rust
|
|
85
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'Cargo.toml')))
|
|
86
|
+
return 'rust';
|
|
87
|
+
// 5. C#(.csproj 或 .sln)
|
|
88
|
+
try {
|
|
89
|
+
const files = await (0, fs_extra_1.readdir)(codePath);
|
|
90
|
+
if (files.some(f => f.endsWith('.csproj')))
|
|
91
|
+
return 'csharp';
|
|
92
|
+
if (files.some(f => f.endsWith('.sln')))
|
|
93
|
+
return 'csharp';
|
|
94
|
+
}
|
|
95
|
+
catch { /* ignore */ }
|
|
96
|
+
// 6. Node.js
|
|
62
97
|
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'package.json')))
|
|
63
98
|
return 'node';
|
|
99
|
+
// 7. Java(pom.xml / build.gradle,但无 Android 特征)
|
|
64
100
|
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'pom.xml')))
|
|
65
101
|
return 'java';
|
|
66
|
-
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'build.gradle')) || await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'build.gradle.kts')))
|
|
102
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'build.gradle')) || await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'build.gradle.kts'))) {
|
|
103
|
+
// 再次确认不是 Android(前面已检测过 AndroidManifest.xml 和 app/build.gradle)
|
|
67
104
|
return 'java';
|
|
105
|
+
}
|
|
106
|
+
// 8. Go
|
|
68
107
|
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'go.mod')))
|
|
69
108
|
return 'go';
|
|
109
|
+
// 9. Python
|
|
70
110
|
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'requirements.txt')) || await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'setup.py')) || await (0, fs_extra_1.pathExists)((0, path_1.join)(codePath, 'pyproject.toml')))
|
|
71
111
|
return 'python';
|
|
72
112
|
return 'unknown';
|
|
73
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* v8.3.105+: 获取跨平台的验证命令
|
|
116
|
+
* 去掉 2>&1 和 || true,因为 runCheck 的 execSync 已捕获输出和异常
|
|
117
|
+
*/
|
|
74
118
|
function getCommands(projectType, codePath) {
|
|
119
|
+
const isWin = process.platform === 'win32';
|
|
75
120
|
switch (projectType) {
|
|
76
121
|
case 'node':
|
|
77
122
|
return {
|
|
@@ -79,23 +124,57 @@ function getCommands(projectType, codePath) {
|
|
|
79
124
|
lint: detectNodeLintCommand(codePath),
|
|
80
125
|
test: detectNodeTestCommand(codePath),
|
|
81
126
|
};
|
|
82
|
-
case 'java':
|
|
127
|
+
case 'java': {
|
|
128
|
+
const mvnw = isWin ? 'mvnw.cmd' : './mvnw';
|
|
83
129
|
return {
|
|
84
|
-
compile:
|
|
85
|
-
lint: 'mvn checkstyle:check -q
|
|
86
|
-
test:
|
|
130
|
+
compile: `mvn compile -q || ${mvnw} compile -q`,
|
|
131
|
+
lint: 'mvn checkstyle:check -q',
|
|
132
|
+
test: `mvn test -q || ${mvnw} test -q`,
|
|
87
133
|
};
|
|
134
|
+
}
|
|
88
135
|
case 'go':
|
|
89
136
|
return {
|
|
90
|
-
compile: 'go build ./...
|
|
91
|
-
lint: 'golangci-lint run
|
|
92
|
-
test: 'go test ./... -v
|
|
137
|
+
compile: 'go build ./...',
|
|
138
|
+
lint: 'golangci-lint run',
|
|
139
|
+
test: 'go test ./... -v',
|
|
93
140
|
};
|
|
94
141
|
case 'python':
|
|
95
142
|
return {
|
|
96
|
-
compile: '
|
|
97
|
-
lint: 'flake8 .
|
|
98
|
-
test: 'pytest -v
|
|
143
|
+
compile: 'python3 -m compileall . -q || python -m compileall . -q',
|
|
144
|
+
lint: 'flake8 . || pylint . || ruff check .',
|
|
145
|
+
test: 'pytest -v || python -m pytest -v',
|
|
146
|
+
};
|
|
147
|
+
case 'android': {
|
|
148
|
+
const gradlew = isWin ? 'gradlew.bat' : './gradlew';
|
|
149
|
+
return {
|
|
150
|
+
compile: `${gradlew} assembleDebug`,
|
|
151
|
+
lint: `${gradlew} lint`,
|
|
152
|
+
test: `${gradlew} test`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
case 'ios':
|
|
156
|
+
return {
|
|
157
|
+
compile: 'xcodebuild build',
|
|
158
|
+
lint: null, // iOS 无标准 lint 工具
|
|
159
|
+
test: 'xcodebuild test',
|
|
160
|
+
};
|
|
161
|
+
case 'flutter':
|
|
162
|
+
return {
|
|
163
|
+
compile: 'flutter build apk',
|
|
164
|
+
lint: 'flutter analyze',
|
|
165
|
+
test: 'flutter test',
|
|
166
|
+
};
|
|
167
|
+
case 'rust':
|
|
168
|
+
return {
|
|
169
|
+
compile: 'cargo build',
|
|
170
|
+
lint: 'cargo clippy',
|
|
171
|
+
test: 'cargo test',
|
|
172
|
+
};
|
|
173
|
+
case 'csharp':
|
|
174
|
+
return {
|
|
175
|
+
compile: 'dotnet build',
|
|
176
|
+
lint: 'dotnet format --verify-no-changes',
|
|
177
|
+
test: 'dotnet test',
|
|
99
178
|
};
|
|
100
179
|
default:
|
|
101
180
|
return { compile: null, lint: null, test: null };
|
|
@@ -253,14 +332,103 @@ ${check.output.slice(0, 3000)}
|
|
|
253
332
|
// ============================================================
|
|
254
333
|
// 主入口
|
|
255
334
|
// ============================================================
|
|
335
|
+
/**
|
|
336
|
+
* v8.3.105+: 从 CONSTITUTION.md 工程类型字符串推断 ProjectType
|
|
337
|
+
*/
|
|
338
|
+
function inferProjectTypeFromConstitution(typeStr) {
|
|
339
|
+
const t = typeStr.toLowerCase();
|
|
340
|
+
if (t.includes('java'))
|
|
341
|
+
return 'java';
|
|
342
|
+
if (t.includes('node') || t.includes('前端') || t.includes('h5') || t.includes('web') || t.includes('小程序'))
|
|
343
|
+
return 'node';
|
|
344
|
+
if (t.includes('go'))
|
|
345
|
+
return 'go';
|
|
346
|
+
if (t.includes('python'))
|
|
347
|
+
return 'python';
|
|
348
|
+
if (t.includes('android'))
|
|
349
|
+
return 'android';
|
|
350
|
+
if (t.includes('ios'))
|
|
351
|
+
return 'ios';
|
|
352
|
+
if (t.includes('flutter'))
|
|
353
|
+
return 'flutter';
|
|
354
|
+
if (t.includes('rust'))
|
|
355
|
+
return 'rust';
|
|
356
|
+
if (t.includes('csharp') || t.includes('c#') || t.includes('.net'))
|
|
357
|
+
return 'csharp';
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* v8.3.105+: 检查前端构建产物
|
|
362
|
+
*/
|
|
363
|
+
async function runArtifactCheck(codePath, projectType) {
|
|
364
|
+
const start = Date.now();
|
|
365
|
+
// 确定期望的产物目录
|
|
366
|
+
let expectedDirs = [];
|
|
367
|
+
switch (projectType) {
|
|
368
|
+
case 'node':
|
|
369
|
+
expectedDirs = ['dist', 'build', 'out'];
|
|
370
|
+
break;
|
|
371
|
+
case 'java':
|
|
372
|
+
expectedDirs = ['target', (0, path_1.join)('build', 'libs')];
|
|
373
|
+
break;
|
|
374
|
+
case 'android':
|
|
375
|
+
expectedDirs = [(0, path_1.join)('app', 'build', 'outputs')];
|
|
376
|
+
break;
|
|
377
|
+
case 'flutter':
|
|
378
|
+
expectedDirs = [(0, path_1.join)('build', 'app', 'outputs')];
|
|
379
|
+
break;
|
|
380
|
+
default:
|
|
381
|
+
return { name: '产物检查', status: 'skip', duration: 0, output: '', details: '该类型暂不支持产物检查', blocking: false };
|
|
382
|
+
}
|
|
383
|
+
for (const dir of expectedDirs) {
|
|
384
|
+
const fullPath = (0, path_1.join)(codePath, dir);
|
|
385
|
+
if (await (0, fs_extra_1.pathExists)(fullPath)) {
|
|
386
|
+
const duration = Date.now() - start;
|
|
387
|
+
return { name: '产物检查', status: 'pass', duration, output: '', details: `发现产物目录: ${dir}`, blocking: false };
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
const duration = Date.now() - start;
|
|
391
|
+
return {
|
|
392
|
+
name: '产物检查',
|
|
393
|
+
status: 'warn',
|
|
394
|
+
duration,
|
|
395
|
+
output: `未在以下路径找到产物目录: ${expectedDirs.map(d => (0, path_1.join)(codePath, d)).join(', ')}`,
|
|
396
|
+
details: '未找到构建产物(需先执行构建)',
|
|
397
|
+
blocking: false,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
256
400
|
async function runVerification(taskId, codePath, options) {
|
|
257
401
|
const checkType = options?.type || 'all';
|
|
258
402
|
const timeout = options?.timeout || 120000;
|
|
259
403
|
logger_1.logger.info(`🔍 开始验证: ${taskId}`);
|
|
260
404
|
logger_1.logger.info(` 代码路径: ${codePath}`);
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
|
|
405
|
+
// v8.3.105+: 项目类型解析优先级:显式传入 > CONSTITUTION.md > 自动检测
|
|
406
|
+
let projectType = 'unknown';
|
|
407
|
+
if (options?.projectType) {
|
|
408
|
+
projectType = options.projectType;
|
|
409
|
+
logger_1.logger.info(` 项目类型: ${projectType}(显式指定)`);
|
|
410
|
+
}
|
|
411
|
+
else if (options?.platformName) {
|
|
412
|
+
// 尝试从 CONSTITUTION.md 读取工程类型
|
|
413
|
+
try {
|
|
414
|
+
const { parsePlatformTypes } = await Promise.resolve().then(() => __importStar(require('./spec-paths')));
|
|
415
|
+
const typeMap = await parsePlatformTypes();
|
|
416
|
+
const constitutionType = typeMap.get(options.platformName);
|
|
417
|
+
if (constitutionType) {
|
|
418
|
+
const inferred = inferProjectTypeFromConstitution(constitutionType);
|
|
419
|
+
if (inferred) {
|
|
420
|
+
projectType = inferred;
|
|
421
|
+
logger_1.logger.info(` 项目类型: ${projectType}(来自 CONSTITUTION.md: ${constitutionType})`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch { /* ignore */ }
|
|
426
|
+
}
|
|
427
|
+
// 如果还没确定,自动检测
|
|
428
|
+
if (projectType === 'unknown') {
|
|
429
|
+
projectType = await detectProjectType(codePath);
|
|
430
|
+
logger_1.logger.info(` 项目类型: ${projectType}(自动检测)`);
|
|
431
|
+
}
|
|
264
432
|
if (projectType === 'unknown') {
|
|
265
433
|
logger_1.logger.warn(' 未识别项目类型,跳过验证');
|
|
266
434
|
return {
|
|
@@ -295,6 +463,13 @@ async function runVerification(taskId, codePath, options) {
|
|
|
295
463
|
checks.push(result);
|
|
296
464
|
logger_1.logger.info(` ${result.status === 'pass' ? '✅' : result.status === 'fail' ? '❌' : '⏭️'} ${result.details} (${(result.duration / 1000).toFixed(1)}s)`);
|
|
297
465
|
}
|
|
466
|
+
// v8.3.105+: 产物检查
|
|
467
|
+
if (checkType === 'all' || checkType === 'artifact') {
|
|
468
|
+
logger_1.logger.info(' 📦 产物检查...');
|
|
469
|
+
const result = await runArtifactCheck(codePath, projectType);
|
|
470
|
+
checks.push(result);
|
|
471
|
+
logger_1.logger.info(` ${result.status === 'pass' ? '✅' : result.status === 'fail' ? '❌' : '⏭️'} ${result.details} (${(result.duration / 1000).toFixed(1)}s)`);
|
|
472
|
+
}
|
|
298
473
|
// 汇总
|
|
299
474
|
const report = {
|
|
300
475
|
taskId,
|
|
@@ -348,8 +523,8 @@ async function generateFixPrompt(report, taskDir) {
|
|
|
348
523
|
}
|
|
349
524
|
// ── v8.2.0+: 注入知识图谱上下文(依赖链 + 相邻任务) ──
|
|
350
525
|
try {
|
|
351
|
-
const {
|
|
352
|
-
const graph = await
|
|
526
|
+
const { loadFreshKnowledgeGraph, traceDependencyChain } = await Promise.resolve().then(() => __importStar(require('./knowledge-graph')));
|
|
527
|
+
const graph = await loadFreshKnowledgeGraph(process.cwd());
|
|
353
528
|
if (graph && report.taskId) {
|
|
354
529
|
const chains = traceDependencyChain(graph, report.taskId, 2);
|
|
355
530
|
if (chains.length > 0) {
|
|
@@ -743,26 +918,23 @@ async function checkTestCoverage(codePath, taskDir) {
|
|
|
743
918
|
const testPaths = [
|
|
744
919
|
(0, path_1.join)(taskDir, 'TEST.md'),
|
|
745
920
|
];
|
|
746
|
-
//
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
testPaths.push((0, path_1.join)(catPath, svc.name, sub.name, 'TEST.md'));
|
|
760
|
-
}
|
|
761
|
-
}
|
|
921
|
+
// v8.3.121+: 端平铺结构,直接扫描 taskDir 下的端目录(排除非端目录)
|
|
922
|
+
const EXCLUDE_DIRS = new Set(['00-specs', '_shared', '99-artifacts', '.meta']);
|
|
923
|
+
try {
|
|
924
|
+
const platformEntries = await (0, fs_extra_1.readdir)(taskDir, { withFileTypes: true });
|
|
925
|
+
for (const pe of platformEntries) {
|
|
926
|
+
if (!pe.isDirectory() || EXCLUDE_DIRS.has(pe.name))
|
|
927
|
+
continue;
|
|
928
|
+
const platformPath = (0, path_1.join)(taskDir, pe.name);
|
|
929
|
+
const subtaskEntries = await (0, fs_extra_1.readdir)(platformPath, { withFileTypes: true });
|
|
930
|
+
for (const sub of subtaskEntries) {
|
|
931
|
+
if (!sub.isDirectory())
|
|
932
|
+
continue;
|
|
933
|
+
testPaths.push((0, path_1.join)(platformPath, sub.name, 'TEST.md'));
|
|
762
934
|
}
|
|
763
|
-
catch { /* 跳过 */ }
|
|
764
935
|
}
|
|
765
936
|
}
|
|
937
|
+
catch { /* 跳过 */ }
|
|
766
938
|
// 旧结构回退
|
|
767
939
|
testPaths.push((0, path_1.join)(taskDir, '99-artifacts', 'TEST.md'));
|
|
768
940
|
let testContent = '';
|
|
@@ -787,7 +959,9 @@ async function checkTestCoverage(codePath, taskDir) {
|
|
|
787
959
|
...(c.match(/[\u4e00-\u9fa5]{2,}/g) || []),
|
|
788
960
|
...(c.match(/[a-zA-Z]{3,}/g) || []),
|
|
789
961
|
];
|
|
790
|
-
|
|
962
|
+
// v8.3.125+: 同义词扩展,避免 "登录" 与 "auth" 不匹配导致漏检
|
|
963
|
+
const expandedKws = [...(0, synonyms_1.expandSynonyms)(keywords)];
|
|
964
|
+
const found = expandedKws.some(kw => allCode.toLowerCase().includes(kw.toLowerCase()));
|
|
791
965
|
if (found)
|
|
792
966
|
covered.push(c);
|
|
793
967
|
else
|
|
@@ -820,26 +994,23 @@ async function checkReviewCompliance(codePath, taskDir) {
|
|
|
820
994
|
const reviewPaths = [
|
|
821
995
|
(0, path_1.join)(taskDir, 'REVIEW.md'),
|
|
822
996
|
];
|
|
823
|
-
//
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
reviewPaths.push((0, path_1.join)(catPath, svc.name, sub.name, 'REVIEW.md'));
|
|
837
|
-
}
|
|
838
|
-
}
|
|
997
|
+
// v8.3.121+: 端平铺结构,直接扫描 taskDir 下的端目录
|
|
998
|
+
const EXCLUDE_DIRS = new Set(['00-specs', '_shared', '99-artifacts', '.meta']);
|
|
999
|
+
try {
|
|
1000
|
+
const platformEntries = await (0, fs_extra_1.readdir)(taskDir, { withFileTypes: true });
|
|
1001
|
+
for (const pe of platformEntries) {
|
|
1002
|
+
if (!pe.isDirectory() || EXCLUDE_DIRS.has(pe.name))
|
|
1003
|
+
continue;
|
|
1004
|
+
const platformPath = (0, path_1.join)(taskDir, pe.name);
|
|
1005
|
+
const subtaskEntries = await (0, fs_extra_1.readdir)(platformPath, { withFileTypes: true });
|
|
1006
|
+
for (const sub of subtaskEntries) {
|
|
1007
|
+
if (!sub.isDirectory())
|
|
1008
|
+
continue;
|
|
1009
|
+
reviewPaths.push((0, path_1.join)(platformPath, sub.name, 'REVIEW.md'));
|
|
839
1010
|
}
|
|
840
|
-
catch { /* 跳过 */ }
|
|
841
1011
|
}
|
|
842
1012
|
}
|
|
1013
|
+
catch { /* 跳过 */ }
|
|
843
1014
|
// 旧结构回退
|
|
844
1015
|
reviewPaths.push((0, path_1.join)(taskDir, '99-artifacts', 'REVIEW.md'));
|
|
845
1016
|
let reviewContent = '';
|
|
@@ -864,7 +1035,9 @@ async function checkReviewCompliance(codePath, taskDir) {
|
|
|
864
1035
|
...(item.match(/[\u4e00-\u9fa5]{2,}/g) || []),
|
|
865
1036
|
...(item.match(/[a-zA-Z]{3,}/g) || []),
|
|
866
1037
|
];
|
|
867
|
-
|
|
1038
|
+
// v8.3.125+: 同义词扩展
|
|
1039
|
+
const expandedKws = [...(0, synonyms_1.expandSynonyms)(keywords)];
|
|
1040
|
+
const found = expandedKws.some(kw => allCode.toLowerCase().includes(kw.toLowerCase()));
|
|
868
1041
|
if (found)
|
|
869
1042
|
passed.push(item);
|
|
870
1043
|
else
|
|
@@ -897,26 +1070,23 @@ async function checkArtifactConsistency(codePath, taskDir, filename, checkName)
|
|
|
897
1070
|
const filePaths = [
|
|
898
1071
|
(0, path_1.join)(taskDir, filename),
|
|
899
1072
|
];
|
|
900
|
-
//
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
filePaths.push((0, path_1.join)(catPath, svc.name, sub.name, filename));
|
|
914
|
-
}
|
|
915
|
-
}
|
|
1073
|
+
// v8.3.121+: 端平铺结构,直接扫描 taskDir 下的端目录
|
|
1074
|
+
const EXCLUDE_DIRS = new Set(['00-specs', '_shared', '99-artifacts', '.meta']);
|
|
1075
|
+
try {
|
|
1076
|
+
const platformEntries = await (0, fs_extra_1.readdir)(taskDir, { withFileTypes: true });
|
|
1077
|
+
for (const pe of platformEntries) {
|
|
1078
|
+
if (!pe.isDirectory() || EXCLUDE_DIRS.has(pe.name))
|
|
1079
|
+
continue;
|
|
1080
|
+
const platformPath = (0, path_1.join)(taskDir, pe.name);
|
|
1081
|
+
const subtaskEntries = await (0, fs_extra_1.readdir)(platformPath, { withFileTypes: true });
|
|
1082
|
+
for (const sub of subtaskEntries) {
|
|
1083
|
+
if (!sub.isDirectory())
|
|
1084
|
+
continue;
|
|
1085
|
+
filePaths.push((0, path_1.join)(platformPath, sub.name, filename));
|
|
916
1086
|
}
|
|
917
|
-
catch { /* 跳过 */ }
|
|
918
1087
|
}
|
|
919
1088
|
}
|
|
1089
|
+
catch { /* 跳过 */ }
|
|
920
1090
|
// 旧结构回退
|
|
921
1091
|
filePaths.push((0, path_1.join)(taskDir, '99-artifacts', filename));
|
|
922
1092
|
let content = '';
|
|
@@ -941,7 +1111,9 @@ async function checkArtifactConsistency(codePath, taskDir, filename, checkName)
|
|
|
941
1111
|
...(item.match(/[\u4e00-\u9fa5]{2,}/g) || []),
|
|
942
1112
|
...(item.match(/[a-zA-Z]{3,}/g) || []),
|
|
943
1113
|
];
|
|
944
|
-
|
|
1114
|
+
// v8.3.125+: 同义词扩展
|
|
1115
|
+
const expandedKws = [...(0, synonyms_1.expandSynonyms)(keywords)];
|
|
1116
|
+
const found = expandedKws.some(kw => allCode.toLowerCase().includes(kw.toLowerCase()));
|
|
945
1117
|
if (found)
|
|
946
1118
|
matched.push(item);
|
|
947
1119
|
else
|
|
@@ -1217,8 +1389,8 @@ async function checkSchemaConsistency(codePath, taskDir) {
|
|
|
1217
1389
|
async function checkDependencyGraphConsistency(codePath, taskDir, taskId) {
|
|
1218
1390
|
const start = Date.now();
|
|
1219
1391
|
try {
|
|
1220
|
-
const {
|
|
1221
|
-
const graph = await
|
|
1392
|
+
const { loadFreshKnowledgeGraph, traceDependencyChain } = await Promise.resolve().then(() => __importStar(require('./knowledge-graph')));
|
|
1393
|
+
const graph = await loadFreshKnowledgeGraph(process.cwd());
|
|
1222
1394
|
if (!graph) {
|
|
1223
1395
|
return { name: '依赖一致性', status: 'skip', duration: Date.now() - start, output: '', details: '知识图谱未加载', blocking: false };
|
|
1224
1396
|
}
|
|
@@ -1480,30 +1652,27 @@ async function checkSpecDocQuality(taskDir) {
|
|
|
1480
1652
|
if (await (0, fs_extra_1.pathExists)(p))
|
|
1481
1653
|
specFiles.push({ path: p, docName: doc });
|
|
1482
1654
|
}
|
|
1483
|
-
//
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1655
|
+
// v8.3.121+: 端平铺结构,直接扫描 taskDir 下的端目录
|
|
1656
|
+
const EXCLUDE_DIRS = new Set(['00-specs', '_shared', '99-artifacts', '.meta']);
|
|
1657
|
+
try {
|
|
1658
|
+
const platformEntries = await (0, fs_extra_1.readdir)(taskDir, { withFileTypes: true });
|
|
1659
|
+
for (const pe of platformEntries) {
|
|
1660
|
+
if (!pe.isDirectory() || EXCLUDE_DIRS.has(pe.name))
|
|
1661
|
+
continue;
|
|
1662
|
+
const platformPath = (0, path_1.join)(taskDir, pe.name);
|
|
1663
|
+
const subtaskEntries = await (0, fs_extra_1.readdir)(platformPath, { withFileTypes: true });
|
|
1664
|
+
for (const sub of subtaskEntries) {
|
|
1665
|
+
if (!sub.isDirectory())
|
|
1492
1666
|
continue;
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
if (
|
|
1496
|
-
|
|
1497
|
-
for (const doc of candidates) {
|
|
1498
|
-
const p = (0, path_1.join)(catPath, svc.name, sub.name, doc);
|
|
1499
|
-
if (await (0, fs_extra_1.pathExists)(p))
|
|
1500
|
-
specFiles.push({ path: p, docName: doc });
|
|
1501
|
-
}
|
|
1667
|
+
for (const doc of candidates) {
|
|
1668
|
+
const p = (0, path_1.join)(platformPath, sub.name, doc);
|
|
1669
|
+
if (await (0, fs_extra_1.pathExists)(p))
|
|
1670
|
+
specFiles.push({ path: p, docName: doc });
|
|
1502
1671
|
}
|
|
1503
1672
|
}
|
|
1504
1673
|
}
|
|
1505
|
-
catch { /* 跳过 */ }
|
|
1506
1674
|
}
|
|
1675
|
+
catch { /* 跳过 */ }
|
|
1507
1676
|
if (specFiles.length === 0) {
|
|
1508
1677
|
return {
|
|
1509
1678
|
name: '规格文档质量',
|
|
@@ -1594,26 +1763,23 @@ async function syncTestDocFromResults(taskDir, testPassed) {
|
|
|
1594
1763
|
(0, path_1.join)(taskDir, 'TEST.md'),
|
|
1595
1764
|
(0, path_1.join)(taskDir, '99-artifacts', 'TEST.md'),
|
|
1596
1765
|
];
|
|
1597
|
-
//
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
testPaths.push((0, path_1.join)(catPath, svc.name, sub.name, 'TEST.md'));
|
|
1611
|
-
}
|
|
1612
|
-
}
|
|
1766
|
+
// v8.3.121+: 端平铺结构,直接扫描 taskDir 下的端目录
|
|
1767
|
+
const EXCLUDE_DIRS = new Set(['00-specs', '_shared', '99-artifacts', '.meta']);
|
|
1768
|
+
try {
|
|
1769
|
+
const platformEntries = await (0, fs_extra_1.readdir)(taskDir, { withFileTypes: true });
|
|
1770
|
+
for (const pe of platformEntries) {
|
|
1771
|
+
if (!pe.isDirectory() || EXCLUDE_DIRS.has(pe.name))
|
|
1772
|
+
continue;
|
|
1773
|
+
const platformPath = (0, path_1.join)(taskDir, pe.name);
|
|
1774
|
+
const subtaskEntries = await (0, fs_extra_1.readdir)(platformPath, { withFileTypes: true });
|
|
1775
|
+
for (const sub of subtaskEntries) {
|
|
1776
|
+
if (!sub.isDirectory())
|
|
1777
|
+
continue;
|
|
1778
|
+
testPaths.push((0, path_1.join)(platformPath, sub.name, 'TEST.md'));
|
|
1613
1779
|
}
|
|
1614
|
-
catch { /* 跳过 */ }
|
|
1615
1780
|
}
|
|
1616
1781
|
}
|
|
1782
|
+
catch { /* 跳过 */ }
|
|
1617
1783
|
for (const testPath of testPaths) {
|
|
1618
1784
|
if (!(await (0, fs_extra_1.pathExists)(testPath)))
|
|
1619
1785
|
continue;
|