speccore 8.3.21 → 8.3.26

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 (120) hide show
  1. package/README.md +7 -4
  2. package/dist/cli.js +19 -3
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/analyze.d.ts.map +1 -1
  5. package/dist/commands/analyze.js +24 -8
  6. package/dist/commands/analyze.js.map +1 -1
  7. package/dist/commands/config.d.ts +3 -1
  8. package/dist/commands/config.d.ts.map +1 -1
  9. package/dist/commands/config.js +206 -90
  10. package/dist/commands/config.js.map +1 -1
  11. package/dist/commands/context-output.d.ts.map +1 -1
  12. package/dist/commands/context-output.js +0 -10
  13. package/dist/commands/context-output.js.map +1 -1
  14. package/dist/commands/dev.js +6 -7
  15. package/dist/commands/dev.js.map +1 -1
  16. package/dist/commands/doctor.d.ts.map +1 -1
  17. package/dist/commands/doctor.js +140 -0
  18. package/dist/commands/doctor.js.map +1 -1
  19. package/dist/commands/done.js +51 -20
  20. package/dist/commands/done.js.map +1 -1
  21. package/dist/commands/execute.d.ts.map +1 -1
  22. package/dist/commands/execute.js +147 -45
  23. package/dist/commands/execute.js.map +1 -1
  24. package/dist/commands/help.js +5 -0
  25. package/dist/commands/help.js.map +1 -1
  26. package/dist/commands/init.d.ts +0 -2
  27. package/dist/commands/init.d.ts.map +1 -1
  28. package/dist/commands/init.js +9 -51
  29. package/dist/commands/init.js.map +1 -1
  30. package/dist/commands/iteration/split.js +29 -17
  31. package/dist/commands/iteration/split.js.map +1 -1
  32. package/dist/commands/status-panel.d.ts.map +1 -1
  33. package/dist/commands/status-panel.js +13 -48
  34. package/dist/commands/status-panel.js.map +1 -1
  35. package/dist/commands/status.d.ts.map +1 -1
  36. package/dist/commands/status.js +32 -0
  37. package/dist/commands/status.js.map +1 -1
  38. package/dist/commands/update.d.ts.map +1 -1
  39. package/dist/commands/update.js +206 -8
  40. package/dist/commands/update.js.map +1 -1
  41. package/dist/commands/verdict.d.ts +16 -0
  42. package/dist/commands/verdict.d.ts.map +1 -0
  43. package/dist/commands/verdict.js +189 -0
  44. package/dist/commands/verdict.js.map +1 -0
  45. package/dist/commands/verify.d.ts.map +1 -1
  46. package/dist/commands/verify.js +3 -2
  47. package/dist/commands/verify.js.map +1 -1
  48. package/dist/core/analyze-engine.d.ts.map +1 -1
  49. package/dist/core/analyze-engine.js +3 -4
  50. package/dist/core/analyze-engine.js.map +1 -1
  51. package/dist/core/arbitration/arbitration-engine.d.ts +36 -0
  52. package/dist/core/arbitration/arbitration-engine.d.ts.map +1 -0
  53. package/dist/core/arbitration/arbitration-engine.js +142 -0
  54. package/dist/core/arbitration/arbitration-engine.js.map +1 -0
  55. package/dist/core/arbitration/conflict-detector.d.ts +15 -0
  56. package/dist/core/arbitration/conflict-detector.d.ts.map +1 -0
  57. package/dist/core/arbitration/conflict-detector.js +78 -0
  58. package/dist/core/arbitration/conflict-detector.js.map +1 -0
  59. package/dist/core/arbitration/conflict-types.d.ts +34 -0
  60. package/dist/core/arbitration/conflict-types.d.ts.map +1 -0
  61. package/dist/core/arbitration/conflict-types.js +8 -0
  62. package/dist/core/arbitration/conflict-types.js.map +1 -0
  63. package/dist/core/arbitration/contract-registry.d.ts +15 -0
  64. package/dist/core/arbitration/contract-registry.d.ts.map +1 -0
  65. package/dist/core/arbitration/contract-registry.js +185 -0
  66. package/dist/core/arbitration/contract-registry.js.map +1 -0
  67. package/dist/core/arbitration/contract-types.d.ts +33 -0
  68. package/dist/core/arbitration/contract-types.d.ts.map +1 -0
  69. package/dist/core/arbitration/contract-types.js +8 -0
  70. package/dist/core/arbitration/contract-types.js.map +1 -0
  71. package/dist/core/arbitration/index.d.ts +16 -0
  72. package/dist/core/arbitration/index.d.ts.map +1 -0
  73. package/dist/core/arbitration/index.js +32 -0
  74. package/dist/core/arbitration/index.js.map +1 -0
  75. package/dist/core/arbitration/l1-auto-arbiter.d.ts +19 -0
  76. package/dist/core/arbitration/l1-auto-arbiter.d.ts.map +1 -0
  77. package/dist/core/arbitration/l1-auto-arbiter.js +41 -0
  78. package/dist/core/arbitration/l1-auto-arbiter.js.map +1 -0
  79. package/dist/core/arbitration/l2-ai-arbiter.d.ts +19 -0
  80. package/dist/core/arbitration/l2-ai-arbiter.d.ts.map +1 -0
  81. package/dist/core/arbitration/l2-ai-arbiter.js +57 -0
  82. package/dist/core/arbitration/l2-ai-arbiter.js.map +1 -0
  83. package/dist/core/arbitration/l3-human-arbiter.d.ts +24 -0
  84. package/dist/core/arbitration/l3-human-arbiter.d.ts.map +1 -0
  85. package/dist/core/arbitration/l3-human-arbiter.js +65 -0
  86. package/dist/core/arbitration/l3-human-arbiter.js.map +1 -0
  87. package/dist/core/arbitration/verdict-generator.d.ts +16 -0
  88. package/dist/core/arbitration/verdict-generator.d.ts.map +1 -0
  89. package/dist/core/arbitration/verdict-generator.js +166 -0
  90. package/dist/core/arbitration/verdict-generator.js.map +1 -0
  91. package/dist/core/arbitration/verdict-types.d.ts +49 -0
  92. package/dist/core/arbitration/verdict-types.d.ts.map +1 -0
  93. package/dist/core/arbitration/verdict-types.js +8 -0
  94. package/dist/core/arbitration/verdict-types.js.map +1 -0
  95. package/dist/core/ask-config.d.ts +4 -3
  96. package/dist/core/ask-config.d.ts.map +1 -1
  97. package/dist/core/ask-config.js +79 -1
  98. package/dist/core/ask-config.js.map +1 -1
  99. package/dist/core/ask-engine.d.ts.map +1 -1
  100. package/dist/core/ask-engine.js +7 -0
  101. package/dist/core/ask-engine.js.map +1 -1
  102. package/dist/core/intent-recognition.d.ts +1 -1
  103. package/dist/core/intent-recognition.d.ts.map +1 -1
  104. package/dist/core/intent-recognition.js +10 -0
  105. package/dist/core/intent-recognition.js.map +1 -1
  106. package/dist/core/pattern-detector.d.ts +24 -0
  107. package/dist/core/pattern-detector.d.ts.map +1 -1
  108. package/dist/core/pattern-detector.js +172 -3
  109. package/dist/core/pattern-detector.js.map +1 -1
  110. package/dist/core/quality-audit.d.ts.map +1 -1
  111. package/dist/core/quality-audit.js +23 -15
  112. package/dist/core/quality-audit.js.map +1 -1
  113. package/dist/core/spec-skeleton.d.ts.map +1 -1
  114. package/dist/core/spec-skeleton.js +35 -12
  115. package/dist/core/spec-skeleton.js.map +1 -1
  116. package/dist/core/unified-config.d.ts +161 -27
  117. package/dist/core/unified-config.d.ts.map +1 -1
  118. package/dist/core/unified-config.js +856 -82
  119. package/dist/core/unified-config.js.map +1 -1
  120. package/package.json +1 -1
