autosnippet 3.0.0 → 3.0.2

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 (290) hide show
  1. package/README.md +230 -324
  2. package/bin/api-server.js +1 -1
  3. package/bin/cli.js +204 -244
  4. package/bin/mcp-server.js +5 -3
  5. package/config/knowledge-base.config.js +132 -132
  6. package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
  7. package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
  8. package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
  9. package/dashboard/dist/index.html +3 -3
  10. package/lib/bootstrap.js +8 -8
  11. package/lib/cli/AiScanService.js +86 -40
  12. package/lib/cli/KnowledgeSyncService.js +113 -74
  13. package/lib/cli/SetupService.js +439 -277
  14. package/lib/cli/UpgradeService.js +63 -100
  15. package/lib/core/AstAnalyzer.js +276 -597
  16. package/lib/core/ast/ProjectGraph.js +101 -40
  17. package/lib/core/ast/ensure-grammars.js +232 -0
  18. package/lib/core/ast/index.js +115 -0
  19. package/lib/core/ast/lang-dart.js +661 -0
  20. package/lib/core/ast/lang-go.js +530 -0
  21. package/lib/core/ast/lang-java.js +435 -0
  22. package/lib/core/ast/lang-javascript.js +272 -0
  23. package/lib/core/ast/lang-kotlin.js +423 -0
  24. package/lib/core/ast/lang-objc.js +388 -0
  25. package/lib/core/ast/lang-python.js +371 -0
  26. package/lib/core/ast/lang-swift.js +337 -0
  27. package/lib/core/ast/lang-typescript.js +503 -0
  28. package/lib/core/capability/CapabilityProbe.js +18 -9
  29. package/lib/core/constitution/Constitution.js +2 -3
  30. package/lib/core/constitution/ConstitutionValidator.js +65 -24
  31. package/lib/core/discovery/DartDiscoverer.js +534 -0
  32. package/lib/core/discovery/DiscovererRegistry.js +83 -0
  33. package/lib/core/discovery/GenericDiscoverer.js +225 -0
  34. package/lib/core/discovery/GoDiscoverer.js +541 -0
  35. package/lib/core/discovery/JvmDiscoverer.js +506 -0
  36. package/lib/core/discovery/NodeDiscoverer.js +466 -0
  37. package/lib/core/discovery/ProjectDiscoverer.js +93 -0
  38. package/lib/core/discovery/PythonDiscoverer.js +338 -0
  39. package/lib/core/discovery/SpmDiscoverer.js +5 -0
  40. package/lib/core/discovery/index.js +53 -0
  41. package/lib/core/enhancement/EnhancementPack.js +71 -0
  42. package/lib/core/enhancement/EnhancementRegistry.js +47 -0
  43. package/lib/core/enhancement/android-enhancement.js +102 -0
  44. package/lib/core/enhancement/django-enhancement.js +70 -0
  45. package/lib/core/enhancement/fastapi-enhancement.js +63 -0
  46. package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
  47. package/lib/core/enhancement/go-web-enhancement.js +201 -0
  48. package/lib/core/enhancement/index.js +65 -0
  49. package/lib/core/enhancement/node-server-enhancement.js +88 -0
  50. package/lib/core/enhancement/react-enhancement.js +86 -0
  51. package/lib/core/enhancement/spring-enhancement.js +112 -0
  52. package/lib/core/enhancement/vue-enhancement.js +96 -0
  53. package/lib/core/gateway/Gateway.js +8 -9
  54. package/lib/core/gateway/GatewayActionRegistry.js +1 -1
  55. package/lib/core/permission/PermissionManager.js +12 -8
  56. package/lib/domain/index.js +13 -9
  57. package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
  58. package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
  59. package/lib/domain/knowledge/Lifecycle.js +22 -22
  60. package/lib/domain/knowledge/index.js +9 -12
  61. package/lib/domain/knowledge/values/Constraints.js +31 -21
  62. package/lib/domain/knowledge/values/Content.js +21 -13
  63. package/lib/domain/knowledge/values/Quality.js +31 -18
  64. package/lib/domain/knowledge/values/Reasoning.js +20 -12
  65. package/lib/domain/knowledge/values/Relations.js +37 -25
  66. package/lib/domain/knowledge/values/Stats.js +18 -12
  67. package/lib/domain/knowledge/values/index.js +4 -3
  68. package/lib/domain/snippet/Snippet.js +35 -10
  69. package/lib/external/ai/AiFactory.js +48 -16
  70. package/lib/external/ai/AiProvider.js +184 -90
  71. package/lib/external/ai/providers/ClaudeProvider.js +25 -12
  72. package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
  73. package/lib/external/ai/providers/MockProvider.js +9 -3
  74. package/lib/external/ai/providers/OpenAiProvider.js +51 -29
  75. package/lib/external/mcp/McpServer.js +66 -36
  76. package/lib/external/mcp/errorHandler.js +23 -11
  77. package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
  78. package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
  79. package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
  80. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
  81. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
  82. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
  83. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
  84. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
  85. package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
  86. package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
  87. package/lib/external/mcp/handlers/bootstrap.js +691 -168
  88. package/lib/external/mcp/handlers/browse.js +66 -22
  89. package/lib/external/mcp/handlers/candidate.js +118 -35
  90. package/lib/external/mcp/handlers/consolidated.js +49 -17
  91. package/lib/external/mcp/handlers/guard.js +104 -39
  92. package/lib/external/mcp/handlers/knowledge.js +60 -36
  93. package/lib/external/mcp/handlers/search.js +43 -14
  94. package/lib/external/mcp/handlers/skill.js +120 -45
  95. package/lib/external/mcp/handlers/structure.js +240 -86
  96. package/lib/external/mcp/handlers/system.js +42 -12
  97. package/lib/external/mcp/handlers/wiki.js +58 -33
  98. package/lib/external/mcp/tools.js +306 -123
  99. package/lib/http/HttpServer.js +72 -47
  100. package/lib/http/middleware/RateLimiter.js +5 -3
  101. package/lib/http/middleware/errorHandler.js +6 -1
  102. package/lib/http/middleware/requestLogger.js +14 -3
  103. package/lib/http/middleware/roleResolver.js +30 -23
  104. package/lib/http/routes/ai.js +387 -265
  105. package/lib/http/routes/auth.js +81 -61
  106. package/lib/http/routes/candidates.js +430 -320
  107. package/lib/http/routes/commands.js +289 -189
  108. package/lib/http/routes/extract.js +158 -125
  109. package/lib/http/routes/guardRules.js +309 -217
  110. package/lib/http/routes/knowledge.js +213 -154
  111. package/lib/http/routes/modules.js +578 -0
  112. package/lib/http/routes/monitoring.js +6 -6
  113. package/lib/http/routes/recipes.js +104 -93
  114. package/lib/http/routes/search.js +361 -305
  115. package/lib/http/routes/skills.js +145 -98
  116. package/lib/http/routes/snippets.js +42 -30
  117. package/lib/http/routes/spm.js +3 -405
  118. package/lib/http/routes/violations.js +113 -93
  119. package/lib/http/routes/wiki.js +211 -170
  120. package/lib/http/utils/routeHelpers.js +3 -1
  121. package/lib/http/utils/sse-sessions.js +16 -6
  122. package/lib/http/utils/sse.js +15 -5
  123. package/lib/infrastructure/audit/AuditLogger.js +5 -2
  124. package/lib/infrastructure/audit/AuditStore.js +10 -7
  125. package/lib/infrastructure/cache/CacheService.js +3 -1
  126. package/lib/infrastructure/cache/GraphCache.js +8 -4
  127. package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
  128. package/lib/infrastructure/config/ConfigLoader.js +9 -5
  129. package/lib/infrastructure/config/Defaults.js +30 -10
  130. package/lib/infrastructure/config/Paths.js +28 -8
  131. package/lib/infrastructure/config/TriggerSymbol.js +22 -10
  132. package/lib/infrastructure/database/DatabaseConnection.js +15 -10
  133. package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
  134. package/lib/infrastructure/external/ClipboardManager.js +6 -2
  135. package/lib/infrastructure/external/NativeUi.js +50 -43
  136. package/lib/infrastructure/external/OpenBrowser.js +14 -17
  137. package/lib/infrastructure/external/XcodeAutomation.js +14 -258
  138. package/lib/infrastructure/logging/Logger.js +46 -30
  139. package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
  140. package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
  141. package/lib/infrastructure/paths/HeaderResolver.js +25 -9
  142. package/lib/infrastructure/paths/PathFinder.js +34 -12
  143. package/lib/infrastructure/plugin/PluginManager.js +26 -8
  144. package/lib/infrastructure/realtime/RealtimeService.js +2 -2
  145. package/lib/infrastructure/vector/Chunker.js +22 -7
  146. package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
  147. package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
  148. package/lib/infrastructure/vector/VectorStore.js +28 -10
  149. package/lib/injection/ServiceContainer.js +247 -93
  150. package/lib/platform/ios/index.js +63 -0
  151. package/lib/platform/ios/routes/spm.js +437 -0
  152. package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
  153. package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
  154. package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
  155. package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
  156. package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
  157. package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
  158. package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
  159. package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
  160. package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
  161. package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
  162. package/lib/repository/base/BaseRepository.js +7 -9
  163. package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
  164. package/lib/repository/token/TokenUsageStore.js +4 -2
  165. package/lib/service/automation/ActionPipeline.js +1 -1
  166. package/lib/service/automation/AutomationOrchestrator.js +8 -4
  167. package/lib/service/automation/ContextCollector.js +7 -5
  168. package/lib/service/automation/DirectiveDetector.js +23 -16
  169. package/lib/service/automation/FileWatcher.js +112 -56
  170. package/lib/service/automation/TriggerResolver.js +6 -4
  171. package/lib/service/automation/handlers/AlinkHandler.js +24 -12
  172. package/lib/service/automation/handlers/CreateHandler.js +19 -20
  173. package/lib/service/automation/handlers/DraftHandler.js +14 -8
  174. package/lib/service/automation/handlers/GuardHandler.js +93 -63
  175. package/lib/service/automation/handlers/HeaderHandler.js +1 -6
  176. package/lib/service/automation/handlers/SearchHandler.js +155 -88
  177. package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
  178. package/lib/service/candidate/SimilarityService.js +25 -9
  179. package/lib/service/chat/AnalystAgent.js +50 -24
  180. package/lib/service/chat/CandidateGuardrail.js +143 -17
  181. package/lib/service/chat/ChatAgent.js +759 -243
  182. package/lib/service/chat/ContextWindow.js +116 -71
  183. package/lib/service/chat/ConversationStore.js +77 -36
  184. package/lib/service/chat/EpisodicConsolidator.js +47 -23
  185. package/lib/service/chat/HandoffProtocol.js +98 -22
  186. package/lib/service/chat/Memory.js +34 -14
  187. package/lib/service/chat/ProducerAgent.js +40 -20
  188. package/lib/service/chat/ProjectSemanticMemory.js +109 -78
  189. package/lib/service/chat/ReasoningLayer.js +148 -70
  190. package/lib/service/chat/ReasoningTrace.js +44 -32
  191. package/lib/service/chat/TaskPipeline.js +39 -19
  192. package/lib/service/chat/ToolRegistry.js +48 -29
  193. package/lib/service/chat/WorkingMemory.js +44 -18
  194. package/lib/service/chat/tools.js +1096 -494
  195. package/lib/service/context/RecipeExtractor.js +132 -51
  196. package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
  197. package/lib/service/cursor/KnowledgeCompressor.js +25 -22
  198. package/lib/service/cursor/RulesGenerator.js +13 -7
  199. package/lib/service/cursor/SkillsSyncer.js +77 -27
  200. package/lib/service/cursor/TokenBudget.js +2 -2
  201. package/lib/service/cursor/TopicClassifier.js +54 -20
  202. package/lib/service/guard/ComplianceReporter.js +55 -43
  203. package/lib/service/guard/ExclusionManager.js +67 -29
  204. package/lib/service/guard/GuardCheckEngine.js +381 -86
  205. package/lib/service/guard/GuardFeedbackLoop.js +22 -10
  206. package/lib/service/guard/GuardService.js +29 -19
  207. package/lib/service/guard/RuleLearner.js +55 -23
  208. package/lib/service/guard/SourceFileCollector.js +27 -20
  209. package/lib/service/guard/ViolationsStore.js +43 -38
  210. package/lib/service/knowledge/CodeEntityGraph.js +147 -82
  211. package/lib/service/knowledge/ConfidenceRouter.js +12 -10
  212. package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
  213. package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
  214. package/lib/service/knowledge/KnowledgeService.js +222 -112
  215. package/lib/service/module/ModuleService.js +969 -0
  216. package/lib/service/quality/FeedbackCollector.js +27 -15
  217. package/lib/service/quality/QualityScorer.js +78 -24
  218. package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
  219. package/lib/service/recipe/RecipeParser.js +78 -45
  220. package/lib/service/search/CoarseRanker.js +43 -28
  221. package/lib/service/search/CrossEncoderReranker.js +32 -21
  222. package/lib/service/search/InvertedIndex.js +21 -7
  223. package/lib/service/search/MultiSignalRanker.js +90 -28
  224. package/lib/service/search/RetrievalFunnel.js +45 -24
  225. package/lib/service/search/SearchEngine.js +255 -103
  226. package/lib/service/skills/EventAggregator.js +32 -15
  227. package/lib/service/skills/SignalCollector.js +140 -64
  228. package/lib/service/skills/SkillAdvisor.js +79 -42
  229. package/lib/service/skills/SkillHooks.js +16 -14
  230. package/lib/service/snippet/PlaceholderConverter.js +5 -0
  231. package/lib/service/snippet/SnippetFactory.js +116 -99
  232. package/lib/service/snippet/SnippetInstaller.js +234 -62
  233. package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
  234. package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
  235. package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
  236. package/lib/service/wiki/WikiGenerator.js +637 -263
  237. package/lib/shared/DimensionCopyRegistry.js +472 -0
  238. package/lib/shared/LanguageService.js +399 -0
  239. package/lib/shared/PathGuard.js +45 -28
  240. package/lib/shared/RecipeReadinessChecker.js +72 -12
  241. package/lib/shared/constants.js +41 -41
  242. package/lib/shared/errors/BaseError.js +2 -2
  243. package/lib/shared/errors/index.js +4 -4
  244. package/lib/shared/similarity.js +25 -8
  245. package/lib/shared/token-utils.js +6 -2
  246. package/lib/shared/utils/common.js +12 -4
  247. package/package.json +49 -13
  248. package/scripts/bench-real-projects.mjs +256 -0
  249. package/scripts/build-native-ui.js +30 -30
  250. package/scripts/clear-old-vector-index.js +5 -35
  251. package/scripts/clear-vector-cache.js +7 -37
  252. package/scripts/collect-test-project-stats.mjs +160 -0
  253. package/scripts/diagnose-mcp.js +41 -32
  254. package/scripts/ensure-parse-package.js +6 -9
  255. package/scripts/generate-recipe-drafts.js +116 -77
  256. package/scripts/init-db.js +3 -20
  257. package/scripts/init-snippets.js +305 -0
  258. package/scripts/init-vector-db.js +173 -170
  259. package/scripts/install-cursor-skill.js +148 -104
  260. package/scripts/install-full.js +8 -21
  261. package/scripts/install-vscode-copilot.js +146 -145
  262. package/scripts/migrate-md-to-knowledge.mjs +139 -151
  263. package/scripts/postinstall-safe.js +5 -17
  264. package/scripts/recipe-audit.js +106 -82
  265. package/scripts/release.js +283 -323
  266. package/scripts/setup-mcp-config.js +60 -52
  267. package/scripts/verify-context-api.js +20 -20
  268. package/skills/autosnippet-analysis/SKILL.md +10 -6
  269. package/skills/autosnippet-candidates/SKILL.md +27 -26
  270. package/skills/autosnippet-coldstart/SKILL.md +555 -38
  271. package/skills/autosnippet-concepts/SKILL.md +349 -337
  272. package/skills/autosnippet-create/SKILL.md +5 -5
  273. package/skills/autosnippet-reference-dart/SKILL.md +543 -0
  274. package/skills/autosnippet-reference-go/SKILL.md +539 -0
  275. package/skills/autosnippet-reference-java/SKILL.md +534 -0
  276. package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
  277. package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
  278. package/skills/autosnippet-reference-objc/SKILL.md +29 -6
  279. package/skills/autosnippet-reference-python/SKILL.md +800 -0
  280. package/skills/autosnippet-reference-swift/SKILL.md +70 -14
  281. package/skills/autosnippet-structure/SKILL.md +4 -4
  282. package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
  283. package/templates/recipes-setup/README.md +2 -2
  284. package/templates/recipes-setup/_template.md +1 -1
  285. package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
  286. package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
  287. package/resources/asd-entry/main.swift +0 -159
  288. package/scripts/build-asd-entry.js +0 -51
  289. package/scripts/init-xcode-snippets.js +0 -311
  290. package/template.json +0 -39
