speccore 8.3.180 → 8.3.182
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/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +104 -18
- package/dist/commands/analyze.js.map +1 -1
- package/dist/core/prompt-builder.d.ts.map +1 -1
- package/dist/core/prompt-builder.js +100 -16
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/requirement-clarifier.d.ts +8 -1
- package/dist/core/requirement-clarifier.d.ts.map +1 -1
- package/dist/core/requirement-clarifier.js +53 -18
- package/dist/core/requirement-clarifier.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-builder.d.ts","sourceRoot":"","sources":["../../src/core/prompt-builder.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"prompt-builder.d.ts","sourceRoot":"","sources":["../../src/core/prompt-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -410,9 +410,22 @@ async function loadExtraSpecs(cwd, taskDir, platform, iteration, options) {
|
|
|
410
410
|
if (content.trim().length <= 50 || content.trim().match(/^#+\s*待填充|^<!--\s*AI-FILL\s*-->$/m)) {
|
|
411
411
|
continue;
|
|
412
412
|
}
|
|
413
|
-
//
|
|
414
|
-
|
|
415
|
-
|
|
413
|
+
// v8.3.181+: 按文件类型细分预算
|
|
414
|
+
const fileName = (0, path_1.basename)(f.path);
|
|
415
|
+
const budget = getFileBudget(fileName);
|
|
416
|
+
if (content.length > budget.limit) {
|
|
417
|
+
if (budget.mode === 'error') {
|
|
418
|
+
logger_1.logger.error(`[prompt-builder] ${fileName} 超过预算上限 (${content.length} > ${budget.limit})。`);
|
|
419
|
+
logger_1.logger.error(` 该文件属于"必须完整"类型,不会被截断。建议精简方式:`);
|
|
420
|
+
logger_1.logger.error(` - 删除过时的注释和示例代码`);
|
|
421
|
+
logger_1.logger.error(` - 将详细说明链接到外部文档`);
|
|
422
|
+
logger_1.logger.error(` - 使用表格代替冗长的列表`);
|
|
423
|
+
logger_1.logger.error(` - 精简后重新执行: speccore execute --resume`);
|
|
424
|
+
// 不截断,保留完整内容
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
content = content.slice(0, budget.limit) + `\n\n> ... (已截断,原文件 ${rawContent.length} 字,预算上限 ${budget.limit},完整内容请 Read: ${fullPath})`;
|
|
428
|
+
}
|
|
416
429
|
}
|
|
417
430
|
// 总大小限制
|
|
418
431
|
if (totalChars + content.length > MAX_TOTAL) {
|
|
@@ -449,8 +462,10 @@ async function loadExtraSpecs(cwd, taskDir, platform, iteration, options) {
|
|
|
449
462
|
if (content.trim().length <= 50 || content.trim().match(/^#+\s*待填充|^<!--\s*AI-FILL\s*-->$/m)) {
|
|
450
463
|
continue;
|
|
451
464
|
}
|
|
452
|
-
|
|
453
|
-
|
|
465
|
+
// v8.3.181+: 自定义文件使用默认预算
|
|
466
|
+
const customBudget = getFileBudget((0, path_1.basename)(uf.path));
|
|
467
|
+
if (content.length > customBudget.limit) {
|
|
468
|
+
content = content.slice(0, customBudget.limit) + `\n\n> ... (已截断,原文件 ${content.length} 字,预算上限 ${customBudget.limit})`;
|
|
454
469
|
}
|
|
455
470
|
if (totalChars + content.length > MAX_TOTAL) {
|
|
456
471
|
const remain = MAX_TOTAL - totalChars;
|
|
@@ -523,15 +538,51 @@ async function loadExtraSpecs(cwd, taskDir, platform, iteration, options) {
|
|
|
523
538
|
return extras;
|
|
524
539
|
}
|
|
525
540
|
/**
|
|
526
|
-
* v8.3.
|
|
527
|
-
*
|
|
528
|
-
*
|
|
541
|
+
* v8.3.181+: 扫描用户自定义文档(白名单模式)
|
|
542
|
+
* 只加载 ALLOWED_EXTRA_FILES 白名单内的文件,防止上下文污染
|
|
543
|
+
* 白名单外文件将被忽略并输出提示
|
|
529
544
|
*/
|
|
545
|
+
// v8.3.182+: 白名单分两级(核心 + 条件)
|
|
546
|
+
// 核心白名单:所有任务都需要
|
|
547
|
+
const CORE_EXTRA_FILES = new Set([
|
|
548
|
+
'CONTEXT.md', // 任务上下文(来源追溯 + 关联任务)
|
|
549
|
+
'ERROR_CODES.md', // 错误码定义
|
|
550
|
+
]);
|
|
551
|
+
// 条件白名单:按平台类型加载
|
|
552
|
+
function getPlatformExtraFiles(platform) {
|
|
553
|
+
if (!platform)
|
|
554
|
+
return new Set();
|
|
555
|
+
const p = platform.toLowerCase();
|
|
556
|
+
if (p.includes('backend') || p.includes('service') || p.includes('api') || p.includes('server')) {
|
|
557
|
+
return new Set(['SCHEMA.md']);
|
|
558
|
+
}
|
|
559
|
+
if (p.includes('web') || p.includes('mobile') || p.includes('h5') || p.includes('frontend') || p.includes('admin')) {
|
|
560
|
+
return new Set(['COMPONENT_TREE.md', 'ROUTES.md', 'STATE.md']);
|
|
561
|
+
}
|
|
562
|
+
return new Set();
|
|
563
|
+
}
|
|
564
|
+
// v8.3.181+: 按文件类型细分预算(必须完整 vs 可以截断)
|
|
565
|
+
const FILE_BUDGETS = {
|
|
566
|
+
'CONSTITUTION.md': { limit: 6000, mode: 'error' },
|
|
567
|
+
'REQ.md': { limit: 2000, mode: 'error' },
|
|
568
|
+
'API_CONTRACT.yaml': { limit: 2000, mode: 'error' },
|
|
569
|
+
'TASK.md': { limit: 1500, mode: 'truncate' },
|
|
570
|
+
'TECH.md': { limit: 3000, mode: 'truncate' },
|
|
571
|
+
'DEV_GUIDE.md': { limit: 2000, mode: 'truncate' },
|
|
572
|
+
};
|
|
573
|
+
const DEFAULT_BUDGET = { limit: 1000, mode: 'truncate' };
|
|
574
|
+
function getFileBudget(fileName) {
|
|
575
|
+
return FILE_BUDGETS[fileName] ?? DEFAULT_BUDGET;
|
|
576
|
+
}
|
|
530
577
|
async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
|
|
531
578
|
const results = [];
|
|
532
579
|
const validExts = ['.md', '.yaml', '.yml', '.json', '.html', '.htm'];
|
|
533
580
|
const skipDirs = new Set(['.meta', '.git', 'node_modules', 'tests', 'src', 'dist', 'build']);
|
|
534
|
-
|
|
581
|
+
const ignoredFiles = [];
|
|
582
|
+
// v8.3.182+: 合并核心白名单 + 条件白名单
|
|
583
|
+
const platformExtras = getPlatformExtraFiles(platform);
|
|
584
|
+
const allowedFiles = new Set([...CORE_EXTRA_FILES, ...platformExtras]);
|
|
585
|
+
// 1. 扫描 00-specs/ 下白名单内的文件
|
|
535
586
|
const specsDir = (0, path_1.join)(cwd, taskDir, '00-specs');
|
|
536
587
|
try {
|
|
537
588
|
if (await (0, fs_extra_1.pathExists)(specsDir)) {
|
|
@@ -542,6 +593,10 @@ async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
|
|
|
542
593
|
const ext = e.name.slice(e.name.lastIndexOf('.'));
|
|
543
594
|
if (!validExts.includes(ext))
|
|
544
595
|
continue;
|
|
596
|
+
if (!allowedFiles.has(e.name)) {
|
|
597
|
+
ignoredFiles.push(`00-specs/${e.name}`);
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
545
600
|
const relPath = (0, path_1.join)('00-specs', e.name);
|
|
546
601
|
const fullPath = (0, path_1.join)(cwd, taskDir, relPath);
|
|
547
602
|
if (!seenPaths.has(fullPath)) {
|
|
@@ -551,7 +606,7 @@ async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
|
|
|
551
606
|
}
|
|
552
607
|
}
|
|
553
608
|
catch { /* 忽略 */ }
|
|
554
|
-
// 2.
|
|
609
|
+
// 2. 扫描子任务目录下白名单内的文件(递归)
|
|
555
610
|
if (platform) {
|
|
556
611
|
const platformBase = (0, path_1.join)(cwd, taskDir, platform);
|
|
557
612
|
try {
|
|
@@ -561,16 +616,26 @@ async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
|
|
|
561
616
|
if (!subE.isDirectory() || subE.name.startsWith('.'))
|
|
562
617
|
continue;
|
|
563
618
|
const subtaskDir = (0, path_1.join)(platformBase, subE.name);
|
|
564
|
-
await scanDirRecursive(subtaskDir, (0, path_1.join)(platform, subE.name), results, seenPaths, skipDirs, validExts, cwd, taskDir);
|
|
619
|
+
await scanDirRecursive(subtaskDir, (0, path_1.join)(platform, subE.name), results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles, allowedFiles);
|
|
565
620
|
}
|
|
566
621
|
}
|
|
567
622
|
}
|
|
568
623
|
catch { /* 忽略 */ }
|
|
569
624
|
}
|
|
625
|
+
// 输出被忽略的文件提示
|
|
626
|
+
if (ignoredFiles.length > 0) {
|
|
627
|
+
console.warn(`[prompt-builder] 以下文件不在白名单中,已忽略(如需加载请在 TASK.md 中声明):`);
|
|
628
|
+
for (const f of ignoredFiles.slice(0, 10)) {
|
|
629
|
+
console.warn(` - ${f}`);
|
|
630
|
+
}
|
|
631
|
+
if (ignoredFiles.length > 10) {
|
|
632
|
+
console.warn(` ... 还有 ${ignoredFiles.length - 10} 个文件被忽略`);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
570
635
|
return results;
|
|
571
636
|
}
|
|
572
|
-
/**
|
|
573
|
-
async function scanDirRecursive(dir, relPrefix, results, seenPaths, skipDirs, validExts, cwd, taskDir) {
|
|
637
|
+
/** 递归扫描目录,收集用户自定义文档(白名单模式) */
|
|
638
|
+
async function scanDirRecursive(dir, relPrefix, results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles, allowedFiles) {
|
|
574
639
|
try {
|
|
575
640
|
const entries = await (0, fs_extra_1.readdir)(dir, { withFileTypes: true });
|
|
576
641
|
for (const e of entries) {
|
|
@@ -579,12 +644,16 @@ async function scanDirRecursive(dir, relPrefix, results, seenPaths, skipDirs, va
|
|
|
579
644
|
if (e.isDirectory()) {
|
|
580
645
|
if (skipDirs.has(e.name) || e.name.startsWith('.'))
|
|
581
646
|
continue;
|
|
582
|
-
await scanDirRecursive((0, path_1.join)(dir, e.name), relPath, results, seenPaths, skipDirs, validExts, cwd, taskDir);
|
|
647
|
+
await scanDirRecursive((0, path_1.join)(dir, e.name), relPath, results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles, allowedFiles);
|
|
583
648
|
}
|
|
584
649
|
else if (e.isFile()) {
|
|
585
650
|
const ext = e.name.slice(e.name.lastIndexOf('.'));
|
|
586
651
|
if (!validExts.includes(ext))
|
|
587
652
|
continue;
|
|
653
|
+
if (!allowedFiles.has(e.name)) {
|
|
654
|
+
ignoredFiles.push(relPath);
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
588
657
|
if (!seenPaths.has(fullPath)) {
|
|
589
658
|
results.push({ name: `用户补充/${relPath}`, path: relPath });
|
|
590
659
|
}
|
|
@@ -623,8 +692,23 @@ async function loadAllTaskContext(cwd, taskDir, platform, iteration, graph) {
|
|
|
623
692
|
}
|
|
624
693
|
if (content.trim().length <= 50 || content.trim().match(/^#+\s*待填充|^<!--\s*AI-FILL\s*-->$/m))
|
|
625
694
|
return;
|
|
626
|
-
|
|
627
|
-
|
|
695
|
+
// v8.3.181+: 兜底模式也按文件类型检查预算(放宽到 2 倍)
|
|
696
|
+
const fileName = (0, path_1.basename)(fullPath);
|
|
697
|
+
const budget = getFileBudget(fileName);
|
|
698
|
+
const fallbackLimit = budget.limit * 2;
|
|
699
|
+
if (content.length > fallbackLimit) {
|
|
700
|
+
if (budget.mode === 'error') {
|
|
701
|
+
logger_1.logger.error(`[prompt-builder] ${fileName} 超过兜底预算上限 (${content.length} > ${fallbackLimit})。`);
|
|
702
|
+
logger_1.logger.error(` 该文件属于"必须完整"类型,不会被截断。建议精简方式:`);
|
|
703
|
+
logger_1.logger.error(` - 删除过时的注释和示例代码`);
|
|
704
|
+
logger_1.logger.error(` - 将详细说明链接到外部文档`);
|
|
705
|
+
logger_1.logger.error(` - 使用表格代替冗长的列表`);
|
|
706
|
+
logger_1.logger.error(` - 精简后重新执行: speccore execute --resume`);
|
|
707
|
+
// 不截断
|
|
708
|
+
}
|
|
709
|
+
else {
|
|
710
|
+
content = content.slice(0, fallbackLimit) + `\n\n> ... (已截断,原文件 ${rawContent.length} 字,兜底预算上限 ${fallbackLimit})`;
|
|
711
|
+
}
|
|
628
712
|
}
|
|
629
713
|
if (totalChars + content.length > MAX_TOTAL)
|
|
630
714
|
return;
|