@@ -63,6 +63,8 @@ const execution_state_1 = require("../core/execution-state");
63
63
  const git_integration_1 = require("../core/git-integration");
64
64
  const prompt_builder_1 = require("../core/prompt-builder");
65
65
  const verify_engine_1 = require("../core/verify-engine");
66
+ const arbitration_engine_1 = require("../core/arbitration/arbitration-engine");
67
+ const verdict_generator_1 = require("../core/arbitration/verdict-generator");
66
68
  const unified_config_1 = require("../core/unified-config");
67
69
  const pipeline_engine_1 = require("../core/pipeline-engine");
68
70
  const index_guard_1 = require("../core/index-guard");
@@ -1171,13 +1173,7 @@ async function preFlightCheck(tasks, iteration, options) {
1171
1173
  }
1172
1174
  }
1173
1175
  if (!testFound) {
1174
- // 旧结构回退
1175
- const testPath = (0, path_1.join)(taskDir, '99-artifacts', 'TEST.md');
1176
- if (await (0, fs_extra_1.pathExists)(testPath)) {
1177
- const test = await (0, fs_extra_1.readFile)(testPath, 'utf-8');
1178
- const n = (test.match(/⬜|✅|❌/g) || []).length;
1179
- logger_1.logger.info(` 3. 测试: ${n} 用例`);
1180
- }
1176
+ logger_1.logger.info(` 3. 测试: 未找到`);
1181
1177
  }
