autosnippet 3.3.4 → 3.3.6

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 (221) hide show
  1. package/README.md +174 -83
  2. package/config/constitution.yaml +2 -0
  3. package/dashboard/dist/assets/icons-D1aVZYFW.js +1 -0
  4. package/dashboard/dist/assets/index-CxHOu8Hd.css +1 -0
  5. package/dashboard/dist/assets/index-DDdAOpYT.js +128 -0
  6. package/dashboard/dist/index.html +3 -3
  7. package/dist/bin/api-server.js +1 -0
  8. package/dist/bin/cli.d.ts +1 -0
  9. package/dist/bin/cli.js +136 -9
  10. package/dist/lib/agent/AgentFactory.d.ts +0 -17
  11. package/dist/lib/agent/AgentFactory.js +1 -25
  12. package/dist/lib/agent/capabilities.d.ts +11 -0
  13. package/dist/lib/agent/capabilities.js +29 -5
  14. package/dist/lib/agent/context/ExplorationTracker.js +10 -1
  15. package/dist/lib/agent/context/exploration/ExplorationStrategies.d.ts +2 -0
  16. package/dist/lib/agent/context/exploration/ExplorationStrategies.js +2 -2
  17. package/dist/lib/agent/domain/insight-analyst.d.ts +47 -3
  18. package/dist/lib/agent/domain/insight-analyst.js +111 -11
  19. package/dist/lib/agent/domain/insight-evolver.d.ts +69 -0
  20. package/dist/lib/agent/domain/insight-evolver.js +230 -0
  21. package/dist/lib/agent/domain/insight-gate.d.ts +42 -0
  22. package/dist/lib/agent/domain/insight-gate.js +41 -0
  23. package/dist/lib/agent/domain/insight-producer.d.ts +27 -2
  24. package/dist/lib/agent/domain/insight-producer.js +60 -5
  25. package/dist/lib/agent/domain/scan-prompts.js +10 -7
  26. package/dist/lib/agent/memory/ActiveContext.d.ts +2 -28
  27. package/dist/lib/agent/memory/MemoryCoordinator.d.ts +2 -2
  28. package/dist/lib/agent/memory/SessionStore.d.ts +6 -12
  29. package/dist/lib/agent/memory/SessionStore.js +9 -15
  30. package/dist/lib/agent/memory/memory-flush-contract.d.ts +49 -0
  31. package/dist/lib/agent/memory/memory-flush-contract.js +16 -0
  32. package/dist/lib/agent/memory/session-store-schema.d.ts +20 -0
  33. package/dist/lib/agent/memory/session-store-schema.js +41 -0
  34. package/dist/lib/agent/presets.d.ts +89 -1
  35. package/dist/lib/agent/presets.js +53 -5
  36. package/dist/lib/agent/tools/_shared.d.ts +7 -15
  37. package/dist/lib/agent/tools/_shared.js +20 -21
  38. package/dist/lib/agent/tools/composite.d.ts +25 -22
  39. package/dist/lib/agent/tools/composite.js +108 -109
  40. package/dist/lib/agent/tools/evolution-tools.d.ts +145 -0
  41. package/dist/lib/agent/tools/evolution-tools.js +161 -0
  42. package/dist/lib/agent/tools/index.d.ts +163 -92
  43. package/dist/lib/agent/tools/index.js +9 -1
  44. package/dist/lib/agent/tools/lifecycle.d.ts +7 -1
  45. package/dist/lib/agent/tools/lifecycle.js +59 -75
  46. package/dist/lib/cli/AiScanService.js +1 -1
  47. package/dist/lib/cli/KnowledgeSyncService.d.ts +5 -1
  48. package/dist/lib/cli/KnowledgeSyncService.js +6 -3
  49. package/dist/lib/core/AstAnalyzer.d.ts +1 -0
  50. package/dist/lib/{service/bootstrap/DimensionCopyRegistry.d.ts → domain/dimension/DimensionCopy.d.ts} +2 -2
  51. package/dist/lib/{service/bootstrap/DimensionCopyRegistry.js → domain/dimension/DimensionCopy.js} +22 -72
  52. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +54 -0
  53. package/dist/lib/domain/dimension/DimensionRegistry.js +620 -0
  54. package/dist/lib/domain/dimension/DimensionSop.d.ts +55 -0
  55. package/dist/lib/domain/dimension/DimensionSop.js +1604 -0
  56. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +61 -0
  57. package/dist/lib/domain/dimension/UnifiedDimension.js +53 -0
  58. package/dist/lib/domain/dimension/index.d.ts +10 -0
  59. package/dist/lib/domain/dimension/index.js +9 -0
  60. package/dist/lib/domain/knowledge/FieldSpec.d.ts +1 -1
  61. package/dist/lib/domain/knowledge/FieldSpec.js +29 -16
  62. package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +33 -111
  63. package/dist/lib/domain/knowledge/KnowledgeEntry.js +27 -6
  64. package/dist/lib/domain/knowledge/KnowledgeRepository.d.ts +1 -0
  65. package/dist/lib/domain/knowledge/KnowledgeRepository.js +3 -0
  66. package/dist/lib/domain/knowledge/Lifecycle.js +1 -1
  67. package/dist/lib/domain/knowledge/StyleGuide.d.ts +1 -1
  68. package/dist/lib/domain/knowledge/StyleGuide.js +1 -1
  69. package/dist/lib/domain/knowledge/UnifiedValidator.js +15 -0
  70. package/dist/lib/domain/knowledge/values/Stats.d.ts +1 -1
  71. package/dist/lib/domain/knowledge/values/Stats.js +2 -2
  72. package/dist/lib/external/mcp/McpServer.js +4 -0
  73. package/dist/lib/external/mcp/handlers/TargetClassifier.d.ts +1 -1
  74. package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.d.ts +8 -16
  75. package/dist/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +10 -10
  76. package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.d.ts +7 -0
  77. package/dist/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +20 -0
  78. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +52 -132
  79. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +204 -17
  80. package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.d.ts +11 -75
  81. package/dist/lib/external/mcp/handlers/bootstrap/base-dimensions.js +40 -191
  82. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.d.ts +13 -78
  83. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +30 -52
  84. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.d.ts +0 -1
  85. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.d.ts +99 -12
  86. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +172 -161
  87. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +7 -17
  88. package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.d.ts +46 -0
  89. package/dist/lib/external/mcp/handlers/bootstrap/shared/async-fill-helpers.js +58 -0
  90. package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.d.ts +25 -0
  91. package/dist/lib/external/mcp/handlers/bootstrap/shared/audit-helpers.js +47 -0
  92. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +50 -12
  93. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +30 -10
  94. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-text.js +1 -1
  95. package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.d.ts +24 -0
  96. package/dist/lib/external/mcp/handlers/bootstrap/shared/handler-types.js +14 -0
  97. package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.d.ts +14 -0
  98. package/dist/lib/external/mcp/handlers/bootstrap/shared/panorama-utils.js +48 -0
  99. package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.d.ts +21 -0
  100. package/dist/lib/external/mcp/handlers/bootstrap/shared/session-helpers.js +45 -0
  101. package/dist/lib/external/mcp/handlers/bootstrap/shared/skill-generator.d.ts +1 -1
  102. package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.d.ts +27 -0
  103. package/dist/lib/external/mcp/handlers/bootstrap/shared/target-file-map.js +44 -0
  104. package/dist/lib/external/mcp/handlers/bootstrap-external.d.ts +14 -10
  105. package/dist/lib/external/mcp/handlers/bootstrap-external.js +39 -51
  106. package/dist/lib/external/mcp/handlers/bootstrap-internal.d.ts +2 -0
  107. package/dist/lib/external/mcp/handlers/bootstrap-internal.js +115 -82
  108. package/dist/lib/external/mcp/handlers/consolidated.d.ts +4 -4
  109. package/dist/lib/external/mcp/handlers/consolidated.js +115 -162
  110. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +69 -1
  111. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +54 -0
  112. package/dist/lib/external/mcp/handlers/evolve-external.js +226 -0
  113. package/dist/lib/external/mcp/handlers/knowledge.js +26 -2
  114. package/dist/lib/external/mcp/handlers/rescan-external.d.ts +76 -0
  115. package/dist/lib/external/mcp/handlers/rescan-external.js +335 -0
  116. package/dist/lib/external/mcp/handlers/rescan-internal.d.ts +120 -0
  117. package/dist/lib/external/mcp/handlers/rescan-internal.js +359 -0
  118. package/dist/lib/external/mcp/handlers/search.d.ts +6 -5
  119. package/dist/lib/external/mcp/handlers/search.js +6 -5
  120. package/dist/lib/external/mcp/handlers/types.d.ts +2 -1
  121. package/dist/lib/external/mcp/handlers/wiki-external.js +2 -2
  122. package/dist/lib/external/mcp/tools.d.ts +8 -18
  123. package/dist/lib/external/mcp/tools.js +60 -3
  124. package/dist/lib/http/routes/knowledge.js +122 -1
  125. package/dist/lib/http/routes/modules.js +25 -3
  126. package/dist/lib/http/routes/panorama.js +16 -4
  127. package/dist/lib/infrastructure/cache/CacheCoordinator.d.ts +41 -0
  128. package/dist/lib/infrastructure/cache/CacheCoordinator.js +105 -0
  129. package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.d.ts +7 -0
  130. package/dist/lib/infrastructure/database/migrations/006_lifecycle_transition_events.js +28 -0
  131. package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +1 -1
  132. package/dist/lib/injection/ServiceContainer.js +55 -0
  133. package/dist/lib/injection/ServiceMap.d.ts +8 -1
  134. package/dist/lib/injection/modules/InfraModule.js +4 -1
  135. package/dist/lib/injection/modules/KnowledgeModule.js +38 -1
  136. package/dist/lib/repository/evolution/ProposalRepository.d.ts +99 -0
  137. package/dist/lib/repository/evolution/ProposalRepository.js +255 -0
  138. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +4 -0
  139. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +16 -1
  140. package/dist/lib/service/bootstrap/BootstrapEventEmitter.d.ts +3 -2
  141. package/dist/lib/service/bootstrap/BootstrapEventEmitter.js +1 -1
  142. package/dist/lib/service/bootstrap/DeliveryVerifier.d.ts +51 -0
  143. package/dist/lib/service/bootstrap/DeliveryVerifier.js +163 -0
  144. package/dist/lib/service/bootstrap/UiStartupTasks.d.ts +22 -4
  145. package/dist/lib/service/bootstrap/UiStartupTasks.js +73 -5
  146. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +54 -0
  147. package/dist/lib/service/bootstrap/bootstrap-event-types.js +10 -0
  148. package/dist/lib/service/cleanup/CleanupService.d.ts +85 -0
  149. package/dist/lib/service/cleanup/CleanupService.js +324 -0
  150. package/dist/lib/service/delivery/AgentInstructionsGenerator.js +39 -43
  151. package/dist/lib/service/delivery/FileProtection.d.ts +20 -0
  152. package/dist/lib/service/delivery/FileProtection.js +54 -0
  153. package/dist/lib/service/delivery/SkillsSyncer.js +16 -21
  154. package/dist/lib/service/evolution/ContentPatcher.d.ts +44 -0
  155. package/dist/lib/service/evolution/ContentPatcher.js +310 -0
  156. package/dist/lib/service/evolution/DecayDetector.d.ts +4 -3
  157. package/dist/lib/service/evolution/DecayDetector.js +97 -22
  158. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -2
  159. package/dist/lib/service/evolution/KnowledgeMetabolism.js +29 -2
  160. package/dist/lib/service/evolution/ProposalExecutor.d.ts +66 -0
  161. package/dist/lib/service/evolution/ProposalExecutor.js +424 -0
  162. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +64 -0
  163. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +458 -0
  164. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +89 -0
  165. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +492 -0
  166. package/dist/lib/service/evolution/StagingManager.js +5 -3
  167. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +44 -0
  168. package/dist/lib/service/evolution/createSupersedeProposal.js +81 -0
  169. package/dist/lib/service/guard/ComplianceReporter.d.ts +4 -0
  170. package/dist/lib/service/guard/ComplianceReporter.js +51 -0
  171. package/dist/lib/service/guard/GuardCheckEngine.js +5 -4
  172. package/dist/lib/service/guard/GuardCrossFileChecks.js +2 -0
  173. package/dist/lib/service/guard/ReverseGuard.d.ts +1 -1
  174. package/dist/lib/service/guard/ReverseGuard.js +32 -2
  175. package/dist/lib/service/knowledge/ConfidenceRouter.js +1 -1
  176. package/dist/lib/service/knowledge/KnowledgeService.d.ts +11 -1
  177. package/dist/lib/service/knowledge/KnowledgeService.js +44 -4
  178. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +225 -0
  179. package/dist/lib/service/knowledge/RecipeProductionGateway.js +384 -0
  180. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +2 -0
  181. package/dist/lib/service/knowledge/SourceRefReconciler.js +48 -0
  182. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +3 -2
  183. package/dist/lib/service/panorama/DimensionAnalyzer.js +15 -140
  184. package/dist/lib/service/search/BM25Scorer.d.ts +2 -2
  185. package/dist/lib/service/search/SearchEngine.d.ts +11 -10
  186. package/dist/lib/service/search/SearchEngine.js +38 -36
  187. package/dist/lib/service/search/SearchTypes.d.ts +14 -8
  188. package/dist/lib/service/search/SearchTypes.js +1 -1
  189. package/dist/lib/service/search/tokenizer.d.ts +1 -1
  190. package/dist/lib/service/search/tokenizer.js +2 -2
  191. package/dist/lib/shared/schemas/common.d.ts +4 -4
  192. package/dist/lib/shared/schemas/http-requests.d.ts +12 -1
  193. package/dist/lib/shared/schemas/http-requests.js +8 -0
  194. package/dist/lib/shared/schemas/mcp-tools.d.ts +33 -2
  195. package/dist/lib/shared/schemas/mcp-tools.js +42 -0
  196. package/dist/lib/types/evolution.d.ts +135 -0
  197. package/dist/lib/types/evolution.js +6 -0
  198. package/dist/lib/types/graph-shared.d.ts +25 -0
  199. package/dist/lib/types/graph-shared.js +7 -0
  200. package/dist/lib/types/knowledge-wire.d.ts +131 -0
  201. package/dist/lib/types/knowledge-wire.js +7 -0
  202. package/dist/lib/types/project-snapshot-builder.d.ts +19 -0
  203. package/dist/lib/types/project-snapshot-builder.js +189 -0
  204. package/dist/lib/types/project-snapshot.d.ts +399 -0
  205. package/dist/lib/types/project-snapshot.js +17 -0
  206. package/dist/lib/types/search-wire.d.ts +46 -0
  207. package/dist/lib/types/search-wire.js +7 -0
  208. package/dist/lib/types/snapshot-views.d.ts +58 -0
  209. package/dist/lib/types/snapshot-views.js +103 -0
  210. package/package.json +1 -1
  211. package/skills/autosnippet-recipes/SKILL.md +1 -1
  212. package/templates/instructions/agent-static.md +2 -0
  213. package/templates/instructions/conventions.md +3 -1
  214. package/templates/recipes-setup/README.md +2 -2
  215. package/dashboard/dist/assets/icons-BJ2mUBi8.js +0 -1
  216. package/dashboard/dist/assets/index-B659K9t5.js +0 -128
  217. package/dashboard/dist/assets/index-NCm40PMD.css +0 -1
  218. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.d.ts +0 -169
  219. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +0 -727
  220. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.d.ts +0 -370
  221. package/dist/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +0 -821
