speccore 8.3.181 → 8.3.188

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.
Files changed (214) hide show
  1. package/.agents/skills/spec-analyze/SKILL.md +2 -169
  2. package/.agents/skills/spec-ask/SKILL.md +2 -177
  3. package/.agents/skills/spec-change/SKILL.md +2 -214
  4. package/.agents/skills/spec-dashboard/SKILL.md +1 -76
  5. package/.agents/skills/spec-deploy/SKILL.md +2 -298
  6. package/.agents/skills/spec-doc2spec/SKILL.md +2 -116
  7. package/.agents/skills/spec-done/SKILL.md +2 -203
  8. package/.agents/skills/spec-execute/SKILL.md +2 -178
  9. package/.agents/skills/spec-help/SKILL.md +1 -75
  10. package/.agents/skills/spec-iteration-create/SKILL.md +2 -123
  11. package/.agents/skills/spec-plan/SKILL.md +2 -117
  12. package/.agents/skills/spec-pr/SKILL.md +2 -203
  13. package/.agents/skills/spec-run/SKILL.md +16 -0
  14. package/.agents/skills/spec-spec2doc/SKILL.md +2 -121
  15. package/.agents/skills/spec-split/SKILL.md +2 -208
  16. package/.agents/skills/spec-task-create/SKILL.md +2 -151
  17. package/.agents/skills/spec-verify/SKILL.md +2 -214
  18. package/.agents/skills/spec-welcome/SKILL.md +1 -67
  19. package/.agents/skills/speccore-router/SKILL.md +14 -2
  20. package/README.en.md +9 -9
  21. package/README.md +2 -1
  22. package/dist/cli.js +24 -25
  23. package/dist/cli.js.map +1 -1
  24. package/dist/commands/about.js +1 -1
  25. package/dist/commands/about.js.map +1 -1
  26. package/dist/commands/analyze.d.ts +1 -0
  27. package/dist/commands/analyze.d.ts.map +1 -1
  28. package/dist/commands/analyze.js +94 -7
  29. package/dist/commands/analyze.js.map +1 -1
  30. package/dist/commands/ask.js +6 -6
  31. package/dist/commands/ask.js.map +1 -1
  32. package/dist/commands/dev.d.ts +2 -0
  33. package/dist/commands/dev.d.ts.map +1 -1
  34. package/dist/commands/dev.js +102 -1
  35. package/dist/commands/dev.js.map +1 -1
  36. package/dist/commands/doctor.js +28 -0
  37. package/dist/commands/doctor.js.map +1 -1
  38. package/dist/commands/execute.js +3 -3
  39. package/dist/commands/execute.js.map +1 -1
  40. package/dist/commands/init.d.ts.map +1 -1
  41. package/dist/commands/init.js +31 -52
  42. package/dist/commands/init.js.map +1 -1
  43. package/dist/commands/iteration/split.d.ts.map +1 -1
  44. package/dist/commands/iteration/split.js +12 -39
  45. package/dist/commands/iteration/split.js.map +1 -1
  46. package/dist/commands/knowledge.d.ts +0 -12
  47. package/dist/commands/knowledge.d.ts.map +1 -1
  48. package/dist/commands/knowledge.js +0 -80
  49. package/dist/commands/knowledge.js.map +1 -1
  50. package/dist/commands/refresh.d.ts.map +1 -1
  51. package/dist/commands/refresh.js +10 -0
  52. package/dist/commands/refresh.js.map +1 -1
  53. package/dist/commands/search.d.ts +1 -0
  54. package/dist/commands/search.d.ts.map +1 -1
  55. package/dist/commands/search.js +38 -0
  56. package/dist/commands/search.js.map +1 -1
  57. package/dist/commands/update.d.ts.map +1 -1
  58. package/dist/commands/update.js +13 -3
  59. package/dist/commands/update.js.map +1 -1
  60. package/dist/core/agent-adapter.d.ts +6 -0
  61. package/dist/core/agent-adapter.d.ts.map +1 -1
  62. package/dist/core/agent-adapter.js +56 -172
  63. package/dist/core/agent-adapter.js.map +1 -1
  64. package/dist/core/agents/defaults/code-generator.md +64 -0
  65. package/dist/core/agents/defaults/code-reviewer.md +5 -0
  66. package/dist/core/agents/defaults/compiler.md +7 -0
  67. package/dist/core/agents/defaults/compliance-checker.md +2 -0
  68. package/dist/core/agents/defaults/dependency-analyst.md +5 -0
  69. package/dist/core/agents/defaults/doc-sync-agent.md +5 -0
  70. package/dist/core/agents/defaults/effort-estimator.md +28 -0
  71. package/dist/core/agents/defaults/global-analyzer.md +66 -0
  72. package/dist/core/agents/defaults/impact-analyst.md +5 -0
  73. package/dist/core/agents/defaults/interaction-designer.md +5 -0
  74. package/dist/core/agents/defaults/performance-expert.md +2 -0
  75. package/dist/core/agents/defaults/product-analyst-backend.md +6 -0
  76. package/dist/core/agents/defaults/product-analyst-frontend.md +6 -0
  77. package/dist/core/agents/defaults/product-analyst.md +5 -0
  78. package/dist/core/agents/defaults/regression-tester.md +5 -0
  79. package/dist/core/agents/defaults/requirement-analyzer.md +72 -0
  80. package/dist/core/agents/defaults/risk-assessor.md +5 -0
  81. package/dist/core/agents/defaults/schedule-planner.md +5 -0
  82. package/dist/core/agents/defaults/security-reviewer-finance.md +6 -0
  83. package/dist/core/agents/defaults/security-reviewer.md +7 -0
  84. package/dist/core/agents/defaults/task-decomposer.md +5 -0
  85. package/dist/core/agents/defaults/test-engineer.md +2 -0
  86. package/dist/core/agents/defaults/test-reviewer.md +5 -0
  87. package/dist/core/agents/engine/agent-loader.d.ts.map +1 -1
  88. package/dist/core/agents/engine/agent-loader.js +76 -6
  89. package/dist/core/agents/engine/agent-loader.js.map +1 -1
  90. package/dist/core/agents/engine/types.d.ts +5 -0
  91. package/dist/core/agents/engine/types.d.ts.map +1 -1
  92. package/dist/core/analyze-engine.d.ts.map +1 -1
  93. package/dist/core/analyze-engine.js +73 -82
  94. package/dist/core/analyze-engine.js.map +1 -1
  95. package/dist/core/ask-engine.d.ts +0 -58
  96. package/dist/core/ask-engine.d.ts.map +1 -1
  97. package/dist/core/ask-engine.js +63 -361
  98. package/dist/core/ask-engine.js.map +1 -1
  99. package/dist/core/business-rules.d.ts +36 -0
  100. package/dist/core/business-rules.d.ts.map +1 -0
  101. package/dist/core/business-rules.js +109 -0
  102. package/dist/core/business-rules.js.map +1 -0
  103. package/dist/core/change-impact-global.d.ts.map +1 -1
  104. package/dist/core/change-impact-global.js +4 -3
  105. package/dist/core/change-impact-global.js.map +1 -1
  106. package/dist/core/code-scanner.d.ts +1 -0
  107. package/dist/core/code-scanner.d.ts.map +1 -1
  108. package/dist/core/code-scanner.js +32 -3
  109. package/dist/core/code-scanner.js.map +1 -1
  110. package/dist/core/content-delivery.d.ts +59 -0
  111. package/dist/core/content-delivery.d.ts.map +1 -0
  112. package/dist/core/content-delivery.js +219 -0
  113. package/dist/core/content-delivery.js.map +1 -0
  114. package/dist/core/global-artifacts.d.ts.map +1 -1
  115. package/dist/core/global-artifacts.js +262 -19
  116. package/dist/core/global-artifacts.js.map +1 -1
  117. package/dist/core/global-retrieval.d.ts +38 -0
  118. package/dist/core/global-retrieval.d.ts.map +1 -0
  119. package/dist/core/global-retrieval.js +100 -0
  120. package/dist/core/global-retrieval.js.map +1 -0
  121. package/dist/core/html-prototype.d.ts +22 -0
  122. package/dist/core/html-prototype.d.ts.map +1 -0
  123. package/dist/core/html-prototype.js +103 -0
  124. package/dist/core/html-prototype.js.map +1 -0
  125. package/dist/core/multi-lang-parser.d.ts +43 -0
  126. package/dist/core/multi-lang-parser.d.ts.map +1 -0
  127. package/dist/core/multi-lang-parser.js +317 -0
  128. package/dist/core/multi-lang-parser.js.map +1 -0
  129. package/dist/core/pipeline-engine.js +16 -16
  130. package/dist/core/pipeline-engine.js.map +1 -1
  131. package/dist/core/platform-inference.d.ts +35 -0
  132. package/dist/core/platform-inference.d.ts.map +1 -0
  133. package/dist/core/platform-inference.js +205 -0
  134. package/dist/core/platform-inference.js.map +1 -0
  135. package/dist/core/prompt-builder.d.ts +1 -1
  136. package/dist/core/prompt-builder.d.ts.map +1 -1
  137. package/dist/core/prompt-builder.js +101 -75
  138. package/dist/core/prompt-builder.js.map +1 -1
  139. package/dist/core/refresh-scheduler.d.ts +50 -0
  140. package/dist/core/refresh-scheduler.d.ts.map +1 -0
  141. package/dist/core/refresh-scheduler.js +139 -0
  142. package/dist/core/refresh-scheduler.js.map +1 -0
  143. package/dist/core/reverse-requirement.d.ts +54 -0
  144. package/dist/core/reverse-requirement.d.ts.map +1 -0
  145. package/dist/core/reverse-requirement.js +277 -0
  146. package/dist/core/reverse-requirement.js.map +1 -0
  147. package/dist/core/schemas/task.schema.d.ts +2 -2
  148. package/dist/core/spec-skeleton.d.ts.map +1 -1
  149. package/dist/core/spec-skeleton.js +123 -0
  150. package/dist/core/spec-skeleton.js.map +1 -1
  151. package/dist/core/unified-config.d.ts +14 -0
  152. package/dist/core/unified-config.d.ts.map +1 -1
  153. package/dist/core/unified-config.js +94 -10
  154. package/dist/core/unified-config.js.map +1 -1
  155. package/dist/core/unified-retrieval.d.ts.map +1 -1
  156. package/dist/core/unified-retrieval.js +34 -8
  157. package/dist/core/unified-retrieval.js.map +1 -1
  158. package/dist/utils/task-utils.d.ts +4 -0
  159. package/dist/utils/task-utils.d.ts.map +1 -1
  160. package/dist/utils/task-utils.js +18 -0
  161. package/dist/utils/task-utils.js.map +1 -1
  162. package/package.json +5 -3
  163. package/vendor/tree-sitter/tree-sitter-go.wasm +0 -0
  164. package/vendor/tree-sitter/tree-sitter-java.wasm +0 -0
  165. package/vendor/tree-sitter/tree-sitter-python.wasm +0 -0
  166. package/vendor/tree-sitter/tree-sitter-rust.wasm +0 -0
  167. package/.agents/agents/README.md +0 -79
  168. package/.agents/agents/spec-analyzer.md +0 -41
  169. package/.agents/agents/spec-architect.md +0 -57
  170. package/.agents/agents/spec-change-detector.md +0 -55
  171. package/.agents/agents/spec-clarifier.md +0 -83
  172. package/.agents/agents/spec-executor.md +0 -41
  173. package/.agents/agents/spec-gatekeeper.md +0 -84
  174. package/.agents/agents/spec-global-analyzer.md +0 -111
  175. package/.agents/agents/spec-knowledge-curator.md +0 -54
  176. package/.agents/agents/spec-reviewer.md +0 -46
  177. package/.agents/agents/spec-security-auditor.md +0 -56
  178. package/.agents/agents/spec-tester.md +0 -120
  179. package/.agents/skills/spec-analyze/references/analysis-report.md +0 -9
  180. package/.agents/skills/spec-execute/references/code-output.md +0 -13
  181. package/.agents/skills/spec-plan/references/plan-template.md +0 -29
  182. package/.agents/skills/spec-task-create/references/requirement-template.md +0 -23
  183. package/dist/commands/bugfix.d.ts +0 -17
  184. package/dist/commands/bugfix.d.ts.map +0 -1
  185. package/dist/commands/bugfix.js +0 -301
  186. package/dist/commands/bugfix.js.map +0 -1
  187. package/dist/commands/help-quick.d.ts +0 -3
  188. package/dist/commands/help-quick.d.ts.map +0 -1
  189. package/dist/commands/help-quick.js +0 -66
  190. package/dist/commands/help-quick.js.map +0 -1
  191. package/dist/commands/index-update.d.ts +0 -8
  192. package/dist/commands/index-update.d.ts.map +0 -1
  193. package/dist/commands/index-update.js +0 -180
  194. package/dist/commands/index-update.js.map +0 -1
  195. package/dist/commands/schedule.d.ts +0 -26
  196. package/dist/commands/schedule.d.ts.map +0 -1
  197. package/dist/commands/schedule.js +0 -182
  198. package/dist/commands/schedule.js.map +0 -1
  199. package/dist/commands/watch.d.ts +0 -11
  200. package/dist/commands/watch.d.ts.map +0 -1
  201. package/dist/commands/watch.js +0 -166
  202. package/dist/commands/watch.js.map +0 -1
  203. package/dist/core/ai-markdown.d.ts +0 -5
  204. package/dist/core/ai-markdown.d.ts.map +0 -1
  205. package/dist/core/ai-markdown.js +0 -29
  206. package/dist/core/ai-markdown.js.map +0 -1
  207. package/dist/core/schedule-engine.d.ts +0 -25
  208. package/dist/core/schedule-engine.d.ts.map +0 -1
  209. package/dist/core/schedule-engine.js +0 -281
  210. package/dist/core/schedule-engine.js.map +0 -1
  211. package/dist/core/schedule-store.d.ts +0 -119
  212. package/dist/core/schedule-store.d.ts.map +0 -1
  213. package/dist/core/schedule-store.js +0 -216
  214. package/dist/core/schedule-store.js.map +0 -1