1182
1178
  // 4. Review(v6.49.9+: 扫描平铺的端目录)
1183
1179
  let reviewFound = false;
@@ -1188,7 +1184,7 @@ async function preFlightCheck(tasks, iteration, options) {
1188
1184
  }
1189
1185
  }
1190
1186
  if (!reviewFound) {
1191
- logger_1.logger.info(` 4. 审查: ${await (0, fs_extra_1.pathExists)((0, path_1.join)(taskDir, '99-artifacts', 'REVIEW.md')) ? '✅' : '❌'}`);
1187
+ logger_1.logger.info(` 4. 审查: ❌`);
1192
1188
  }
1193
1189
  // 5. API(00-specs/ 优先,_shared/ 回退)
1194
1190
  const hasApiContract = await (0, fs_extra_1.pathExists)((0, path_1.join)(taskDir, '00-specs', 'API_CONTRACT.yaml')) || await (0, fs_extra_1.pathExists)((0, path_1.join)(taskDir, '_shared', 'API_CONTRACT.yaml'));
@@ -1533,7 +1529,8 @@ async function executionVerifyLoop(tasks, iteration, options) {
1533
1529
  const maxRounds = 3;
1534
1530
  const iterDir = await (0, context_1.getIterationDir)(iteration);
1535
1531
  const config = await (0, unified_config_1.loadConfig)();
1536
- const codePath = config.code_scope?.[0] || process.cwd();
1532
+ const projectConfig = await (0, unified_config_1.loadProjectConfig)();
1533
+ const codePath = projectConfig.code_scope?.[0] || process.cwd();
1537
1534
  const absCodePath = codePath.startsWith('/') ? codePath : (0, path_1.join)(process.cwd(), codePath);
1538
1535
  for (const task of tasks) {
1539
1536
  logger_1.logger.info(`\n🔍 验证 ${task.id}...`);
@@ -1544,27 +1541,100 @@ async function executionVerifyLoop(tasks, iteration, options) {
1544
1541
  if (round > 1)
1545
1542
  logger_1.logger.info(` 🔄 第 ${round} 轮修复...`);
1546
1543
  allPassed = true;
1547
- // ── Step 1: 质量门禁(编译→Lint→测试→依赖→安全→Spec一致性)──
1548
- const gate = await (0, verify_engine_1.runQualityGate)(task.id, taskCodePath, taskDir);
1549
- if (!gate.passed) {
1550
- allPassed = false;
1551
- logger_1.logger.warn(` ❌ 质量门禁未通过`);
1552
- for (const f of gate.blockingFailed) {
1553
- logger_1.logger.warn(` ❌ ${f.name}: ${f.details}`);
1554
- await (0, issue_tracker_1.logIssue)(taskDir, {
1555
- type: f.name.includes('编译') || f.name.includes('测试') ? 'error' : 'technical',
1556
- severity: 'critical',
1557
- summary: `${f.name}: ${f.details}`,
1558
- detail: `任务: ${task.id},轮次: ${round}/3`,
1559
- });
1544
+ // ── Step 1: 契约冲突裁决 / 传统质量门禁 ──
1545
+ const arbConfig = await (0, arbitration_engine_1.getArbitrationConfig)();
1546
+ let testPassed = true;
1547
+ if (!arbConfig.enabled) {
1548
+ // 仲裁已禁用:回退到传统质量门禁
1549
+ const gate = await (0, verify_engine_1.runQualityGate)(task.id, taskCodePath, taskDir);
1550
+ await (0, verify_engine_1.writeVerifyReport)(gate.report, taskDir);
1551
+ if (options.auto) {
1552
+ logger_1.logger.info(` 🚧 质量门禁: ${gate.passed ? '✅ 通过' : '❌ 失败'} (arbitration=off)`);
1553
+ }
1554
+ else {
1555
+ logger_1.logger.info('');
1556
+ logger_1.logger.info(`🚧 传统质量门禁 — ${task.id}`);
1557
+ logger_1.logger.info(` ${gate.passed ? '✅ 全部通过' : `❌ ${gate.blockingFailed.length} 项阻塞性检查失败`}`);
1560
1558
  }
1559
+ if (!gate.passed) {
1560
+ allPassed = false;
1561
+ }
1562
+ const testCheck = gate.report.checks.find(c => c.name === '单元测试');
1563
+ testPassed = !testCheck || testCheck.status !== 'fail';
1561
1564
  }
1562
1565
  else {
1563
- logger_1.logger.info(` ✅ 质量门禁通过`);
1566
+ // 仲裁已启用:执行三级裁决
1567
+ const arbResult = await (0, arbitration_engine_1.runArbitration)(task.id, taskCodePath, taskDir, { mode: arbConfig.mode });
1568
+ await (0, verdict_generator_1.writeArbitrationReport)(arbResult.report, taskDir);
1569
+ if (options.auto) {
1570
+ // auto 模式:极简输出
1571
+ const totalFailed = arbResult.report.L1.failed + arbResult.report.L2.failed + arbResult.report.L3.failed;
1572
+ const modeLabel = arbConfig.mode === 'full' ? '' : ` [${arbConfig.mode}]`;
1573
+ if (totalFailed === 0) {
1574
+ logger_1.logger.info(` ⚖️ 契约裁决${modeLabel}: ✅ 全部通过`);
1575
+ }
1576
+ else {
1577
+ logger_1.logger.info(` ⚖️ 契约裁决${modeLabel}: ❌ L1=${arbResult.report.L1.failed} L2=${arbResult.report.L2.pending} L3=${arbResult.report.L3.pending}`);
1578
+ }
1579
+ }
1580
+ else {
1581
+ // 正常模式:完整输出
1582
+ logger_1.logger.info('');
1583
+ logger_1.logger.info(`⚖️ 契约冲突裁决 — ${task.id}${arbConfig.mode !== 'full' ? ` [mode=${arbConfig.mode}]` : ''}`);
1584
+ // L1 机器契约
1585
+ if (arbResult.report.L1.total > 0) {
1586
+ logger_1.logger.info(` ⚙️ L1 机器契约: ${arbResult.report.L1.passed}/${arbResult.report.L1.total} 通过`);
1587
+ if (arbResult.report.L1.failed > 0) {
1588
+ logger_1.logger.warn(` ❌ ${arbResult.report.L1.failed} 项致命错误,已自动裁决驳回`);
1589
+ allPassed = false;
1590
+ }
1591
+ }
1592
+ else {
1593
+ logger_1.logger.info(` ⚙️ L1 机器契约: ✅ 全部通过`);
1594
+ }
1595
+ // L2 规范契约
1596
+ if (arbResult.report.L2.total > 0) {
1597
+ logger_1.logger.info(` 🤖 L2 规范契约: ${arbResult.report.L2.passed}/${arbResult.report.L2.total} 通过, ${arbResult.report.L2.pending} 待确认`);
1598
+ if (arbResult.report.L2.pending > 0) {
1599
+ logger_1.logger.info(` 💡 ${arbResult.report.L2.pending} 项需确认修复方案(见 ARBITRATION_REPORT.md)`);
1600
+ }
1601
+ if (arbResult.report.L2.failed > 0) {
1602
+ allPassed = false;
1603
+ }
1604
+ }
1605
+ else {
1606
+ logger_1.logger.info(` 🤖 L2 规范契约: ✅ 全部通过`);
1607
+ }
1608
+ // L3 架构契约
1609
+ if (arbResult.report.L3.total > 0) {
1610
+ logger_1.logger.info(` 👤 L3 架构契约: ${arbResult.report.L3.passed}/${arbResult.report.L3.total} 通过, ${arbResult.report.L3.pending} 待裁决`);
1611
+ if (arbResult.report.L3.pending > 0) {
1612
+ logger_1.logger.warn(` ⚠️ ${arbResult.report.L3.pending} 项需人工裁决`);
1613
+ logger_1.logger.info(` 执行: speccore verdict --list --task ${task.id}`);
1614
+ allPassed = false;
1615
+ }
1616
+ }
1617
+ else {
1618
+ logger_1.logger.info(` 👤 L3 架构契约: ✅ 全部通过`);
1619
+ }
1620
+ }
1621
+ if (!arbResult.canProceed) {
1622
+ allPassed = false;
1623
+ if (!options.auto) {
1624
+ for (const c of arbResult.report.conflicts.filter(c => c.level === 'L1' && c.status === 'resolved')) {
1625
+ await (0, issue_tracker_1.logIssue)(taskDir, {
1626
+ type: 'error',
1627
+ severity: 'critical',
1628
+ summary: `L1 契约违反: ${c.contractName}`,
1629
+ detail: `任务: ${task.id},轮次: ${round}/3,${c.message}`,
1630
+ });
1631
+ }
1632
+ }
1633
+ }
1634
+ const testConflict = arbResult.report.conflicts.find(c => c.contractName === '单元测试通过');
1635
+ testPassed = !testConflict || testConflict.status !== 'resolved';
1564
1636
  }
1565
1637
  // ── Step 2: 文档同步 — 根据单元测试结果更新 TEST.md ──
1566
- const testCheck = gate.report.checks.find(c => c.name === '单元测试');
1567
- const testPassed = testCheck?.status === 'pass';
1568
1638
  await (0, verify_engine_1.syncTestDocFromResults)(taskDir, testPassed);
1569
1639
  // ── Step 3: 检查 REVIEW.md(人工审查清单)──
1570
1640
  const platDirsRound = await getPlatformSubtaskDirs(taskDir);
@@ -1625,7 +1695,8 @@ async function executionVerifyLoop(tasks, iteration, options) {
1625
1695
  if (round < maxRounds) {
1626
1696
  logger_1.logger.info(` 💡 AI 将修复未通过项。使用 speccore execute --task=${task.id} --force 重新执行代码生成`);
1627
1697
  await (0, fs_extra_1.writeFile)((0, path_1.join)(taskDir, '.needs-retry'), String(round));
1628
- // 输出 [SPECCORE_EXEC] 让 AI 修复
1698
+ // 输出 [SPECCORE_EXEC] 让 AI 修复(回退到质量门禁报告)
1699
+ const gate = await (0, verify_engine_1.runQualityGate)(task.id, taskCodePath, taskDir);
1629
1700
  if (!gate.passed) {
1630
1701
  await (0, verify_engine_1.outputFixTag)(gate.report, taskDir, round);
1631
1702
  }
@@ -1635,29 +1706,60 @@ async function executionVerifyLoop(tasks, iteration, options) {
1635
1706
  if (allPassed) {
1636
1707
  await (0, fs_extra_1.writeFile)((0, path_1.join)(taskDir, '.verification'), 'passed');
1637
1708
  logger_1.logger.info(` ✅ ${task.id} 全部检查通过,可以 speccore done`);
1638
- // v8.2.0+: 执行通过后检测可复用模式候选
1709
+ // v8.3.23+: 执行通过后检测可复用模式候选(适配端平铺结构 + 自动写入)
1639
1710
  try {
1640
- const codeDirs = [
1641
- (0, path_1.join)(taskDir, '10-backend'),
1642
- (0, path_1.join)(taskDir, '20-frontend'),
1643
- (0, path_1.join)(taskDir, 'src'),
1644
- ];
1711
+ const codeDirs = await (0, pattern_detector_1.resolveCodeDirsFromTask)(taskDir);
1712
+ if (codeDirs.length === 0) {
1713
+ // 无代码目录时静默跳过(代码可能在外部工程)
1714
+ return;
1715
+ }
1645
1716
  const candidates = await (0, pattern_detector_1.detectPatternCandidates)(codeDirs, `task:${task.id}`);
1646
- if (candidates.length > 0) {
1717
+ if (candidates.length === 0)
1718
+ return;
1719
+ const mode = await (0, pattern_detector_1.getPatternAutoSaveMode)();
1720
+ const autoSaved = [];
1721
+ const manual = [];
1722
+ for (const c of candidates) {
1723
+ const result = await (0, pattern_detector_1.autoSavePattern)(c, `task:${task.id}`, mode);
1724
+ if (result.saved && result.path) {
1725
+ autoSaved.push(`${c.name} [${result.confidence}]`);
1726
+ }
1727
+ else if (!(0, pattern_detector_1.isHighConfidenceCandidate)(c) && mode === 'smart') {
1728
+ manual.push(`${c.name} [${c.category}]`);
1729
+ }
1730
+ }
1731
+ logger_1.logger.info('');
1732
+ logger_1.logger.info('🧩 执行完成,检测到以下可复用模式候选:');
1733
+ const byPlatform = (0, pattern_detector_1.groupCandidatesByPlatform)(candidates);
1734
+ for (const [plat, list] of Object.entries(byPlatform)) {
1735
+ const platLabel = plat === 'shared' ? '🌐 跨端共享' : plat === 'backend' ? '⚙️ 后端' : plat === 'frontend' ? '🎨 前端' : '📦 其他';
1736
+ logger_1.logger.info(` ${platLabel}:`);
1737
+ for (const c of list.slice(0, 2)) {
1738
+ logger_1.logger.info(` • ${c.name} [${c.category}] — ${c.reason}`);
1739
+ }
1740
+ if (list.length > 2) {
1741
+ logger_1.logger.info(` ... 还有 ${list.length - 2} 个`);
1742
+ }
1743
+ }
1744
+ if (autoSaved.length > 0) {
1647
1745
  logger_1.logger.info('');
1648
- logger_1.logger.info('🧩 执行完成,检测到以下可复用模式候选:');
1649
- const byPlatform = (0, pattern_detector_1.groupCandidatesByPlatform)(candidates);
1650
- for (const [plat, list] of Object.entries(byPlatform)) {
1651
- const platLabel = plat === 'shared' ? '🌐 跨端共享' : plat === 'backend' ? '⚙️ 后端' : plat === 'frontend' ? '🎨 前端' : '📦 其他';
1652
- logger_1.logger.info(` ${platLabel}:`);
1653
- for (const c of list.slice(0, 2)) {
1654
- logger_1.logger.info(` • ${c.name} [${c.category}] — ${c.reason}`);
1655
- }
1656
- if (list.length > 2) {
1657
- logger_1.logger.info(` ... 还有 ${list.length - 2} 个`);
1658
- }
1746
+ logger_1.logger.info(` ✅ 已自动保存 ${autoSaved.length} 个高置信度模式到 .speccore/PATTERNS/`);
1747
+ for (const s of autoSaved.slice(0, 3)) {
1748
+ logger_1.logger.info(` • ${s}`);
1659
1749
  }
1660
- logger_1.logger.info(` 💡 有价值?执行 speccore pattern save --name=<模式名> --file=<文件路径>`);
1750
+ }
1751
+ if (manual.length > 0 && mode === 'smart') {
1752
+ logger_1.logger.info('');
1753
+ logger_1.logger.info(` 💡 以下 ${manual.length} 个候选置信度较低,建议手动确认后保存:`);
1754
+ for (const m of manual.slice(0, 3)) {
1755
+ logger_1.logger.info(` • ${m}`);
1756
+ }
1757
+ logger_1.logger.info(' 命令: speccore pattern save --name=<模式名> --file=<文件路径>');
1758
+ }
1759
+ if (mode === 'off') {
1760
+ logger_1.logger.info('');
1761
+ logger_1.logger.info(' 💡 检测到可复用模式,自动保存已关闭。如需保存请执行:');
1762
+ logger_1.logger.info(' speccore pattern save --name=<模式名> --file=<文件路径>');
1661
1763
  }
1662
1764
  }
1663
1765
  catch { /* 静默失败 */ }