@@ -0,0 +1,335 @@
1
+ /**
2
+ * MCP Handler — autosnippet_rescan (增量知识更新)
3
+ *
4
+ * 保留已审核 Recipe,清理衍生缓存,全量/指定维度重新扫描,
5
+ * 新知识通过批量提交走正常的进化架构。
6
+ *
7
+ * 流程:
8
+ * 1. snapshotRecipes — 快照保留知识
9
+ * 2. rescanClean — 清理衍生缓存
10
+ * 3. Phase 1-4 全量分析
11
+ * 4. RecipeRelevanceAuditor — 证据验证 + 快速衰退
12
+ * 5. 构建 Mission Briefing(含 allRecipes + evolutionGuide)
13
+ * 6. 返回给 Agent 按维度执行: evolve → gap-fill → dimension_complete
14
+ *
15
+ * @module handlers/rescan-external
16
+ */
17
+ import path from 'node:path';
18
+ import { CleanupService } from '#service/cleanup/CleanupService.js';
19
+ import { RecipeRelevanceAuditor } from '#service/evolution/RecipeRelevanceAuditor.js';
20
+ import { resolveProjectRoot } from '#shared/resolveProjectRoot.js';
21
+ import { buildProjectSnapshot } from '#types/project-snapshot-builder.js';
22
+ import { toSessionCache } from '#types/snapshot-views.js';
23
+ import { envelope } from '../envelope.js';
24
+ import { buildMissionBriefing } from './bootstrap/MissionBriefingBuilder.js';
25
+ import { extractCodeEntities, extractDependencyEdges } from './bootstrap/shared/audit-helpers.js';
26
+ import { runAllPhases } from './bootstrap/shared/bootstrap-phases.js';
27
+ import { getOrCreateSessionManager } from './bootstrap/shared/session-helpers.js';
28
+ import { buildLanguageExtension } from './LanguageExtensions.js';
29
+ // ── Helpers ─────────────────────────────────────────────────
30
+ function truncate(s, max) {
31
+ if (!s) {
32
+ return '';
33
+ }
34
+ return s.length <= max ? s : `${s.slice(0, max)}…`;
35
+ }
36
+ // ── 主入口 ─────────────────────────────────────────────────
37
+ export async function rescanExternal(ctx, args) {
38
+ const t0 = Date.now();
39
+ const projectRoot = resolveProjectRoot(ctx.container);
40
+ const db = ctx.container.get('database');
41
+ // ═══════════════════════════════════════════════════════════
42
+ // Step 1: 快照现有知识
43
+ // ═══════════════════════════════════════════════════════════
44
+ const cleanupService = new CleanupService({
45
+ projectRoot,
46
+ db,
47
+ logger: ctx.logger,
48
+ });
49
+ const recipeSnapshot = await cleanupService.snapshotRecipes();
50
+ ctx.logger.info(`[Rescan] Preserved ${recipeSnapshot.count} recipes`, {
51
+ coverageByDimension: recipeSnapshot.coverageByDimension,
52
+ });
53
+ // ═══════════════════════════════════════════════════════════
54
+ // Step 2: 清理衍生缓存
55
+ // ═══════════════════════════════════════════════════════════
56
+ const cleanResult = await cleanupService.rescanClean();
57
+ // ═══════════════════════════════════════════════════════════
58
+ // Step 2.5: Recipe 文件 ↔ DB 一致性恢复 + 向量索引重建
59
+ // ═══════════════════════════════════════════════════════════
60
+ // 2.5a: KnowledgeSyncService — 恢复 Recipe 文件 ↔ DB 一致性
61
+ // rescanClean 保留了 recipes/ 文件和 active/published/staging/evolving DB 记录,
62
+ // 但清除了 recipe_source_refs 等桥接表,需重新同步。
63
+ try {
64
+ const syncService = ctx.container.services.knowledgeSyncService
65
+ ? ctx.container.get('knowledgeSyncService')
66
+ : null;
67
+ if (syncService) {
68
+ const rawDb = typeof db?.getDb === 'function'
69
+ ? db.getDb()
70
+ : db;
71
+ const syncReport = syncService.sync(rawDb, {
72
+ force: true,
73
+ });
74
+ ctx.logger.info('[Rescan] KnowledgeSyncService sync complete', {
75
+ synced: syncReport.synced,
76
+ created: syncReport.created,
77
+ updated: syncReport.updated,
78
+ });
79
+ }
80
+ }
81
+ catch (e) {
82
+ ctx.logger.warn(`[Rescan] KnowledgeSyncService sync failed (non-blocking): ${e instanceof Error ? e.message : String(e)}`);
83
+ }
84
+ // NOTE: 不在 rescan 中调用 VectorService.fullBuild()
85
+ // 理由:fullBuild 依赖外部 embedding API(LLM),在 MCP handler 同步路径中
86
+ // 引入 LLM 调用不合理(无超时、可能阻塞、需要 API key)。
87
+ // 向量索引会在后续 Agent 提交新知识时由 SyncCoordinator 增量更新。
88
+ // ═══════════════════════════════════════════════════════════
89
+ // Step 3: Phase 1-4 全量分析
90
+ // ═══════════════════════════════════════════════════════════
91
+ const phaseResults = await runAllPhases(projectRoot, ctx, {
92
+ maxFiles: 500,
93
+ contentMaxLines: 120,
94
+ sourceTag: 'rescan-external',
95
+ summaryPrefix: 'Rescan scan',
96
+ clearOldData: false, // 已由 rescanClean 清理
97
+ generateReport: true,
98
+ incremental: false,
99
+ });
100
+ // 空项目 fast-path
101
+ if (phaseResults.isEmpty) {
102
+ return envelope({
103
+ success: true,
104
+ data: { message: 'No source files found. Nothing to rescan.' },
105
+ meta: { tool: 'autosnippet_rescan', responseTimeMs: Date.now() - t0 },
106
+ });
107
+ }
108
+ const { allFiles, primaryLang, depGraphData, langStats, astProjectSummary, codeEntityResult, callGraphResult, guardAudit, activeDimensions: allDimensions, targetsSummary, localPackageModules, langProfile, } = phaseResults;
109
+ // ── Build immutable ProjectSnapshot ──
110
+ const snapshot = buildProjectSnapshot({
111
+ projectRoot,
112
+ sourceTag: 'rescan-external',
113
+ ...phaseResults,
114
+ report: phaseResults.report,
115
+ });
116
+ // ═══════════════════════════════════════════════════════════
117
+ // Step 4: Recipe 证据验证 + 快速衰退
118
+ // ═══════════════════════════════════════════════════════════
119
+ const auditor = new RecipeRelevanceAuditor({
120
+ db,
121
+ logger: ctx.logger,
122
+ });
123
+ const codeEntities = extractCodeEntities(astProjectSummary);
124
+ const dependencyEdges = extractDependencyEdges(depGraphData);
125
+ const auditSummary = await auditor.audit(recipeSnapshot.entries, {
126
+ fileList: allFiles.map((f) => f.relativePath || f.name),
127
+ codeEntities,
128
+ dependencyGraph: dependencyEdges,
129
+ });
130
+ // ═══════════════════════════════════════════════════════════
131
+ // Step 5: 构建 Mission Briefing + 过滤维度
132
+ // ═══════════════════════════════════════════════════════════
133
+ // 按需过滤维度
134
+ const dimensions = args.dimensions?.length
135
+ ? allDimensions.filter((d) => args.dimensions.includes(d.id))
136
+ : allDimensions;
137
+ // 创建 Session
138
+ const sessionManager = getOrCreateSessionManager(ctx.container);
139
+ const session = sessionManager.createSession({
140
+ projectRoot,
141
+ dimensions,
142
+ projectContext: {
143
+ projectName: path.basename(projectRoot),
144
+ primaryLang,
145
+ fileCount: allFiles.length,
146
+ modules: depGraphData?.nodes?.length || 0,
147
+ },
148
+ });
149
+ // 缓存 Phase 结果
150
+ session.setSnapshotCache(toSessionCache(snapshot));
151
+ // 构建 projectMeta
152
+ const projectMeta = {
153
+ name: path.basename(projectRoot),
154
+ primaryLanguage: primaryLang,
155
+ secondaryLanguages: langProfile.secondary || [],
156
+ isMultiLang: langProfile.isMultiLang || false,
157
+ fileCount: allFiles.length,
158
+ projectType: snapshot.discoverer.id,
159
+ projectRoot,
160
+ };
161
+ // 构建 Mission Briefing
162
+ const briefing = buildMissionBriefing({
163
+ projectMeta,
164
+ astData: astProjectSummary,
165
+ codeEntityResult,
166
+ callGraphResult,
167
+ depGraphData,
168
+ guardAudit,
169
+ targets: targetsSummary,
170
+ activeDimensions: dimensions,
171
+ session,
172
+ languageExtension: buildLanguageExtension(primaryLang),
173
+ languageStats: langStats,
174
+ panoramaResult: snapshot.panorama,
175
+ localPackageModules,
176
+ });
177
+ // 附加 warnings
178
+ if (phaseResults.warnings.length > 0) {
179
+ briefing.meta = briefing.meta || {};
180
+ briefing.meta.warnings = [...(briefing.meta.warnings || []), ...phaseResults.warnings];
181
+ }
182
+ // ═══════════════════════════════════════════════════════════
183
+ // Step 6: 注入 evidenceHints (含 trigger/维度/doClause)
184
+ // ═══════════════════════════════════════════════════════════
185
+ // 建立 recipeId → snapshot entry 映射,用于补充 audit 结果中缺少的字段
186
+ const snapshotById = new Map(recipeSnapshot.entries.map((e) => [e.id, e]));
187
+ // ── 构建 allRecipes: 全部 Recipe (healthy + decaying) 含完整内容 + auditHint ──
188
+ const allRecipes = auditSummary.results
189
+ .filter((r) => r.verdict !== 'dead') // dead 已直接 deprecated
190
+ .map((r) => {
191
+ const snap = snapshotById.get(r.recipeId);
192
+ const content = snap?.content;
193
+ const sourceRefs = (snap?.sourceRefs ?? []);
194
+ return {
195
+ id: r.recipeId,
196
+ title: r.title,
197
+ trigger: snap?.trigger || '',
198
+ knowledgeType: snap?.knowledgeType || '',
199
+ doClause: snap?.doClause || '',
200
+ lifecycle: snap?.lifecycle || 'active',
201
+ // 完整内容(截断控制)
202
+ content: content
203
+ ? {
204
+ markdown: truncate(content.markdown, 500),
205
+ rationale: truncate(content.rationale, 200),
206
+ coreCode: truncate(content.coreCode, 400),
207
+ }
208
+ : null,
209
+ sourceRefs: sourceRefs.slice(0, 5),
210
+ // 系统预检
211
+ auditHint: {
212
+ relevanceScore: r.relevanceScore,
213
+ verdict: r.verdict,
214
+ decayReasons: r.decayReasons || [],
215
+ },
216
+ };
217
+ });
218
+ const decayCount = allRecipes.filter((r) => r.auditHint.verdict === 'decay' || r.auditHint.verdict === 'severe').length;
219
+ // ── 按维度分组现有 recipes,计算每维度的补齐配额 ──
220
+ // 覆盖采用加权策略:
221
+ // - active/evolving: 确认知识,始终计入覆盖
222
+ // - staging + audit healthy/watch: 待审但仍有效的候选,计入覆盖
223
+ // - staging + audit decay/severe/dead: 已过时的候选,不计入覆盖但占位去重
224
+ const TARGET_PER_DIM = 5;
225
+ const auditVerdictMap = new Map(auditSummary.results.map((r) => [r.recipeId, r.verdict]));
226
+ const coverageByDim = {};
227
+ for (const entry of recipeSnapshot.entries) {
228
+ const dim = entry.knowledgeType || 'unknown';
229
+ const isConfirmed = entry.lifecycle === 'active' || entry.lifecycle === 'evolving';
230
+ const verdict = auditVerdictMap.get(entry.id);
231
+ // staging 条目:无 audit 结果时默认计入(首次冷启动后无 audit 数据),audit 通过时计入
232
+ const isHealthyStaging = entry.lifecycle === 'staging' && (!verdict || verdict === 'healthy' || verdict === 'watch');
233
+ if (isConfirmed || isHealthyStaging) {
234
+ if (!coverageByDim[dim]) {
235
+ coverageByDim[dim] = [];
236
+ }
237
+ coverageByDim[dim].push({
238
+ title: entry.title,
239
+ trigger: entry.trigger,
240
+ doClause: entry.doClause || '',
241
+ });
242
+ }
243
+ }
244
+ const dimensionGaps = dimensions.map((d) => {
245
+ const existing = coverageByDim[d.id] || [];
246
+ return {
247
+ dimensionId: d.id,
248
+ existingCount: existing.length,
249
+ gap: Math.max(0, TARGET_PER_DIM - existing.length),
250
+ existingTriggers: existing.map((e) => e.trigger).filter(Boolean),
251
+ };
252
+ });
253
+ const totalGap = dimensionGaps.reduce((sum, g) => sum + g.gap, 0);
254
+ // occupiedTriggers 包含全量(含 audit-failed 的 staging),防止 trigger 冲突
255
+ const occupiedTriggers = recipeSnapshot.entries.map((e) => e.trigger).filter(Boolean);
256
+ // ── 注入 evidenceHints (allRecipes + evolutionGuide + dimensionGaps) ──
257
+ briefing.evidenceHints = {
258
+ allRecipes,
259
+ rescanMode: true,
260
+ dimensionGaps,
261
+ evolutionGuide: {
262
+ decayCount,
263
+ totalCount: allRecipes.length,
264
+ instructions: decayCount > 0
265
+ ? `${decayCount} 个 Recipe 标记为衰退,需优先验证。每个维度内先 evolve 再补齐。`
266
+ : '所有 Recipe 状态健康,快速确认后补齐新知识。',
267
+ },
268
+ constraints: {
269
+ occupiedTriggers,
270
+ rules: [
271
+ '禁止提交 occupiedTriggers 列表中已存在的 trigger',
272
+ '每个维度的补齐数量参考 dimensionGaps[].gap,gap=0 的维度可以跳过或只提交真正的新发现',
273
+ '专注于尚未覆盖的新模式,不要重复已有知识的内容',
274
+ ],
275
+ },
276
+ };
277
+ // ── 覆盖 executionPlan.workflow 为 rescan 专属版本 (per-dimension evolve + gap-fill) ──
278
+ const briefingRecord = briefing;
279
+ if (briefingRecord.executionPlan && typeof briefingRecord.executionPlan === 'object') {
280
+ briefingRecord.executionPlan.workflow =
281
+ '【增量扫描模式 — 按维度 Evolve + Gap-Fill】 ' +
282
+ '对每个维度 (按 tiers 顺序): ' +
283
+ 'Step 1 — Evolve (维度级首步): ' +
284
+ '过滤 allRecipes 中本维度的 Recipe,读 sourceRefs 源码验证 → ' +
285
+ '调用 autosnippet_evolve({ decisions: [本维度决策] }) → ' +
286
+ 'Step 2 — Gap-Fill: ' +
287
+ '分析代码发现新模式 → 调用 autosnippet_submit_knowledge 提交 (数量参考 gap 值) → ' +
288
+ 'Step 3 — Complete: 调用 autosnippet_dimension_complete 完成维度';
289
+ }
290
+ const dimGapLog = dimensionGaps
291
+ .map((g) => `${g.dimensionId}(${g.existingCount}→gap ${g.gap})`)
292
+ .join(', ');
293
+ ctx.logger.info(`[Rescan] Mission Briefing ready: ${allFiles.length} files, ${dimensions.length} dims, ` +
294
+ `preserved: ${recipeSnapshot.count}, decayed: ${decayCount}, totalGap: ${totalGap} — session ${session.id}`);
295
+ ctx.logger.info(`[Rescan] Dimension gaps: ${dimGapLog}`);
296
+ // ── 构建 gap 摘要信息 ──
297
+ const gapSummaryParts = dimensionGaps
298
+ .filter((g) => g.gap > 0)
299
+ .map((g) => `${g.dimensionId}(需补${g.gap}条)`);
300
+ const coveredDims = dimensionGaps.filter((g) => g.gap === 0).length;
301
+ const gapSummary = gapSummaryParts.length > 0
302
+ ? `需补齐维度: ${gapSummaryParts.join('、')}。`
303
+ : '所有维度已充分覆盖,仅在发现全新模式时提交。';
304
+ return envelope({
305
+ success: true,
306
+ data: {
307
+ rescan: {
308
+ preservedRecipes: recipeSnapshot.count,
309
+ cleanedTables: cleanResult.clearedTables.length,
310
+ cleanedFiles: cleanResult.deletedFiles,
311
+ reason: args.reason || null,
312
+ },
313
+ relevanceAudit: {
314
+ totalAudited: auditSummary.totalAudited,
315
+ healthy: auditSummary.healthy,
316
+ watch: auditSummary.watch,
317
+ decay: auditSummary.decay,
318
+ severe: auditSummary.severe,
319
+ dead: auditSummary.dead,
320
+ proposalsCreated: auditSummary.proposalsCreated,
321
+ immediateDeprecated: auditSummary.immediateDeprecated,
322
+ },
323
+ ...briefing,
324
+ },
325
+ message: `✅ Rescan 完成项目扫描,保留 ${recipeSnapshot.count} 个 Recipe(衰退 ${decayCount} 个),` +
326
+ `${coveredDims}/${dimensions.length} 个维度已充分覆盖。` +
327
+ `${gapSummary}` +
328
+ `对每个维度执行三步:` +
329
+ `(1) autosnippet_evolve — 过滤 allRecipes 中本维度 Recipe,读源码验证后提交决策 → ` +
330
+ `(2) autosnippet_submit_knowledge — 分析代码,发现未覆盖的新模式 → ` +
331
+ `(3) autosnippet_dimension_complete — 标记维度完成。` +
332
+ `注意: evidenceHints.constraints.occupiedTriggers 中的 trigger 已被占用,请勿重复。`,
333
+ meta: { tool: 'autosnippet_rescan', responseTimeMs: Date.now() - t0 },
334
+ });
335
+ }
@@ -0,0 +1,120 @@
1
+ /**
2
+ * rescan-internal.ts — 内部 Agent 增量扫描
3
+ *
4
+ * 与 rescan-external.ts(为外部 IDE Agent 生成 Mission Briefing)不同,
5
+ * 本文件由内置 AI pipeline(fillDimensionsV3)在服务端自动完成知识补齐。
6
+ *
7
+ * 流程:
8
+ * 1. snapshotRecipes — 快照保留知识
9
+ * 2. rescanClean — 清理衍生缓存
10
+ * 2.5 Recipe 文件 ↔ DB 一致性恢复
11
+ * 3. Phase 1-4 全量分析(文件收集→AST→依赖→Guard→维度)
12
+ * 4. RecipeRelevanceAuditor — 证据验证 + 快速衰退
13
+ * 5. 计算 gap 维度(需要补齐的维度)
14
+ * 5.5 BootstrapSessionManager — 缓存 Phase 结果供复用
15
+ * 6. 快速返回骨架 → 异步 fillDimensionsV3 填充 gap 维度
16
+ * 7. 前端通过 Socket.io 接收维度完成进度
17
+ *
18
+ * @module handlers/rescan-internal
19
+ */
20
+ import type { RescanInput } from '#shared/schemas/mcp-tools.js';
21
+ import type { McpContext } from './types.js';
22
+ interface RescanLogger {
23
+ info(...args: unknown[]): void;
24
+ warn(...args: unknown[]): void;
25
+ error(...args: unknown[]): void;
26
+ }
27
+ interface RescanMcpContext extends McpContext {
28
+ logger: RescanLogger;
29
+ }
30
+ interface RescanInternalArgs extends RescanInput {
31
+ /** 跳过异步填充(测试用) */
32
+ skipAsyncFill?: boolean;
33
+ }
34
+ /**
35
+ * rescanInternal — 内部 Agent 增量扫描
36
+ *
37
+ * 同步返回骨架(含 audit 摘要 + 异步会话 ID),
38
+ * 后台通过 fillDimensionsV3 对 gap 维度执行 AI 补齐。
39
+ */
40
+ export declare function rescanInternal(ctx: RescanMcpContext, args: RescanInternalArgs): Promise<{
41
+ success: boolean;
42
+ errorCode: string | null;
43
+ message: string;
44
+ data: {
45
+ message: string;
46
+ } | null;
47
+ meta: {
48
+ source?: string | undefined;
49
+ responseTimeMs?: number | undefined;
50
+ version: string;
51
+ tool?: string | undefined;
52
+ };
53
+ } | {
54
+ success: boolean;
55
+ errorCode: string | null;
56
+ message: string;
57
+ data: {
58
+ rescan: {
59
+ preservedRecipes: number;
60
+ cleanedTables: number;
61
+ cleanedFiles: number;
62
+ reason: string | null;
63
+ };
64
+ relevanceAudit: {
65
+ totalAudited: number;
66
+ healthy: number;
67
+ watch: number;
68
+ decay: number;
69
+ severe: number;
70
+ dead: number;
71
+ proposalsCreated: number;
72
+ immediateDeprecated: number;
73
+ };
74
+ gapAnalysis: {
75
+ totalDimensions: number;
76
+ gapDimensions: number;
77
+ skippedDimensions: string[];
78
+ gaps: {
79
+ dimensionId: string;
80
+ label: string | undefined;
81
+ existing: number;
82
+ gap: number;
83
+ }[];
84
+ };
85
+ languageStats: Record<string, number>;
86
+ primaryLanguage: string | null;
87
+ guardSummary: {
88
+ totalViolations: number;
89
+ errors: number;
90
+ warnings: number;
91
+ } | null;
92
+ astSummary: {
93
+ classes: number;
94
+ protocols: number;
95
+ categories: number;
96
+ } | null;
97
+ codeEntityGraph: {
98
+ totalEntities: number;
99
+ totalEdges: number;
100
+ } | null;
101
+ callGraph: {
102
+ entitiesUpserted: number;
103
+ edgesCreated: number;
104
+ } | null;
105
+ panorama: Record<string, unknown> | null;
106
+ bootstrapSession: Record<string, unknown> | null;
107
+ sessionId: string | null;
108
+ asyncFill: boolean;
109
+ status: string;
110
+ files: number;
111
+ targets: number;
112
+ } | null;
113
+ meta: {
114
+ source?: string | undefined;
115
+ responseTimeMs?: number | undefined;
116
+ version: string;
117
+ tool?: string | undefined;
118
+ };
119
+ }>;
120
+ export {};