@@ -58,7 +58,12 @@ const knowledge_graph_1 = require("./knowledge-graph");
58
58
  const context_builder_1 = require("./context-builder");
59
59
  const spec_paths_1 = require("./spec-paths");
60
60
  const context_1 = require("./context");
61
+ const rag_engine_1 = require("./rag-engine");
61
62
  const unified_retrieval_1 = require("./unified-retrieval");
63
+ // v8.3.183+: 统一内容供给管线(md 大纲摘要,替代链接全文内联)
64
+ const content_delivery_1 = require("./content-delivery");
65
+ // v8.3.183+: HTML 原型渲染(Playwright 截图 + accessibility tree,替代纯文本)
66
+ const html_prototype_1 = require("./html-prototype");
62
67
  // v8.3.122+: execute 时深入读取关联源码
63
68
  const code_scanner_1 = require("./code-scanner");
64
69
  // v8.3.125+: 同义词扩展,解决中英文/缩写关键词匹配失败
@@ -415,7 +420,12 @@ async function loadExtraSpecs(cwd, taskDir, platform, iteration, options) {
415
420
  const budget = getFileBudget(fileName);
416
421
  if (content.length > budget.limit) {
417
422
  if (budget.mode === 'error') {
418
- logger_1.logger.error(`[prompt-builder] ${fileName} 超过预算上限 (${content.length} > ${budget.limit})。该文件必须完整,请精简源文件内容。`);
423
+ logger_1.logger.error(`[prompt-builder] ${fileName} 超过预算上限 (${content.length} > ${budget.limit})。`);
424
+ logger_1.logger.error(` 该文件属于"必须完整"类型,不会被截断。建议精简方式:`);
425
+ logger_1.logger.error(` - 删除过时的注释和示例代码`);
426
+ logger_1.logger.error(` - 将详细说明链接到外部文档`);
427
+ logger_1.logger.error(` - 使用表格代替冗长的列表`);
428
+ logger_1.logger.error(` - 精简后重新执行: speccore execute --resume`);
419
429
  // 不截断,保留完整内容
420
430
  }
421
431
  else {
@@ -537,14 +547,28 @@ async function loadExtraSpecs(cwd, taskDir, platform, iteration, options) {
537
547
  * 只加载 ALLOWED_EXTRA_FILES 白名单内的文件,防止上下文污染
538
548
  * 白名单外文件将被忽略并输出提示
539
549
  */
540
- const ALLOWED_EXTRA_FILES = new Set([
541
- 'SCHEMA.md', 'TEST.md', 'REVIEW.md', 'DEPLOY.md', 'MONITOR.md',
542
- 'RISK.md', 'DEPS.md', 'ERROR_CODES.md', 'COMPONENT_TREE.md',
543
- 'ROUTES.md', 'STATE.md',
550
+ // v8.3.182+: 白名单分两级(核心 + 条件)
551
+ // 核心白名单:所有任务都需要
552
+ const CORE_EXTRA_FILES = new Set([
553
+ 'CONTEXT.md', // 任务上下文(来源追溯 + 关联任务)
554
+ 'ERROR_CODES.md', // 错误码定义
544
555
  ]);
556
+ // 条件白名单:按平台类型加载
557
+ function getPlatformExtraFiles(platform) {
558
+ if (!platform)
559
+ return new Set();
560
+ const p = platform.toLowerCase();
561
+ if (p.includes('backend') || p.includes('service') || p.includes('api') || p.includes('server')) {
562
+ return new Set(['SCHEMA.md']);
563
+ }
564
+ if (p.includes('web') || p.includes('mobile') || p.includes('h5') || p.includes('frontend') || p.includes('admin')) {
565
+ return new Set(['COMPONENT_TREE.md', 'ROUTES.md', 'STATE.md']);
566
+ }
567
+ return new Set();
568
+ }
545
569
  // v8.3.181+: 按文件类型细分预算(必须完整 vs 可以截断)
546
570
  const FILE_BUDGETS = {
547
- 'CONSTITUTION.md': { limit: 4000, mode: 'error' },
571
+ 'CONSTITUTION.md': { limit: 6000, mode: 'error' },
548
572
  'REQ.md': { limit: 2000, mode: 'error' },
549
573
  'API_CONTRACT.yaml': { limit: 2000, mode: 'error' },
550
574
  'TASK.md': { limit: 1500, mode: 'truncate' },
@@ -560,6 +584,9 @@ async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
560
584
  const validExts = ['.md', '.yaml', '.yml', '.json', '.html', '.htm'];
561
585
  const skipDirs = new Set(['.meta', '.git', 'node_modules', 'tests', 'src', 'dist', 'build']);
562
586
  const ignoredFiles = [];
587
+ // v8.3.182+: 合并核心白名单 + 条件白名单
588
+ const platformExtras = getPlatformExtraFiles(platform);
589
+ const allowedFiles = new Set([...CORE_EXTRA_FILES, ...platformExtras]);
563
590
  // 1. 扫描 00-specs/ 下白名单内的文件
564
591
  const specsDir = (0, path_1.join)(cwd, taskDir, '00-specs');
565
592
  try {
@@ -571,7 +598,7 @@ async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
571
598
  const ext = e.name.slice(e.name.lastIndexOf('.'));
572
599
  if (!validExts.includes(ext))
573
600
  continue;
574
- if (!ALLOWED_EXTRA_FILES.has(e.name)) {
601
+ if (!allowedFiles.has(e.name)) {
575
602
  ignoredFiles.push(`00-specs/${e.name}`);
576
603
  continue;
577
604
  }
@@ -594,7 +621,7 @@ async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
594
621
  if (!subE.isDirectory() || subE.name.startsWith('.'))
595
622
  continue;
596
623
  const subtaskDir = (0, path_1.join)(platformBase, subE.name);
597
- await scanDirRecursive(subtaskDir, (0, path_1.join)(platform, subE.name), results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles);
624
+ await scanDirRecursive(subtaskDir, (0, path_1.join)(platform, subE.name), results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles, allowedFiles);
598
625
  }
599
626
  }
600
627
  }
@@ -613,7 +640,7 @@ async function scanUserCustomFiles(cwd, taskDir, platform, seenPaths) {
613
640
  return results;
614
641
  }
615
642
  /** 递归扫描目录,收集用户自定义文档(白名单模式) */
616
- async function scanDirRecursive(dir, relPrefix, results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles) {
643
+ async function scanDirRecursive(dir, relPrefix, results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles, allowedFiles) {
617
644
  try {
618
645
  const entries = await (0, fs_extra_1.readdir)(dir, { withFileTypes: true });
619
646
  for (const e of entries) {
@@ -622,13 +649,13 @@ async function scanDirRecursive(dir, relPrefix, results, seenPaths, skipDirs, va
622
649
  if (e.isDirectory()) {
623
650
  if (skipDirs.has(e.name) || e.name.startsWith('.'))
624
651
  continue;
625
- await scanDirRecursive((0, path_1.join)(dir, e.name), relPath, results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles);
652
+ await scanDirRecursive((0, path_1.join)(dir, e.name), relPath, results, seenPaths, skipDirs, validExts, cwd, taskDir, ignoredFiles, allowedFiles);
626
653
  }
627
654
  else if (e.isFile()) {
628
655
  const ext = e.name.slice(e.name.lastIndexOf('.'));
629
656
  if (!validExts.includes(ext))
630
657
  continue;
631
- if (!ALLOWED_EXTRA_FILES.has(e.name)) {
658
+ if (!allowedFiles.has(e.name)) {
632
659
  ignoredFiles.push(relPath);
633
660
  continue;
634
661
  }
@@ -676,7 +703,12 @@ async function loadAllTaskContext(cwd, taskDir, platform, iteration, graph) {
676
703
  const fallbackLimit = budget.limit * 2;
677
704
  if (content.length > fallbackLimit) {
678
705
  if (budget.mode === 'error') {
679
- logger_1.logger.error(`[prompt-builder] ${fileName} 超过兜底预算上限 (${content.length} > ${fallbackLimit})。该文件必须完整,请精简源文件内容。`);
706
+ logger_1.logger.error(`[prompt-builder] ${fileName} 超过兜底预算上限 (${content.length} > ${fallbackLimit})。`);
707
+ logger_1.logger.error(` 该文件属于"必须完整"类型,不会被截断。建议精简方式:`);
708
+ logger_1.logger.error(` - 删除过时的注释和示例代码`);
709
+ logger_1.logger.error(` - 将详细说明链接到外部文档`);
710
+ logger_1.logger.error(` - 使用表格代替冗长的列表`);
711
+ logger_1.logger.error(` - 精简后重新执行: speccore execute --resume`);
680
712
  // 不截断
681
713
  }
682
714
  else {
@@ -1059,7 +1091,7 @@ async function buildGlobalTOC(globalDir) {
1059
1091
  * 加载全局上下文(带 TOC 缓存)
1060
1092
  * 策略:必读的 INDEX.md 直接注入 + 其余文件只给目录,AI 自己 Read
1061
1093
  */
1062
- async function loadGlobalContext(cwd, _command, platform) {
1094
+ async function loadGlobalContext(cwd, _command, platform, feature) {
1063
1095
  const globalDir = (0, path_1.join)(cwd, '.speccore', 'GLOBAL');
1064
1096
  const ctx = { toc: [] };
1065
1097
  if (!await (0, fs_extra_1.pathExists)(globalDir))
@@ -1074,37 +1106,15 @@ async function loadGlobalContext(cwd, _command, platform) {
1074
1106
  // 支持单文件(单文件模式)+ BUSINESS_RULES/ 目录(推荐,支持按 platform 过滤)
1075
1107
  if (!ctx.keyFileSummaries)
1076
1108
  ctx.keyFileSummaries = [];
1077
- // 1. 单文件模式:GLOBAL/BUSINESS_RULES.md
1078
- const legacyPath = (0, path_1.join)(globalDir, 'BUSINESS_RULES.md');
1079
- if (await (0, fs_extra_1.pathExists)(legacyPath)) {
1080
- try {
1081
- const content = await (0, fs_extra_1.readFile)(legacyPath, 'utf-8');
1082
- ctx.keyFileSummaries.push({ path: 'BUSINESS_RULES.md', content: content.slice(0, 4000) });
1083
- }
1084
- catch { /* 忽略 */ }
1085
- }
1086
- // 2. 新路径:GLOBAL/BUSINESS_RULES/ 目录,按 platform 过滤加载
1087
- const businessRulesDir = (0, path_1.join)(globalDir, 'BUSINESS_RULES');
1088
- if (await (0, fs_extra_1.pathExists)(businessRulesDir)) {
1089
- try {
1090
- const files = (await (0, fs_extra_1.readdir)(businessRulesDir))
1091
- .filter(f => f.endsWith('.md'))
1092
- .sort();
1093
- for (const file of files) {
1094
- // platform 过滤:无 platform 时加载全部;有 platform 时加载 common + 匹配端
1095
- if (platform) {
1096
- const base = file.replace(/\.md$/, '');
1097
- const isCommon = base.includes('-common');
1098
- const isPlatformMatch = base === platform || base.endsWith(`-${platform}`) || base.includes(`-${platform}-`);
1099
- if (!isCommon && !isPlatformMatch)
1100
- continue;
1101
- }
1102
- const content = await (0, fs_extra_1.readFile)((0, path_1.join)(businessRulesDir, file), 'utf-8');
1103
- ctx.keyFileSummaries.push({ path: `BUSINESS_RULES/${file}`, content: content.slice(0, 4000) });
1104
- }
1109
+ // v8.3.184+: 业务规则三层统一加载(全局 BUSINESS_RULES/ + 端级 + 功能级)
1110
+ try {
1111
+ const { loadBusinessRules } = await Promise.resolve().then(() => __importStar(require('./business-rules')));
1112
+ const rules = await loadBusinessRules({ cwd, platform, feature });
1113
+ for (const item of rules) {
1114
+ ctx.keyFileSummaries.push({ path: item.path, content: item.content });
1105
1115
  }
1106
- catch { /* 忽略 */ }
1107
1116
  }
1117
+ catch { /* 忽略 */ }
1108
1118
  // 3. v8.3.134+: RULES/ 规则文件自动注入(四层架构第二层)
1109
1119
  // 按 frontmatter priority 降序排序,优先加载高优先级规则;总量上限 8000 字符
1110
1120
  const rulesDir = (0, path_1.join)(cwd, '.speccore', 'RULES');
@@ -1604,8 +1614,8 @@ function getInstruction(command, context) {
1604
1614
  */
1605
1615
  // v8.3.160+: 命令 → 默认子 Agent 角色映射
1606
1616
  const DEFAULT_SUBAGENT_MAP = {
1607
- analyze: 'spec-analyzer',
1608
- execute: 'spec-executor',
1617
+ analyze: 'requirement-analyzer',
1618
+ execute: 'code-generator',
1609
1619
  split: 'task-decomposer',
1610
1620
  plan: 'schedule-planner',
1611
1621
  change: 'impact-analyst',
@@ -2404,6 +2414,23 @@ function formatPrompt(prompt, maxTokens) {
2404
2414
  logger_1.logger?.info?.(` 🪶 Prompt 已极简模式:仅保留技术栈/API/核心指令`);
2405
2415
  return result;
2406
2416
  }
2417
+ // ═══════════════════════════════════════════════════════════
2418
+ // v8.3.187+ 通用行为准则(degrade to honesty 体系)
2419
+ // 融合业界最佳实践:
2420
+ // - Claude Code 官方系统提示词:Read before write / Minimal change / 不臆造 API
2421
+ // - Anthropic Prompt Library:avoid over-engineering / hallucination-free / 诚实标注
2422
+ // - Karpathy 12 规则:Think before coding / Precise edits / 主动澄清 / 明确失败报告
2423
+ // 原则:少而精(5–8 条为宜,过多会导致合规率骤降),每条可操作、正面指令 + 明确禁止结合。
2424
+ // ═══════════════════════════════════════════════════════════
2425
+ const UNIVERSAL_BEHAVIOR_RULES = [
2426
+ '- **Spec 优先(最高优先级)**:代码、口头要求与 Spec(REQ/TECH/API_CONTRACT)冲突时,一律以 Spec 为准,并明确指出冲突点与差异。',
2427
+ '- **先读后写**:动手改代码前,先读相关 Spec 与现有实现;禁止凭空臆造不存在的 API、字段、路径或库方法,不确定就查,查不到就如实说明。',
2428
+ '- **不迎合用户**:优先保证技术正确与真实,而非附和用户;需求有缺陷、自相矛盾或不合理处,直接指出并给建议,不为顺从而照做。',
2429
+ '- **最小改动**:只做当前任务要求或明确必要的改动;不顺手重构无关代码、不添加超出需求的「改进」、不过度设计;无用代码直接删除,不留兼容性 hack。',
2430
+ '- **主动澄清**:需求或 Spec 有歧义、缺关键信息时,先提出澄清问题或明确列出假设,不擅自猜测后闷头实现。',
2431
+ '- **降级到诚实**:区分「事实 / 推断 / 猜测」;不确定的信息标注置信度,不编造;做不到或没把握的方案,说明局限,不给自信的错误答案。',
2432
+ '- **破坏性操作先确认**:删除、覆盖、迁移文件或改动公共 API 等影响面大/不可逆的操作,先说明影响并确认后再执行。',
2433
+ ];
2407
2434
  /** 实际构建 prompt 文本(无裁剪逻辑) */
2408
2435
  function buildPromptText(prompt) {
2409
2436
  // v8.3.160+: analyze 命令使用 buildMultiDocPrompt 生成的原始 Prompt,直接返回
@@ -2413,6 +2440,11 @@ function buildPromptText(prompt) {
2413
2440
  const lines = [];
2414
2441
  lines.push('[SPECCORE_PROMPT]');
2415
2442
  lines.push('');
2443
+ // v8.3.184+ 通用行为准则(v8.3.187+ 扩展并抽取为 UNIVERSAL_BEHAVIOR_RULES 常量)
2444
+ lines.push('## 通用行为准则');
2445
+ for (const rule of UNIVERSAL_BEHAVIOR_RULES)
2446
+ lines.push(rule);
2447
+ lines.push('');
2416
2448
  // v8.3.160+: 注入子 Agent 角色定义和上下文裁剪策略
2417
2449
  if (prompt.agentContext) {
2418
2450
  lines.push(prompt.agentContext);
@@ -2774,32 +2806,22 @@ async function expandMarkdownLinks(content, baseDir, seenPaths, maxDepth = 3, cu
2774
2806
  let linkContent = await (0, fs_extra_1.readFile)(resolved, 'utf-8');
2775
2807
  if (linkContent.trim().length <= 30)
2776
2808
  continue;
2777
- // v8.3.138+: HTML/原型文件使用独立阈值(8KB),避免原型文件被过度截断。
2778
- // 超过阈值不截断 inline(避免结构残缺误导 AI),而是提示宿主 AI 直接打开查看。
2779
2809
  const isHtml = resolved.endsWith('.html') || resolved.endsWith('.htm');
2780
- const htmlMaxChars = 8192; // 8KB,足够覆盖大多数 HTML 原型
2781
- const isLarge = isHtml ? linkContent.length > htmlMaxChars : linkContent.length > maxChars;
2782
- if (isHtml && isLarge) {
2783
- expansions.push(`\n\n---\n📄 **HTML 原型文件**(内容过大未展开,宿主 AI 请务必直接打开查看):\n` +
2784
- `- 文件: ${resolved}\n` +
2785
- `- 大小: ${(linkContent.length / 1024).toFixed(1)} KB\n` +
2786
- `- 描述: ${link.text || '无描述'}\n` +
2787
- `> ⚠️ **请打开此 HTML 文件查看完整内容**。此为页面原型/设计稿,与需求理解高度相关,CLI 因文件过大未完整展开,需要你直接打开文件查看。`);
2788
- continue;
2789
- }
2790
- // v8.3.122+: HTML 原型文件保留完整内容,不再提取纯文本
2810
+ // v8.3.183+: 统一用结构化摘要替代全文内联
2811
+ // - html → Playwright accessibility tree(页面结构),失败降级 extractHtmlText
2812
+ // - md → 标题大纲
2813
+ let rawSummary;
2791
2814
  if (isHtml) {
2792
- // 保留原始 HTML(包含 CSS/JS/结构),让 AI 完整解析原型
2815
+ const proto = await (0, html_prototype_1.renderHtmlPrototype)(resolved);
2816
+ rawSummary = proto?.accessibilityTree || (0, rag_engine_1.extractHtmlText)(linkContent);
2793
2817
  }
2794
- const isTruncated = isHtml ? linkContent.length > htmlMaxChars : linkContent.length > maxChars;
2795
- if (isTruncated) {
2796
- linkContent = linkContent.slice(0, maxChars) +
2797
- `\n\n---\n📄 **文件内容已截断**(宿主 AI 请务必打开查看完整内容):\n` +
2798
- `- 文件: ${resolved}\n` +
2799
- `- 大小: ${(await (0, fs_extra_1.stat)(resolved)).size} 字节\n` +
2800
- `> ⚠️ **请打开此文件查看完整内容**。此文件与需求理解高度相关,CLI 因长度限制已截断,需要你直接打开文件查看。`;
2818
+ else {
2819
+ rawSummary = (0, content_delivery_1.extractMdOutline)(linkContent);
2801
2820
  }
2802
- expansions.push(`\n\n<!-- 展开链接: ${link.path} -->\n**[链接展开] ${link.text}** (${link.path}):\n\n${linkContent}`);
2821
+ const summary = rawSummary.length > maxChars
2822
+ ? rawSummary.slice(0, maxChars) + '\n…(摘要截断)'
2823
+ : rawSummary;
2824
+ expansions.push(`\n\n**[链接] ${link.text}** (${link.path}):\n${summary}\n> 全文见 \`${resolved}\``);
2803
2825
  }
2804
2826
  catch { /* 忽略读取失败的链接文件 */ }
2805
2827
  }
@@ -2873,17 +2895,21 @@ async function inlineMarkdownImages(content, baseDir, seenPaths, visionConfig, m
2873
2895
  }
2874
2896
  }
2875
2897
  else {
2876
- // v8.3.138+: 无视觉模型时,明确提示宿主 AI 打开图片查看(不要用 HTML 注释,AI 会忽略)
2877
- inlines.push(`\n\n---\n🖼️ **图片文件**(CLI 无法解析图片内容,宿主 AI 请务必直接打开查看):`);
2878
- inlines.push(`- ${img.alt || '无描述'}: ${resolved}`);
2879
- try {
2880
- if (await (0, fs_extra_1.pathExists)(resolved)) {
2881
- const st = await (0, fs_extra_1.stat)(resolved);
2882
- inlines.push(`- 文件大小: ${(st.size / 1024).toFixed(1)} KB`);
2898
+ // v8.3.183+: 无视觉模型时,用 alt 语义兜底(硬保证有描述),"请打开"降为补充
2899
+ const altDesc = img.alt && img.alt.trim() ? img.alt.trim() : '';
2900
+ if (altDesc) {
2901
+ inlines.push(`\n\n---\n🖼️ **图片** ${altDesc}:\`${resolved}\`\n> 图片细节需宿主 AI 打开查看(CLI 无视觉模型,仅能提供 alt 语义)`);
2902
+ }
2903
+ else {
2904
+ inlines.push(`\n\n---\n🖼️ **图片文件**(无 alt 描述,宿主 AI 请打开查看):\n- ${resolved}`);
2905
+ try {
2906
+ if (await (0, fs_extra_1.pathExists)(resolved)) {
2907
+ const st = await (0, fs_extra_1.stat)(resolved);
2908
+ inlines.push(`- 文件大小: ${(st.size / 1024).toFixed(1)} KB`);
2909
+ }
2883
2910
  }
2911
+ catch { /* ignore */ }
2884
2912
  }
2885
- catch { /* ignore */ }
2886
- inlines.push(`> ⚠️ **请打开此图片文件查看内容**。此图片与需求理解高度相关,CLI 无法自动解析图片内容,需要你直接打开文件查看。`);
2887
2913
  }
2888
2914
  }
2889
2915
  // v8.3.125+: 在内容末尾附加外链图片清单,提示宿主 AI 按需查看