@@ -22,10 +22,10 @@ import Logger from '../../infrastructure/logging/Logger.js';
22
22
 
23
23
  /** 任务状态枚举 */
24
24
  export const TaskStatus = Object.freeze({
25
- SKELETON: 'skeleton', // 骨架已创建,等待填充
26
- FILLING: 'filling', // 内容正在填充中
27
- COMPLETED: 'completed', // 填充完成
28
- FAILED: 'failed', // 填充失败
25
+ SKELETON: 'skeleton', // 骨架已创建,等待填充
26
+ FILLING: 'filling', // 内容正在填充中
27
+ COMPLETED: 'completed', // 填充完成
28
+ FAILED: 'failed', // 填充失败
29
29
  });
30
30
 
31
31
  /**
@@ -36,19 +36,19 @@ class BootstrapSession {
36
36
  this.id = sessionId;
37
37
  this.startedAt = Date.now();
38
38
  this.completedAt = null;
39
- this.status = 'running'; // running | completed | failed
40
- this.tasks = new Map(); // taskId → TaskInfo
41
- this.summary = null; // 完成后的摘要
39
+ this.status = 'running'; // running | completed | failed
40
+ this.tasks = new Map(); // taskId → TaskInfo
41
+ this.summary = null; // 完成后的摘要
42
42
  }
43
43
 
44
44
  addTask(taskId, meta) {
45
45
  this.tasks.set(taskId, {
46
46
  id: taskId,
47
47
  status: TaskStatus.SKELETON,
48
- meta, // { type: 'dimension'|'skill', dimId, label, skillWorthy }
48
+ meta, // { type: 'dimension'|'skill', dimId, label, skillWorthy }
49
49
  startedAt: null,
50
50
  completedAt: null,
51
- result: null, // 填充结果摘要
51
+ result: null, // 填充结果摘要
52
52
  error: null,
53
53
  });
54
54
  }
@@ -57,11 +57,21 @@ class BootstrapSession {
57
57
  return this.tasks.get(taskId);
58
58
  }
59
59
 
60
- get totalTasks() { return this.tasks.size; }
61
- get completedTasks() { return [...this.tasks.values()].filter(t => t.status === TaskStatus.COMPLETED).length; }
62
- get failedTasks() { return [...this.tasks.values()].filter(t => t.status === TaskStatus.FAILED).length; }
63
- get fillingTasks() { return [...this.tasks.values()].filter(t => t.status === TaskStatus.FILLING).length; }
64
- get skeletonTasks() { return [...this.tasks.values()].filter(t => t.status === TaskStatus.SKELETON).length; }
60
+ get totalTasks() {
61
+ return this.tasks.size;
62
+ }
63
+ get completedTasks() {
64
+ return [...this.tasks.values()].filter((t) => t.status === TaskStatus.COMPLETED).length;
65
+ }
66
+ get failedTasks() {
67
+ return [...this.tasks.values()].filter((t) => t.status === TaskStatus.FAILED).length;
68
+ }
69
+ get fillingTasks() {
70
+ return [...this.tasks.values()].filter((t) => t.status === TaskStatus.FILLING).length;
71
+ }
72
+ get skeletonTasks() {
73
+ return [...this.tasks.values()].filter((t) => t.status === TaskStatus.SKELETON).length;
74
+ }
65
75
 
66
76
  get isAllDone() {
67
77
  return this.skeletonTasks === 0 && this.fillingTasks === 0;
@@ -70,14 +80,18 @@ class BootstrapSession {
70
80
  get totalToolCalls() {
71
81
  let count = 0;
72
82
  for (const t of this.tasks.values()) {
73
- if (t.result?.toolCallCount) count += t.result.toolCallCount;
83
+ if (t.result?.toolCallCount) {
84
+ count += t.result.toolCallCount;
85
+ }
74
86
  }
75
87
  return count;
76
88
  }
77
89
 
78
90
  get progress() {
79
91
  const total = this.totalTasks;
80
- if (total === 0) return 100;
92
+ if (total === 0) {
93
+ return 100;
94
+ }
81
95
  return Math.round(((this.completedTasks + this.failedTasks) / total) * 100);
82
96
  }
83
97
 
@@ -94,7 +108,7 @@ class BootstrapSession {
94
108
  filling: this.fillingTasks,
95
109
  skeleton: this.skeletonTasks,
96
110
  totalToolCalls: this.totalToolCalls,
97
- tasks: [...this.tasks.values()].map(t => ({
111
+ tasks: [...this.tasks.values()].map((t) => ({
98
112
  id: t.id,
99
113
  status: t.status,
100
114
  meta: t.meta,
@@ -138,7 +152,9 @@ export class BootstrapTaskManager {
138
152
  startSession(taskDefs) {
139
153
  // ── 并发锁:如果上一个 session 还在运行,先中止 ──
140
154
  if (this.isRunning) {
141
- Logger.warn(`[Bootstrap] Previous session ${this.#currentSession.id} still running — aborting before starting new session`);
155
+ Logger.warn(
156
+ `[Bootstrap] Previous session ${this.#currentSession.id} still running — aborting before starting new session`
157
+ );
142
158
  this.abortSession('Superseded by new bootstrap request');
143
159
  }
144
160
 
@@ -152,7 +168,7 @@ export class BootstrapTaskManager {
152
168
  Logger.info(`[Bootstrap] Session ${sessionId} started with ${taskDefs.length} tasks`);
153
169
  this.#emit('bootstrap:started', {
154
170
  sessionId,
155
- tasks: taskDefs.map(t => ({ id: t.id, ...t.meta })),
171
+ tasks: taskDefs.map((t) => ({ id: t.id, ...t.meta })),
156
172
  total: taskDefs.length,
157
173
  startedAt: this.#currentSession.startedAt,
158
174
  });
@@ -170,7 +186,9 @@ export class BootstrapTaskManager {
170
186
  */
