autosnippet 3.0.1 → 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 +655 -260
  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
@@ -25,21 +25,44 @@ const SKILL_NAME_MAP = {
25
25
  'project-objc-deep-scan': 'autosnippet-objc-deep-scan',
26
26
  'project-category-scan': 'autosnippet-category-scan',
27
27
  'project-best-practice': 'autosnippet-best-practice',
28
+ // 新语言维度
29
+ 'project-module-exports': 'autosnippet-module-exports',
30
+ 'project-framework-conventions': 'autosnippet-framework-conventions',
31
+ 'project-python-structure': 'autosnippet-python-structure',
32
+ 'project-jvm-annotations': 'autosnippet-jvm-annotations',
28
33
  };
29
34
 
30
35
  /**
31
36
  * 用途描述模板(英文,Cursor 优先)
32
37
  */
33
38
  const SKILL_DESC_MAP = {
34
- 'autosnippet-architecture': 'Architecture patterns, module boundaries, and dependency rules for {project}. Use when creating new modules, reviewing architecture, or understanding dependencies.',
35
- 'autosnippet-code-standard': 'Coding standards and style conventions for {project}. Use when writing new code, reviewing formatting, or enforcing naming conventions.',
36
- 'autosnippet-profile': 'Project overview and profile for {project}. Use when needing background on the project, its tech stack, or structure.',
37
- 'autosnippet-guidelines': 'Agent interaction guidelines for {project}. Use when understanding how to work with this specific project.',
38
- 'autosnippet-data-flow': 'Event and data flow patterns for {project}. Use when working with events, state management, or data pipelines.',
39
- 'autosnippet-code-pattern': 'Common code patterns and idioms for {project}. Use when implementing features following project conventions.',
40
- 'autosnippet-objc-deep-scan': 'Objective-C deep scan results for {project}. Use when working with Objective-C code, method swizzling, or runtime features.',
41
- 'autosnippet-category-scan': 'Category and extension analysis for {project}. Use when working with categories or finding existing utility methods.',
42
- 'autosnippet-best-practice': 'Best practices and proven patterns for {project}. Use when making design decisions or code review.',
39
+ 'autosnippet-architecture':
40
+ 'Architecture patterns, module boundaries, and dependency rules for {project}. Use when creating new modules, reviewing architecture, or understanding dependencies.',
41
+ 'autosnippet-code-standard':
42
+ 'Coding standards and style conventions for {project}. Use when writing new code, reviewing formatting, or enforcing naming conventions.',
43
+ 'autosnippet-profile':
44
+ 'Project overview and profile for {project}. Use when needing background on the project, its tech stack, or structure.',
45
+ 'autosnippet-guidelines':
46
+ 'Agent interaction guidelines for {project}. Use when understanding how to work with this specific project.',
47
+ 'autosnippet-data-flow':
48
+ 'Event and data flow patterns for {project}. Use when working with events, state management, or data pipelines.',
49
+ 'autosnippet-code-pattern':
50
+ 'Common code patterns and idioms for {project}. Use when implementing features following project conventions.',
51
+ 'autosnippet-objc-deep-scan':
52
+ 'Objective-C deep scan results for {project}. Use when working with Objective-C code, method swizzling, or runtime features.',
53
+ 'autosnippet-category-scan':
54
+ 'Category and extension analysis for {project}. Use when working with categories or finding existing utility methods.',
55
+ 'autosnippet-best-practice':
56
+ 'Best practices and proven patterns for {project}. Use when making design decisions or code review.',
57
+ // 新语言维度
58
+ 'autosnippet-module-exports':
59
+ 'Module export structure, barrel exports, and public API surface for {project}. Use when working with imports/exports or module boundaries.',
60
+ 'autosnippet-framework-conventions':
61
+ 'Framework-specific conventions (component structure, routing, state management) for {project}. Use when following framework patterns.',
62
+ 'autosnippet-python-structure':
63
+ 'Python package structure, __init__.py exports, import patterns and type hint coverage for {project}. Use when working with Python modules.',
64
+ 'autosnippet-jvm-annotations':
65
+ 'Annotation patterns (DI, ORM, API, custom) and meta-programming for {project}. Use when working with Spring, Jakarta, or framework annotations.',
43
66
  };