171
187
  abortSession(reason = 'Aborted by user') {
172
188
  const session = this.#currentSession;
173
- if (!session || session.status !== 'running') return;
189
+ if (!session || session.status !== 'running') {
190
+ return;
191
+ }
174
192
 
175
193
  // 将未完成的任务全部标记 FAILED
176
194
  for (const task of session.tasks.values()) {
@@ -196,8 +214,12 @@ export class BootstrapTaskManager {
196
214
  this.#emit('bootstrap:all-completed', {
197
215
  sessionId: session.id,
198
216
  summary: session.summary,
199
- tasks: [...session.tasks.values()].map(t => ({
200
- id: t.id, status: t.status, meta: t.meta, result: t.result, error: t.error,
217
+ tasks: [...session.tasks.values()].map((t) => ({
218
+ id: t.id,
219
+ status: t.status,
220
+ meta: t.meta,
221
+ result: t.result,
222
+ error: t.error,
201
223
  })),
202
224
  });
203
225
  }
@@ -214,10 +236,12 @@ export class BootstrapTaskManager {
214
236
  isSessionValid(sessionId) {
215
237
  // Session 在 running 或 completed 状态都有效 — completed 表示维度填充完成,
216
238
  // 但 Phase 5.5 Skills 生成仍需运行。只有被新 session 替代时才无效。
217
- return this.#currentSession?.id === sessionId &&
239
+ return (
240
+ this.#currentSession?.id === sessionId &&
218
241
  (this.#currentSession?.status === 'running' ||
219
- this.#currentSession?.status === 'completed' ||
220
- this.#currentSession?.status === 'completed_with_errors');
242
+ this.#currentSession?.status === 'completed' ||
243
+ this.#currentSession?.status === 'completed_with_errors')
244
+ );
221
245
  }
222
246
 
223
247
  /**
@@ -225,9 +249,13 @@ export class BootstrapTaskManager {
225
249
  */
226
250
  markTaskFilling(taskId) {
227
251
  const session = this.#currentSession;
228
- if (!session) return;
252
+ if (!session) {
253
+ return;
254
+ }
229
255
  const task = session.getTask(taskId);
230
- if (!task) return;
256
+ if (!task) {
257
+ return;
258
+ }
231
259
 
232
260
  task.status = TaskStatus.FILLING;
233
261
  task.startedAt = Date.now();
@@ -248,15 +276,21 @@ export class BootstrapTaskManager {
248
276
  */
249
277
  markTaskCompleted(taskId, result = {}) {
250
278
  const session = this.#currentSession;
251
- if (!session) return;
279
+ if (!session) {
280
+ return;
281
+ }
252
282
  const task = session.getTask(taskId);
253
- if (!task) return;
283
+ if (!task) {
284
+ return;
285
+ }
254
286
 
255
287
  task.status = TaskStatus.COMPLETED;
256
288
  task.completedAt = Date.now();
257
289
  task.result = result;
258
290
 
259
- Logger.info(`[Bootstrap] Task "${taskId}" completed (${session.completedTasks}/${session.totalTasks})`);
291
+ Logger.info(
292
+ `[Bootstrap] Task "${taskId}" completed (${session.completedTasks}/${session.totalTasks})`
293
+ );
260
294
  this.#emit('bootstrap:task-completed', {
261
295
  sessionId: session.id,
262
296
  taskId,
@@ -280,9 +314,13 @@ export class BootstrapTaskManager {
280
314
  */
281
315
  markTaskFailed(taskId, error) {
282
316
  const session = this.#currentSession;
283
- if (!session) return;
317
+ if (!session) {
318
+ return;
319
+ }
284
320
  const task = session.getTask(taskId);
285
- if (!task) return;
321
+ if (!task) {
322
+ return;
323
+ }
286
324
 
287
325
  task.status = TaskStatus.FAILED;
288
326
  task.completedAt = Date.now();
@@ -347,7 +385,9 @@ export class BootstrapTaskManager {
347
385
 
348
386
  #finishSession() {
349
387
  const session = this.#currentSession;
350
- if (!session) return;
388
+ if (!session) {
389
+ return;
390
+ }
351
391
 
352
392
  session.status = session.failedTasks > 0 ? 'completed_with_errors' : 'completed';
353
393
  session.completedAt = Date.now();
@@ -359,12 +399,14 @@ export class BootstrapTaskManager {
359
399
  };
360
400
 
361
401
  const durationSec = ((session.completedAt - session.startedAt) / 1000).toFixed(1);
362
- Logger.info(`[Bootstrap] Session ${session.id} finished: ${session.completedTasks} completed, ${session.failedTasks} failed (${durationSec}s)`);
402
+ Logger.info(
403
+ `[Bootstrap] Session ${session.id} finished: ${session.completedTasks} completed, ${session.failedTasks} failed (${durationSec}s)`
404
+ );
363
405
 
364
406
  this.#emit('bootstrap:all-completed', {
365
407
  sessionId: session.id,
366
408
  summary: session.summary,
367
- tasks: [...session.tasks.values()].map(t => ({
409
+ tasks: [...session.tasks.values()].map((t) => ({
368
410
  id: t.id,
369
411
  status: t.status,
370
412
  meta: t.meta,
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { getProjectRecipesPath } from '../../infrastructure/config/Paths.js';
4
- import { tokenizeForSimilarity, jaccardSimilarity } from '../../shared/similarity.js';
4
+ import { jaccardSimilarity, tokenizeForSimilarity } from '../../shared/similarity.js';
5
5
 
6
6
  /**
7
7
  * SimilarityService — 轻量级 Recipe 相似度检测
@@ -12,12 +12,18 @@ import { tokenizeForSimilarity, jaccardSimilarity } from '../../shared/similarit
12
12
  * 计算候选与单个 Recipe 的综合相似度
13
13
  */
14
14
  function computeSimilarity(candidate, recipe) {
15
- const titleSim = jaccardSimilarity(tokenizeForSimilarity(candidate.title), tokenizeForSimilarity(recipe.title));
15
+ const titleSim = jaccardSimilarity(
16
+ tokenizeForSimilarity(candidate.title),
17
+ tokenizeForSimilarity(recipe.title)
18
+ );
16
19
  const summarySim = jaccardSimilarity(
17
20
  tokenizeForSimilarity(candidate.summary || candidate.description),
18
- tokenizeForSimilarity(recipe.summary || recipe.description),
21
+ tokenizeForSimilarity(recipe.summary || recipe.description)
22
+ );
23
+ const codeSim = jaccardSimilarity(
24
+ tokenizeForSimilarity(candidate.code, 3),
25
+ tokenizeForSimilarity(recipe.code, 3)
19
26
  );
20
- const codeSim = jaccardSimilarity(tokenizeForSimilarity(candidate.code, 3), tokenizeForSimilarity(recipe.code, 3));
21
27
  // 加权: title 30%, summary 30%, code 40%
22
28
  return titleSim * 0.3 + summarySim * 0.3 + codeSim * 0.4;
23
29
  }
@@ -27,11 +33,15 @@ function computeSimilarity(candidate, recipe) {
27
33
  */
28
34
  function loadRecipesFromDisk(recipesDir) {
29
35
  const recipes = [];
30
- if (!fs.existsSync(recipesDir)) return recipes;
36
+ if (!fs.existsSync(recipesDir)) {
37
+ return recipes;
38
+ }
31
39
 
32
40
  const walk = (dir) => {
33
41
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
34
- if (entry.name.startsWith('.')) continue;
42
+ if (entry.name.startsWith('.')) {
43
+ continue;
44
+ }
35
45
  const full = path.join(dir, entry.name);
36
46
  if (entry.isDirectory()) {
37
47
  walk(full);
@@ -39,7 +49,7 @@ function loadRecipesFromDisk(recipesDir) {
39
49
  try {
40
50
  const content = fs.readFileSync(full, 'utf8');
41
51
  const titleMatch = content.match(/^#\s+(.+)/m);
42
- const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
52
+ const _fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
43
53
  const codeMatch = content.match(/```\w*\n([\s\S]*?)```/);
44
54
  const summaryMatch = content.match(/summary[_cn]*:\s*(.+)/i);
45
55
  recipes.push({
@@ -48,7 +58,9 @@ function loadRecipesFromDisk(recipesDir) {
48
58
  summary: summaryMatch?.[1]?.trim() || '',
49
59
  code: codeMatch?.[1]?.trim() || '',
50
60
  });
51
- } catch { /* skip unreadable */ }
61
+ } catch {
62
+ /* skip unreadable */
63
+ }
52
64
  }
53
65
  }
54
66
  };
@@ -73,7 +85,11 @@ export function findSimilarRecipes(projectRoot, candidate, opts = {}) {
73
85
  for (const recipe of recipes) {
74
86
  const sim = computeSimilarity(candidate, recipe);
75
87
  if (sim >= threshold) {
76
- results.push({ file: recipe.file, title: recipe.title, similarity: Math.round(sim * 1000) / 1000 });
88
+ results.push({
89
+ file: recipe.file,
90
+ title: recipe.title,
91
+ similarity: Math.round(sim * 1000) / 1000,
92
+ });
77
93
  }
78
94
  }
79
95
 
@@ -12,8 +12,8 @@
12
12
  * @module AnalystAgent
13
13
  */
14
14
 
15
- import { buildAnalysisReport, analysisQualityGate, buildRetryPrompt } from './HandoffProtocol.js';
16
15
  import Logger from '../../infrastructure/logging/Logger.js';
16
+ import { analysisQualityGate, buildAnalysisReport, buildRetryPrompt } from './HandoffProtocol.js';
17
17
 
18
18
  // ──────────────────────────────────────────────────────────────────
19
19
  // System Prompt — Analyst 专用 (~100 tokens)
@@ -77,12 +77,12 @@ const ANALYST_TOOLS = [
77
77
  // ──────────────────────────────────────────────────────────────────
78
78
 
79
79
  const ANALYST_BUDGET = {
80
- maxIterations: 24, // was 18 — 大项目维度需要充足探索轮次
81
- searchBudget: 18, // was 14 — 匹配更大探索空间
82
- searchBudgetGrace: 10, // was 8
83
- maxSubmits: 0, // Analyst 不提交候选
80
+ maxIterations: 24, // was 18 — 大项目维度需要充足探索轮次
81
+ searchBudget: 18, // was 14 — 匹配更大探索空间
82
+ searchBudgetGrace: 10, // was 8
83
+ maxSubmits: 0, // Analyst 不提交候选
84
84
  softSubmitLimit: 0,
85
- idleRoundsToExit: 2, // 减少空转
85
+ idleRoundsToExit: 2, // 减少空转
86
86
  };
87
87
 
88
88
  // ──────────────────────────────────────────────────────────────────
@@ -99,11 +99,20 @@ const ANALYST_BUDGET = {
99
99
  * @param {object} [codeEntityGraph] — CodeEntityGraph 实例 (Phase E 代码实体图谱)
100
100
  * @returns {string}
101
101
  */
102
- function buildAnalystPrompt(dimConfig, projectInfo, dimensionContext, episodicMemory, semanticMemory, codeEntityGraph) {
102
+ function buildAnalystPrompt(
103
+ dimConfig,
104
+ projectInfo,
105
+ dimensionContext,
106
+ episodicMemory,
107
+ semanticMemory,
108
+ codeEntityGraph
109
+ ) {
103
110
  const parts = [];
104
111
 
105
112
  // §1 任务描述
106
- parts.push(`分析项目 ${projectInfo.name} (${projectInfo.lang}, ${projectInfo.fileCount} 个文件) 的 ${dimConfig.label}。`);
113
+ parts.push(
114
+ `分析项目 ${projectInfo.name} (${projectInfo.lang}, ${projectInfo.fileCount} 个文件) 的 ${dimConfig.label}。`
115
+ );
107
116
 
108
117
  // §2 维度指引
109
118
  if (dimConfig.guide) {
@@ -112,7 +121,7 @@ function buildAnalystPrompt(dimConfig, projectInfo, dimensionContext, episodicMe
112
121
 
113
122
  // §3 探索焦点
114
123
  if (dimConfig.focusAreas?.length > 0) {
115
- parts.push(`重点关注:\n${dimConfig.focusAreas.map(f => `- ${f}`).join('\n')}`);
124
+ parts.push(`重点关注:\n${dimConfig.focusAreas.map((f) => `- ${f}`).join('\n')}`);
116
125
  }
117
126
 
118
127
  // §4 输出要求
@@ -142,7 +151,8 @@ ${depthHint}
142
151
  // 回退到 DimensionContext (兼容)
143
152
  if (episodicMemory) {
144
153
  const emContext = episodicMemory.buildContextForDimension(
145
- dimConfig.id, dimConfig.focusAreas || []
154
+ dimConfig.id,
155
+ dimConfig.focusAreas || []
146
156
  );
147
157
  if (emContext) {
148
158
  parts.push(emContext);
@@ -183,7 +193,9 @@ ${depthHint}
183
193
  if (section) {
184
194
  parts.push(section);
185
195
  }
186
- } catch { /* SemanticMemory retrieval failed, non-critical */ }
196
+ } catch {
197
+ /* SemanticMemory retrieval failed, non-critical */
198
+ }
187
199
  }
188
200
 
189
201
  // §9: 代码实体图谱 (Phase E) — 类/协议/Category 关系拓扑
@@ -194,7 +206,9 @@ ${depthHint}
194
206
  parts.push(graphCtx);
195
207
  parts.push('使用 query_code_graph 工具可以查询更详细的继承链、影响分析等。');
196
208
  }
197
- } catch { /* CodeEntityGraph context failed, non-critical */ }
209
+ } catch {
210
+ /* CodeEntityGraph context failed, non-critical */
211
+ }
198
212
  }
199
213
 
200
214
  return parts.join('\n\n');
@@ -243,22 +257,26 @@ export class AnalystAgent {
243
257
  async analyze(dimConfig, projectInfo, options = {}) {
244
258
  const dimId = dimConfig.id;
245
259
  const prompt = buildAnalystPrompt(
246
- dimConfig, projectInfo,
260
+ dimConfig,
261
+ projectInfo,
247
262
  options.dimensionContext,
248
- options.episodicMemory, // v4.0: EpisodicMemory 增强
249
- options.semanticMemory, // v4.1: ProjectSemanticMemory 历史记忆
250
- options.codeEntityGraph // Phase E: CodeEntityGraph 代码实体图谱
263
+ options.episodicMemory, // v4.0: EpisodicMemory 增强
264
+ options.semanticMemory, // v4.1: ProjectSemanticMemory 历史记忆
265
+ options.codeEntityGraph // Phase E: CodeEntityGraph 代码实体图谱
251
266
  );
252
267
 
253
- this.#logger.info(`[AnalystAgent] ▶ analyzing dimension "${dimId}" — prompt ${prompt.length} chars`);
268
+ this.#logger.info(
269
+ `[AnalystAgent] ▶ analyzing dimension "${dimId}" — prompt ${prompt.length} chars`
270
+ );
254
271
 
255
272
  let retries = 0;
256
273
  let lastReport = null;
257
274
 
258
275
  while (retries <= this.#maxRetries) {
259
- const execPrompt = retries === 0
260
- ? prompt
261
- : prompt + '\n\n' + buildRetryPrompt(lastReport?._gateReason || 'Analysis too short');
276
+ const execPrompt =
277
+ retries === 0
278
+ ? prompt
279
+ : `${prompt}\n\n${buildRetryPrompt(lastReport?._gateReason || 'Analysis too short')}`;
262
280
 
263
281
  try {
264
282
  const result = await this.#chatAgent.execute(execPrompt, {
@@ -293,13 +311,19 @@ export class AnalystAgent {
293
311
  }
294
312
 
295
313
  // 质量门控 — 传入 outputType 以调整门槛
296
- const gate = analysisQualityGate(report, { outputType: dimConfig.outputType || 'analysis' });
314
+ const gate = analysisQualityGate(report, {
315
+ outputType: dimConfig.outputType || 'analysis',
316
+ });
297
317
  if (gate.pass) {
298
- this.#logger.info(`[AnalystAgent] ✅ dimension "${dimId}" — ${report.analysisText.length} chars, ${report.referencedFiles.length} files referenced, ${report.metadata.toolCallCount} tool calls`);
318
+ this.#logger.info(
319
+ `[AnalystAgent] ✅ dimension "${dimId}" — ${report.analysisText.length} chars, ${report.referencedFiles.length} files referenced, ${report.metadata.toolCallCount} tool calls`
320
+ );
299
321
  return report;
300
322
  }
301
323
 
302
- this.#logger.warn(`[AnalystAgent] ⚠ Gate failed for "${dimId}": ${gate.reason} (action=${gate.action})`);
324
+ this.#logger.warn(
325
+ `[AnalystAgent] ⚠ Gate failed for "${dimId}": ${gate.reason} (action=${gate.action})`
326
+ );
303
327
 
304
328
  if (gate.action === 'degrade') {
305
329
  // 直接降级 — 不重试
@@ -320,7 +344,9 @@ export class AnalystAgent {
320
344
 
321
345
  // 重试耗尽 — 返回最后一次结果
322
346
  this.#logger.warn(`[AnalystAgent] Retries exhausted for "${dimId}" — returning last report`);
323
- return lastReport || buildAnalysisReport({ reply: '', toolCalls: [] }, dimId, this.#projectGraph);
347
+ return (
348
+ lastReport || buildAnalysisReport({ reply: '', toolCalls: [] }, dimId, this.#projectGraph)
349
+ );
324
350
  }
325
351
  }
326
352