44
67
 
45
68
  export class SkillsSyncer {
@@ -69,9 +92,10 @@ export class SkillsSyncer {
69
92
  }
70
93
 
71
94
  // 扫描源目录
72
- const skillDirs = fs.readdirSync(this.sourceDir, { withFileTypes: true })
73
- .filter(d => d.isDirectory())
74
- .map(d => d.name);
95
+ const skillDirs = fs
96
+ .readdirSync(this.sourceDir, { withFileTypes: true })
97
+ .filter((d) => d.isDirectory())
98
+ .map((d) => d.name);
75
99
 
76
100
  for (const dirName of skillDirs) {
77
101
  try {
@@ -81,7 +105,8 @@ export class SkillsSyncer {
81
105
  continue;
82
106
  }
83
107
 
84
- const targetName = SKILL_NAME_MAP[dirName] || `autosnippet-${dirName.replace(/^project-/, '')}`;
108
+ const targetName =
109
+ SKILL_NAME_MAP[dirName] || `autosnippet-${dirName.replace(/^project-/, '')}`;
85
110
  const targetSkillDir = path.join(this.targetDir, targetName);
86
111
 
87
112
  // 创建目标目录
@@ -118,7 +143,9 @@ export class SkillsSyncer {
118
143
  const body = bodyMatch ? bodyMatch[1].trim() : source.trim();
119
144
 
120
145
  // 获取描述
121
- const descTemplate = SKILL_DESC_MAP[targetName] || `Knowledge and patterns from {project}. Use when working with ${sourceDirName.replace(/^project-/, '')} related code.`;
146
+ const descTemplate =
147
+ SKILL_DESC_MAP[targetName] ||
148
+ `Knowledge and patterns from {project}. Use when working with ${sourceDirName.replace(/^project-/, '')} related code.`;
122
149
  const description = descTemplate.replace(/\{project\}/g, this.projectName);
123
150
 
124
151
  // 构建 Cursor 标准格式
@@ -147,7 +174,7 @@ export class SkillsSyncer {
147
174
  '',
148
175
  'See `references/RECIPES.md` for related recipe summaries.',
149
176
  ];
150
- return lines.join('\n') + '\n';
177
+ return `${lines.join('\n')}\n`;
151
178
  }
152
179
 
153
180
  /**
@@ -168,7 +195,9 @@ export class SkillsSyncer {
168
195
  { page: 1, pageSize: 50 }
169
196
  );
170
197
  recipes = result?.items || result?.data || [];
171
- if (Array.isArray(result)) recipes = result;
198
+ if (Array.isArray(result)) {
199
+ recipes = result;
200
+ }
172
201
  } catch {
173
202
  // 忽略查询错误
174
203
  }
@@ -176,10 +205,7 @@ export class SkillsSyncer {
176
205
 
177
206
  // 生成 RECIPES.md
178
207
  const dimensionLabel = sourceDirName.replace(/^project-/, '').replace(/-/g, ' ');
179
- const lines = [
180
- `# ${this._capitalizeWords(dimensionLabel)} Recipes`,
181
- '',
182
- ];
208
+ const lines = [`# ${this._capitalizeWords(dimensionLabel)} Recipes`, ''];
183
209
 
184
210
  if (recipes.length > 0) {
185
211
  lines.push('| Title | Trigger | Summary |');
@@ -187,7 +213,9 @@ export class SkillsSyncer {
187
213
  for (const entry of recipes.slice(0, 20)) {
188
214
  const title = (entry.title || '').replace(/\|/g, '/');
189
215
  const trigger = entry.trigger || '-';
190
- const summary = (entry.summaryCn || entry.description || '').replace(/\|/g, '/').slice(0, 80);
216
+ const summary = (entry.summaryCn || entry.description || '')
217
+ .replace(/\|/g, '/')
218
+ .slice(0, 80);
191
219
  lines.push(`| ${title} | ${trigger} | ${summary} |`);
192
220
  }
193
221
  } else {
@@ -197,7 +225,7 @@ export class SkillsSyncer {
197
225
  lines.push('');
198
226
  lines.push(`For full content, use: \`autosnippet_search("${dimensionLabel}")\``);
199
227
 
200
- fs.writeFileSync(path.join(refsDir, 'RECIPES.md'), lines.join('\n') + '\n', 'utf8');
228
+ fs.writeFileSync(path.join(refsDir, 'RECIPES.md'), `${lines.join('\n')}\n`, 'utf8');
201
229
  }
202
230
 
203
231
  /**
@@ -250,18 +278,40 @@ export class SkillsSyncer {
250
278
  '- Code review and quality improvements',
251
279
  '- Choosing between implementation approaches',
252
280
  ],
281
+ 'project-module-exports': [
282
+ '- Working with module imports and exports',
283
+ '- Understanding the public API surface',
284
+ '- Refactoring barrel exports or re-export chains',
285
+ ],
286
+ 'project-framework-conventions': [
287
+ '- Following framework-specific patterns (React/Vue/Angular)',
288
+ '- Organizing components and routes',
289
+ '- Implementing state management patterns',
290
+ ],
291
+ 'project-python-structure': [
292
+ '- Working with Python modules and packages',
293
+ '- Understanding import patterns and __init__.py exports',
294
+ '- Adding type hints or decorators',
295
+ ],
296
+ 'project-jvm-annotations': [
297
+ '- Working with dependency injection annotations',
298
+ '- Configuring ORM entities and API endpoints',
299
+ '- Using or creating custom annotations',
300
+ ],
253
301
  };
254
- return casesMap[sourceDirName] || [
255
- '- Working with code related to this dimension',
256
- '- Need guidance on project-specific patterns',
257
- ];
302
+ return (
303
+ casesMap[sourceDirName] || [
304
+ '- Working with code related to this dimension',
305
+ '- Need guidance on project-specific patterns',
306
+ ]
307
+ );
258
308
  }
259
309
 
260
310
  /**
261
311
  * @private
262
312
  */
263
313
  _capitalizeWords(str) {
264
- return str.replace(/\b\w/g, c => c.toUpperCase());
314
+ return str.replace(/\b\w/g, (c) => c.toUpperCase());
265
315
  }
266
316
  }
267
317
 
@@ -10,10 +10,10 @@ export { estimateTokens };
10
10
 
11
11
  /** 默认预算配置 */
12
12
  export const BUDGET = {
13
- CHANNEL_A_MAX: 400, // Always-On Rules 最大 token
13
+ CHANNEL_A_MAX: 400, // Always-On Rules 最大 token
14
14
  CHANNEL_B_MAX_PER_FILE: 750, // Smart Rules 每个主题文件最大 token
15
15
  CHANNEL_B_MAX_PATTERNS: 5, // Smart Rules 每个主题最多模式数
16
- CHANNEL_A_MAX_RULES: 8, // Always-On Rules 最多规则数
16
+ CHANNEL_A_MAX_RULES: 8, // Always-On Rules 最多规则数
17
17
  };
18
18
 
19
19
  /**
@@ -14,23 +14,28 @@
14
14
  const TOPIC_MAP = {
15
15
  networking: {
16
16
  dimensions: ['event-and-data-flow'],
17
- descriptionKeywords: 'network, HTTP, API, request, response, URL, fetch, socket, REST, download, upload, error handling, retry, timeout',
17
+ descriptionKeywords:
18
+ 'network, HTTP, API, request, response, URL, fetch, socket, REST, download, upload, error handling, retry, timeout',
18
19
  },
19
20
  ui: {
20
21
  dimensions: ['code-pattern'],
21
- descriptionKeywords: 'view, controller, UI, layout, animation, cell, table, collection, button, scroll, navigation, auto layout, gesture, storyboard',
22
+ descriptionKeywords:
23
+ 'view, controller, UI, layout, animation, cell, table, collection, button, scroll, navigation, auto layout, gesture, storyboard',
22
24
  },
23
25
  data: {
24
26
  dimensions: ['code-pattern', 'architecture'],
25
- descriptionKeywords: 'model, storage, database, cache, CoreData, Realm, SQLite, keychain, UserDefaults, JSON, parsing, serialization, persistence',
27
+ descriptionKeywords:
28
+ 'model, storage, database, cache, CoreData, Realm, SQLite, keychain, UserDefaults, JSON, parsing, serialization, persistence',
26
29
  },
27
30
  architecture: {
28
31
  dimensions: ['architecture', 'best-practice'],
29
- descriptionKeywords: 'singleton, delegate, factory, observer, protocol, manager, service, dependency injection, module, MVVM, MVC, coordinator, router, design pattern',
32
+ descriptionKeywords:
33
+ 'singleton, delegate, factory, observer, protocol, manager, service, dependency injection, module, MVVM, MVC, coordinator, router, design pattern',
30
34
  },
31
35
  conventions: {
32
36
  dimensions: ['code-standard'],
33
- descriptionKeywords: 'naming, format, style, import, header, prefix, convention, documentation, file organization, constants, enum, typedef, pragma mark',
37
+ descriptionKeywords:
38
+ 'naming, format, style, import, header, prefix, convention, documentation, file organization, constants, enum, typedef, pragma mark',
34
39
  },
35
40
  };
36
41
 
@@ -54,7 +59,9 @@ export class TopicClassifier {
54
59
  for (const entry of entries) {
55
60
  const topic = this._classifyEntry(entry);
56
61
  if (topic) {
57
- if (!grouped[topic]) grouped[topic] = [];
62
+ if (!grouped[topic]) {
63
+ grouped[topic] = [];
64
+ }
58
65
  grouped[topic].push(entry);
59
66
  } else {
60
67
  unmatched.push(entry);
@@ -79,13 +86,13 @@ export class TopicClassifier {
79
86
  const topicDef = TOPIC_MAP[topic];
80
87
  const baseKeywords = topicDef
81
88
  ? topicDef.descriptionKeywords
82
- : entries.map(e => (e.title || '')).filter(Boolean).join(', ');
89
+ : entries
90
+ .map((e) => e.title || '')
91
+ .filter(Boolean)
92
+ .join(', ');
83
93
 
84
94
  // 从 entries 提取额外关键词
85
- const entryKeywords = entries
86
- .map(e => this._extractKeywords(e))
87
- .flat()
88
- .filter(Boolean);
95
+ const entryKeywords = entries.flatMap((e) => this._extractKeywords(e)).filter(Boolean);
89
96
  const unique = [...new Set(entryKeywords)].slice(0, 10);
90
97
  const extra = unique.length > 0 ? `, ${unique.join(', ')}` : '';
91
98
 
@@ -97,7 +104,7 @@ export class TopicClassifier {
97
104
  * @private
98
105
  */
99
106
  _classifyEntry(entry) {
100
- return entry.topicHint || null; // AI 没给 → null → 归入 general
107
+ return entry.topicHint || null; // AI 没给 → null → 归入 general
101
108
  }
102
109
 
103
110
  /**
@@ -105,12 +112,10 @@ export class TopicClassifier {
105
112
  * @private
106
113
  */
107
114
  _extractKeywords(entry) {
108
- const text = (entry.title || '') + ' ' + (entry.description || '');
115
+ const text = `${entry.title || ''} ${entry.description || ''}`;
109
116
  // 提取英文关键词(3+ 字母)
110
117
  const words = text.match(/[a-zA-Z]{3,}/g) || [];
111
- const filtered = words
112
- .map(w => w.toLowerCase())
113
- .filter(w => !STOP_WORDS.has(w));
118
+ const filtered = words.map((w) => w.toLowerCase()).filter((w) => !STOP_WORDS.has(w));
114
119
  return [...new Set(filtered)].slice(0, 5);
115
120
  }
116
121
 
@@ -132,10 +137,39 @@ export class TopicClassifier {
132
137
 
133
138
  /** @type {Set<string>} */
134
139
  const STOP_WORDS = new Set([
135
- 'the', 'and', 'for', 'this', 'that', 'with', 'from', 'use', 'using',
136
- 'when', 'not', 'all', 'are', 'has', 'have', 'been', 'will', 'can',
137
- 'should', 'must', 'may', 'each', 'which', 'their', 'your', 'its',
138
- 'project', 'code', 'file', 'class', 'method', 'function', 'bootstrap',
140
+ 'the',
141
+ 'and',
142
+ 'for',
143
+ 'this',
144
+ 'that',
145
+ 'with',
146
+ 'from',
147
+ 'use',
148
+ 'using',
149
+ 'when',
150
+ 'not',
151
+ 'all',
152
+ 'are',
153
+ 'has',
154
+ 'have',
155
+ 'been',
156
+ 'will',
157
+ 'can',
158
+ 'should',
159
+ 'must',
160
+ 'may',
161
+ 'each',
162
+ 'which',
163
+ 'their',
164
+ 'your',
165
+ 'its',
166
+ 'project',
167
+ 'code',
168
+ 'file',
169
+ 'class',
170
+ 'method',
171
+ 'function',
172
+ 'bootstrap',
139
173
  ]);
140
174
 
141
175
  export default TopicClassifier;
@@ -13,8 +13,8 @@
13
13
  */
14
14
 
15
15
  import Logger from '../../infrastructure/logging/Logger.js';
16
- import { collectSourceFilesWithContent } from './SourceFileCollector.js';
17
16
  import { COMPLIANCE_SCORING, QUALITY_GATE } from '../../shared/constants.js';
17
+ import { collectSourceFilesWithContent } from './SourceFileCollector.js';
18
18
 
19
19
  /**
20
20
  * Quality Gate 评分算法
@@ -30,11 +30,15 @@ function computeScore(summary, ruleHealth = []) {
30
30
  // 加分:规则平均 F1 > 阈值加分
31
31
  if (ruleHealth.length > 0) {
32
32
  const avgF1 = ruleHealth.reduce((s, r) => s + (r.f1 || 0), 0) / ruleHealth.length;
33
- if (avgF1 > COMPLIANCE_SCORING.HIGH_F1_THRESHOLD) score += COMPLIANCE_SCORING.HIGH_F1_BONUS;
33
+ if (avgF1 > COMPLIANCE_SCORING.HIGH_F1_THRESHOLD) {
34
+ score += COMPLIANCE_SCORING.HIGH_F1_BONUS;
35
+ }
34
36
  }
35
37
 
36
38
  // 扣分:高误报规则每条扣分
37
- const problematic = ruleHealth.filter(r => (r.precision || 1) < COMPLIANCE_SCORING.LOW_PRECISION_THRESHOLD);
39
+ const problematic = ruleHealth.filter(
40
+ (r) => (r.precision || 1) < COMPLIANCE_SCORING.LOW_PRECISION_THRESHOLD
41
+ );
38
42
  score -= problematic.length * COMPLIANCE_SCORING.PROBLEMATIC_RULE_PENALTY;
39
43
 
40
44
  return Math.max(0, Math.min(100, Math.round(score)));
@@ -44,11 +48,21 @@ function computeScore(summary, ruleHealth = []) {
44
48
  * 判定 Quality Gate 状态
45
49
  */
46
50
  function evaluateGate(summary, score, thresholds) {
47
- const { maxErrors = QUALITY_GATE.MAX_ERRORS, maxWarnings = QUALITY_GATE.MAX_WARNINGS, minScore = QUALITY_GATE.MIN_SCORE } = thresholds;
48
-
49
- if (summary.errors > maxErrors) return 'FAIL';
50
- if (score < minScore) return 'FAIL';
51
- if (summary.warnings > maxWarnings) return 'WARN';
51
+ const {
52
+ maxErrors = QUALITY_GATE.MAX_ERRORS,
53
+ maxWarnings = QUALITY_GATE.MAX_WARNINGS,
54
+ minScore = QUALITY_GATE.MIN_SCORE,
55
+ } = thresholds;
56
+
57
+ if (summary.errors > maxErrors) {
58
+ return 'FAIL';
59
+ }
60
+ if (score < minScore) {
61
+ return 'FAIL';
62
+ }
63
+ if (summary.warnings > maxWarnings) {
64
+ return 'WARN';
65
+ }
52
66
  return 'PASS';
53
67
  }
54
68
 
@@ -60,7 +74,13 @@ export class ComplianceReporter {
60
74
  * @param {import('./ExclusionManager.js').ExclusionManager} exclusionManager
61
75
  * @param {object} qualityGateConfig - { maxErrors, maxWarnings, minScore }
62
76
  */
63
- constructor(guardCheckEngine, violationsStore, ruleLearner, exclusionManager, qualityGateConfig = {}) {
77
+ constructor(
78
+ guardCheckEngine,
79
+ violationsStore,
80
+ ruleLearner,
81
+ exclusionManager,
82
+ qualityGateConfig = {}
83
+ ) {
64
84
  this.engine = guardCheckEngine;
65
85
  this.violationsStore = violationsStore;
66
86
  this.ruleLearner = ruleLearner;
@@ -96,11 +116,15 @@ export class ComplianceReporter {
96
116
  // 3. 通过 ExclusionManager 过滤被排除的项
97
117
  const filteredFiles = [];
98
118
  for (const fileResult of auditResult.files || []) {
99
- if (this.exclusionManager?.isPathExcluded?.(fileResult.filePath)) continue;
119
+ if (this.exclusionManager?.isPathExcluded?.(fileResult.filePath)) {
120
+ continue;
121
+ }
100
122
 
101
- const filteredViolations = fileResult.violations.filter(v => {
123
+ const filteredViolations = fileResult.violations.filter((v) => {
102
124
  // isRuleExcluded 内部已检查全局排除
103
- if (this.exclusionManager?.isRuleExcluded?.(v.ruleId, fileResult.filePath)) return false;
125
+ if (this.exclusionManager?.isRuleExcluded?.(v.ruleId, fileResult.filePath)) {
126
+ return false;
127
+ }
104
128
  return true;
105
129
  });
106
130
 
@@ -109,9 +133,9 @@ export class ComplianceReporter {
109
133
  violations: filteredViolations,
110
134
  summary: {
111
135
  total: filteredViolations.length,
112
- errors: filteredViolations.filter(v => v.severity === 'error').length,
113
- warnings: filteredViolations.filter(v => v.severity === 'warning').length,
114
- infos: filteredViolations.filter(v => v.severity === 'info').length,
136
+ errors: filteredViolations.filter((v) => v.severity === 'error').length,
137
+ warnings: filteredViolations.filter((v) => v.severity === 'warning').length,
138
+ infos: filteredViolations.filter((v) => v.severity === 'info').length,
115
139
  },
116
140
  });
117
141
  }
@@ -151,14 +175,14 @@ export class ComplianceReporter {
151
175
  }
152
176
 
153
177
  const topViolations = [...ruleAgg.values()]
154
- .map(v => ({ ...v, fileCount: v.fileCount.size }))
178
+ .map((v) => ({ ...v, fileCount: v.fileCount.size }))
155
179
  .sort((a, b) => b.occurrences - a.occurrences)
156
180
  .slice(0, 20);
157
181
 
158
182
  // 6. 文件热点
159
183
  const fileHotspots = filteredFiles
160
- .filter(f => f.summary.total > 0)
161
- .map(f => ({
184
+ .filter((f) => f.summary.total > 0)
185
+ .map((f) => ({
162
186
  filePath: f.filePath,
163
187
  violationCount: f.summary.total,
164
188
  errorCount: f.summary.errors,
@@ -201,8 +225,8 @@ export class ComplianceReporter {
201
225
  // 10. 写入 ViolationsStore(记录本次运行)
202
226
  try {
203
227
  if (this.violationsStore?.appendRun) {
204
- const allViolations = filteredFiles.flatMap(f =>
205
- f.violations.map(v => ({ ...v, filePath: f.filePath }))
228
+ const allViolations = filteredFiles.flatMap((f) =>
229
+ f.violations.map((v) => ({ ...v, filePath: f.filePath }))
206
230
  );
207
231
  this.violationsStore.appendRun({
208
232
  filePath: projectRoot,
@@ -239,7 +263,6 @@ export class ComplianceReporter {
239
263
  const { format = 'text' } = options;
240
264
 
241
265
  if (format === 'json') {
242
- console.log(JSON.stringify(report, null, 2));
243
266
  return;
244
267
  }
245
268
 
@@ -253,38 +276,27 @@ export class ComplianceReporter {
253
276
  }
254
277
 
255
278
  _printText(report) {
256
- const { qualityGate, summary, topViolations, fileHotspots, trend } = report;
279
+ const { qualityGate, topViolations, fileHotspots, trend } = report;
257
280
 
258
- const gateIcon = qualityGate.status === 'PASS' ? '✅' : qualityGate.status === 'WARN' ? '⚠️' : '❌';
259
- console.log(`\n${''.repeat(60)}`);
260
- console.log(` 🛡️ Guard Compliance Report`);
261
- console.log(`${'═'.repeat(60)}`);
262
- console.log(` ${gateIcon} Quality Gate: ${qualityGate.status} (Score: ${qualityGate.score}/100)`);
263
- console.log(` 📁 Files Scanned: ${summary.filesScanned}`);
264
- console.log(` 📊 Violations: ${summary.errors} errors, ${summary.warnings} warnings, ${summary.infos || 0} infos`);
281
+ const _gateIcon =
282
+ qualityGate.status === 'PASS' ? '✅' : qualityGate.status === 'WARN' ? '⚠️' : '❌';
265
283
 
266
284
  if (trend.hasHistory) {
267
- const errTrend = trend.errorsChange > 0 ? `+${trend.errorsChange}` : `${trend.errorsChange}`;
268
- const warnTrend = trend.warningsChange > 0 ? `+${trend.warningsChange}` : `${trend.warningsChange}`;
269
- console.log(` 📈 Trend: errors ${errTrend}, warnings ${warnTrend}`);
285
+ const _errTrend = trend.errorsChange > 0 ? `+${trend.errorsChange}` : `${trend.errorsChange}`;
286
+ const _warnTrend =
287
+ trend.warningsChange > 0 ? `+${trend.warningsChange}` : `${trend.warningsChange}`;
270
288
  }
271
289
 
272
290
  if (topViolations.length > 0) {
273
- console.log(`\n Top Violations:`);
274
291
  for (const v of topViolations.slice(0, 10)) {
275
- const fix = v.fixRecipeId ? ` → 🔧 recipe:${v.fixRecipeId}` : '';
276
- console.log(` [${v.severity}] ${v.ruleId} — ${v.occurrences} hits in ${v.fileCount} files${fix}`);
292
+ const _fix = v.fixRecipeId ? ` → 🔧 recipe:${v.fixRecipeId}` : '';
277
293
  }
278
294
  }
279
295
 
280
296
  if (fileHotspots.length > 0) {
281
- console.log(`\n File Hotspots:`);
282
- for (const f of fileHotspots.slice(0, 10)) {
283
- console.log(` 📄 ${f.filePath} — ${f.violationCount} violations (${f.errorCount} errors)`);
297
+ for (const _f of fileHotspots.slice(0, 10)) {
284
298
  }
285
299
  }
286
-
287
- console.log(`${'═'.repeat(60)}\n`);
288
300
  }
289
301
 
290
302
  _printMarkdown(report) {
@@ -303,7 +315,9 @@ export class ComplianceReporter {
303
315
 
304
316
  if (trend.hasHistory) {
305
317
  lines.push(`| Errors Trend | ${trend.errorsChange > 0 ? '+' : ''}${trend.errorsChange} |`);
306
- lines.push(`| Warnings Trend | ${trend.warningsChange > 0 ? '+' : ''}${trend.warningsChange} |`);
318
+ lines.push(
319
+ `| Warnings Trend | ${trend.warningsChange > 0 ? '+' : ''}${trend.warningsChange} |`
320
+ );
307
321
  }
308
322
 
309
323
  if (topViolations.length > 0) {
@@ -328,8 +342,6 @@ export class ComplianceReporter {
328
342
  lines.push(`| ${f.filePath} | ${f.violationCount} | ${f.errorCount} |`);
329
343
  }
330
344
  }
331
-
332
- console.log(lines.join('\n'));
333
345
  }
334
346
  }
335
347