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
@@ -7,38 +7,16 @@
7
7
  * - 主语言 → 语言扩展字段(分析维度、典型模式、反模式、Guard 规则等)
8
8
  */
9
9
 
10
- import path from 'path';
10
+ import { LanguageService } from '../../../shared/LanguageService.js';
11
11
 
12
- /** 根据文件扩展名推断语言 */
12
+ /** 根据文件扩展名推断语言 — 委托给 LanguageService(唯一来源) */
13
13
  export function inferLang(filename) {
14
- const ext = path.extname(filename).toLowerCase();
15
- const map = {
16
- '.swift': 'swift', '.m': 'objectivec', '.h': 'objectivec', '.mm': 'objectivec',
17
- '.c': 'c', '.cpp': 'cpp', '.js': 'javascript', '.ts': 'typescript',
18
- '.py': 'python', '.rb': 'ruby', '.java': 'java', '.kt': 'kotlin',
19
- };
20
- return map[ext] || 'unknown';
14
+ return LanguageService.inferLang(filename);
21
15
  }
22
16
 
23
- /** 从 langStats 推断主语言 — 按映射后的语言聚合计数 */
17
+ /** 从 langStats 推断主语言 — 委托给 LanguageService(唯一来源) */
24
18
  export function detectPrimaryLanguage(langStats) {
25
- const langMap = {
26
- swift: 'swift', m: 'objectivec', h: 'objectivec', mm: 'objectivec',
27
- c: 'c', cpp: 'cpp', js: 'javascript', ts: 'typescript', jsx: 'javascript', tsx: 'typescript',
28
- py: 'python', rb: 'ruby', java: 'java', kt: 'kotlin', go: 'go', rs: 'rust',
29
- dart: 'dart', cs: 'csharp',
30
- };
31
- // 按映射后的语言聚合计数,避免多扩展名语言(ObjC .h/.m/.mm)计数分散
32
- const aggregated = {};
33
- for (const [ext, count] of Object.entries(langStats)) {
34
- const lang = langMap[ext] || ext;
35
- aggregated[lang] = (aggregated[lang] || 0) + count;
36
- }
37
- let best = 'unknown', bestCount = 0;
38
- for (const [lang, count] of Object.entries(aggregated)) {
39
- if (count > bestCount) { best = lang; bestCount = count; }
40
- }
41
- return best;
19
+ return LanguageService.detectPrimary(langStats);
42
20
  }
43
21
 
44
22
  /**
@@ -59,10 +37,26 @@ export function buildLanguageExtension(lang) {
59
37
  switch (lang) {
60
38
  case 'swift':
61
39
  base.extraDimensions = [
62
- { id: 'concurrency', label: 'Swift Concurrency', guide: 'async/await、Actor、@Sendable、TaskGroup、MainActor 用法' },
63
- { id: 'protocol-oriented', label: '面向协议编程', guide: 'Protocol 扩展、条件一致性、PAT (Protocol with Associated Type)' },
64
- { id: 'property-wrapper', label: 'Property Wrapper', guide: '@Published、@State、@Environment、自定义 Property Wrapper' },
65
- { id: 'value-semantics', label: '值语义', guide: 'struct vs class 决策、COW (Copy-on-Write)、Equatable/Hashable' },
40
+ {
41
+ id: 'concurrency',
42
+ label: 'Swift Concurrency',
43
+ guide: 'async/await、Actor、@Sendable、TaskGroup、MainActor 用法',
44
+ },
45
+ {
46
+ id: 'protocol-oriented',
47
+ label: '面向协议编程',
48
+ guide: 'Protocol 扩展、条件一致性、PAT (Protocol with Associated Type)',
49
+ },
50
+ {
51
+ id: 'property-wrapper',
52
+ label: 'Property Wrapper',
53
+ guide: '@Published、@State、@Environment、自定义 Property Wrapper',
54
+ },
55
+ {
56
+ id: 'value-semantics',
57
+ label: '值语义',
58
+ guide: 'struct vs class 决策、COW (Copy-on-Write)、Equatable/Hashable',
59
+ },
66
60
  ];
67
61
  base.typicalPatterns = [
68
62
  'Result<Success, Failure> 统一错误处理',
@@ -74,8 +68,16 @@ export function buildLanguageExtension(lang) {
74
68
  ];
75
69
  base.commonAntiPatterns = [
76
70
  { bad: '强制 try! / as! 解包', why: '运行时 crash', fix: 'guard let / if let / do-catch' },
77
- { bad: 'DispatchQueue.main.async 更新 UI', why: 'Swift Concurrency 下造成 data race', fix: '@MainActor' },
78
- { bad: '闭包中不用 [weak self]', why: '循环引用导致内存泄漏', fix: '[weak self] / [unowned self]' },
71
+ {
72
+ bad: 'DispatchQueue.main.async 更新 UI',
73
+ why: 'Swift Concurrency 下造成 data race',
74
+ fix: '@MainActor',
75
+ },
76
+ {
77
+ bad: '闭包中不用 [weak self]',
78
+ why: '循环引用导致内存泄漏',
79
+ fix: '[weak self] / [unowned self]',
80
+ },
79
81
  ];
80
82
  base.suggestedGuardRules = [
81
83
  { pattern: 'try!', severity: 'warning', message: '避免 force try,使用 do-catch' },
@@ -93,10 +95,26 @@ export function buildLanguageExtension(lang) {
93
95
 
94
96
  case 'objectivec':
95
97
  base.extraDimensions = [
96
- { id: 'memory-management', label: '内存管理', guide: 'ARC 下的 strong/weak/unsafe_unretained、autorelease、dealloc 模式' },
97
- { id: 'category-extension', label: 'Category/Extension', guide: 'Category 方法命名冲突、Class Extension 私有属性' },
98
- { id: 'block-pattern', label: 'Block 模式', guide: 'Block 循环引用、__weak/__strong dance、Block 作为回调' },
99
- { id: 'nullability', label: 'Nullability 标注', guide: 'nullable/nonnull/NS_ASSUME_NONNULL、与 Swift 互操作' },
98
+ {
99
+ id: 'memory-management',
100
+ label: '内存管理',
101
+ guide: 'ARC 下的 strong/weak/unsafe_unretained、autorelease、dealloc 模式',
102
+ },
103
+ {
104
+ id: 'category-extension',
105
+ label: 'Category/Extension',
106
+ guide: 'Category 方法命名冲突、Class Extension 私有属性',
107
+ },
108
+ {
109
+ id: 'block-pattern',
110
+ label: 'Block 模式',
111
+ guide: 'Block 循环引用、__weak/__strong dance、Block 作为回调',
112
+ },
113
+ {
114
+ id: 'nullability',
115
+ label: 'Nullability 标注',
116
+ guide: 'nullable/nonnull/NS_ASSUME_NONNULL、与 Swift 互操作',
117
+ },
100
118
  ];
101
119
  base.typicalPatterns = [
102
120
  'delegate + protocol 回调模式',
@@ -108,11 +126,23 @@ export function buildLanguageExtension(lang) {
108
126
  ];
109
127
  base.commonAntiPatterns = [
110
128
  { bad: 'Block 内直接引用 self', why: '循环引用', fix: '__weak + __strong dance' },
111
- { bad: '头文件缺少 nullability 标注', why: 'Swift 桥接时全部变为 optional', fix: 'NS_ASSUME_NONNULL + 显式 nullable' },
112
- { bad: 'Category 方法不带前缀', why: '与系统方法/其他库冲突', fix: '加项目前缀如 xx_methodName' },
129
+ {
130
+ bad: '头文件缺少 nullability 标注',
131
+ why: 'Swift 桥接时全部变为 optional',
132
+ fix: 'NS_ASSUME_NONNULL + 显式 nullable',
133
+ },
134
+ {
135
+ bad: 'Category 方法不带前缀',
136
+ why: '与系统方法/其他库冲突',
137
+ fix: '加项目前缀如 xx_methodName',
138
+ },
113
139
  ];
114
140
  base.suggestedGuardRules = [
115
- { pattern: '\\[self\\s', severity: 'warning', message: 'Block 内直接引用 self,考虑 __weak' },
141
+ {
142
+ pattern: '\\[self\\s',
143
+ severity: 'warning',
144
+ message: 'Block 内直接引用 self,考虑 __weak',
145
+ },
116
146
  ];
117
147
  base.agentCautions = [
118
148
  'ObjC 头文件必须包含 NS_ASSUME_NONNULL_BEGIN/END',
@@ -125,10 +155,29 @@ export function buildLanguageExtension(lang) {
125
155
  case 'typescript':
126
156
  case 'javascript':
127
157
  base.extraDimensions = [
128
- { id: 'module-system', label: '模块系统', guide: 'ESM vs CJS、dynamic import、barrel export、tree-shaking' },
129
- { id: 'type-safety', label: '类型安全', guide: lang === 'typescript' ? 'strict 模式、泛型、类型守卫、Utility Types' : 'JSDoc 类型标注、.d.ts 声明' },
130
- { id: 'async-pattern', label: '异步模式', guide: 'Promise 链、async/await、Error 处理、AbortController' },
131
- { id: 'framework-convention', label: '框架约定', guide: 'React Hooks/Vue Composition/Node.js 中间件等框架特有模式' },
158
+ {
159
+ id: 'module-system',
160
+ label: '模块系统',
161
+ guide: 'ESM vs CJS、dynamic import、barrel export、tree-shaking',
162
+ },
163
+ {
164
+ id: 'type-safety',
165
+ label: '类型安全',
166
+ guide:
167
+ lang === 'typescript'
168
+ ? 'strict 模式、泛型、类型守卫、Utility Types'
169
+ : 'JSDoc 类型标注、.d.ts 声明',
170
+ },
171
+ {
172
+ id: 'async-pattern',
173
+ label: '异步模式',
174
+ guide: 'Promise 链、async/await、Error 处理、AbortController',
175
+ },
176
+ {
177
+ id: 'framework-convention',
178
+ label: '框架约定',
179
+ guide: 'React Hooks/Vue Composition/Node.js 中间件等框架特有模式',
180
+ },
132
181
  ];
133
182
  base.typicalPatterns = [
134
183
  'async/await + try-catch 错误处理',
@@ -157,9 +206,17 @@ export function buildLanguageExtension(lang) {
157
206
 
158
207
  case 'python':
159
208
  base.extraDimensions = [
160
- { id: 'type-hints', label: '类型注解', guide: 'typing 模块、Protocol、TypeVar、Generic、dataclass' },
209
+ {
210
+ id: 'type-hints',
211
+ label: '类型注解',
212
+ guide: 'typing 模块、Protocol、TypeVar、Generic、dataclass',
213
+ },
161
214
  { id: 'async-io', label: '异步 IO', guide: 'asyncio、aiohttp、async generators' },
162
- { id: 'package-structure', label: '包结构', guide: '__init__.py、相对导入、pyproject.toml' },
215
+ {
216
+ id: 'package-structure',
217
+ label: '包结构',
218
+ guide: '__init__.py、相对导入、pyproject.toml',
219
+ },
163
220
  ];
164
221
  base.typicalPatterns = [
165
222
  'dataclass 数据建模',
@@ -205,8 +262,16 @@ export function buildLanguageExtension(lang) {
205
262
 
206
263
  case 'java':
207
264
  base.extraDimensions = [
208
- { id: 'concurrency', label: '并发', guide: 'synchronized、ExecutorService、CompletableFuture、虚拟线程 (21+)' },
209
- { id: 'generics', label: '泛型', guide: '类型擦除、通配符 <? extends/super>、类型安全容器' },
265
+ {
266
+ id: 'concurrency',
267
+ label: '并发',
268
+ guide: 'synchronized、ExecutorService、CompletableFuture、虚拟线程 (21+)',
269
+ },
270
+ {
271
+ id: 'generics',
272
+ label: '泛型',
273
+ guide: '类型擦除、通配符 <? extends/super>、类型安全容器',
274
+ },
210
275
  ];
211
276
  base.typicalPatterns = [
212
277
  'Builder 模式',
@@ -224,8 +289,16 @@ export function buildLanguageExtension(lang) {
224
289
 
225
290
  case 'go':
226
291
  base.extraDimensions = [
227
- { id: 'goroutine', label: 'Goroutine/Channel', guide: '并发模式、channel、select、context 传播' },
228
- { id: 'error-handling', label: '错误处理', guide: 'error interface、errors.Is/As、sentinel errors、%w wrap' },
292
+ {
293
+ id: 'goroutine',
294
+ label: 'Goroutine/Channel',
295
+ guide: '并发模式、channel、select、context 传播',
296
+ },
297
+ {
298
+ id: 'error-handling',
299
+ label: '错误处理',
300
+ guide: 'error interface、errors.Is/As、sentinel errors、%w wrap',
301
+ },
229
302
  { id: 'interface', label: '接口设计', guide: '隐式实现、小接口、io.Reader/Writer 组合' },
230
303
  ];
231
304
  base.typicalPatterns = [
@@ -244,9 +317,21 @@ export function buildLanguageExtension(lang) {
244
317
 
245
318
  case 'rust':
246
319
  base.extraDimensions = [
247
- { id: 'ownership', label: '所有权/借用', guide: 'ownership、borrowing、lifetime、Clone vs Copy' },
248
- { id: 'error-handling', label: '错误处理', guide: 'Result<T,E>、? 操作符、thiserror/anyhow' },
249
- { id: 'trait-system', label: 'Trait 系统', guide: 'trait bound、impl Trait、dyn Trait、derive 宏' },
320
+ {
321
+ id: 'ownership',
322
+ label: '所有权/借用',
323
+ guide: 'ownership、borrowing、lifetime、Clone vs Copy',
324
+ },
325
+ {
326
+ id: 'error-handling',
327
+ label: '错误处理',
328
+ guide: 'Result<T,E>、? 操作符、thiserror/anyhow',
329
+ },
330
+ {
331
+ id: 'trait-system',
332
+ label: 'Trait 系统',
333
+ guide: 'trait bound、impl Trait、dyn Trait、derive 宏',
334
+ },
250
335
  ];
251
336
  base.typicalPatterns = [
252
337
  'Result<T, E> + ? 操作符',
@@ -9,18 +9,42 @@
9
9
  /** 根据 Target 名称推断模块职责 */
10
10
  export function inferTargetRole(targetName) {
11
11
  const n = targetName.toLowerCase();
12
- if (/core|kit|shared|common|foundation|base/i.test(n)) return 'core';
13
- if (/service|manager|provider|repository|store/i.test(n)) return 'service';
14
- if (/ui|view|screen|component|widget/i.test(n)) return 'ui';
15
- if (/network|api|http|grpc|socket/i.test(n)) return 'networking';
16
- if (/storage|database|cache|persist|realm|coredata/i.test(n)) return 'storage';
17
- if (/test|spec|mock|stub|fake/i.test(n)) return 'test';
18
- if (/app|main|launch|entry/i.test(n)) return 'app';
19
- if (/router|coordinator|navigation/i.test(n)) return 'routing';
20
- if (/util|helper|extension|tool/i.test(n)) return 'utility';
21
- if (/model|entity|dto|schema/i.test(n)) return 'model';
22
- if (/auth|login|session|token/i.test(n)) return 'auth';
23
- if (/config|setting|environment|constant/i.test(n)) return 'config';
12
+ if (/core|kit|shared|common|foundation|base/i.test(n)) {
13
+ return 'core';
14
+ }
15
+ if (/service|manager|provider|repository|store/i.test(n)) {
16
+ return 'service';
17
+ }
18
+ if (/ui|view|screen|component|widget/i.test(n)) {
19
+ return 'ui';
20
+ }
21
+ if (/network|api|http|grpc|socket/i.test(n)) {
22
+ return 'networking';
23
+ }
24
+ if (/storage|database|cache|persist|realm|coredata/i.test(n)) {
25
+ return 'storage';
26
+ }
27
+ if (/test|spec|mock|stub|fake/i.test(n)) {
28
+ return 'test';
29
+ }
30
+ if (/app|main|launch|entry/i.test(n)) {
31
+ return 'app';
32
+ }
33
+ if (/router|coordinator|navigation/i.test(n)) {
34
+ return 'routing';
35
+ }
36
+ if (/util|helper|extension|tool/i.test(n)) {
37
+ return 'utility';
38
+ }
39
+ if (/model|entity|dto|schema/i.test(n)) {
40
+ return 'model';
41
+ }
42
+ if (/auth|login|session|token/i.test(n)) {
43
+ return 'auth';
44
+ }
45
+ if (/config|setting|environment|constant/i.test(n)) {
46
+ return 'config';
47
+ }
24
48
  return 'feature';
25
49
  }
26
50
 
@@ -28,11 +52,23 @@ export function inferTargetRole(targetName) {
28
52
  export function inferFilePriority(filename) {
29
53
  const n = filename.toLowerCase();
30
54
  // High: core definitions, services, protocols, configs
31
- if (/protocol|interface|delegate|service|manager|provider|config|constant|router|coordinator|factory|builder/i.test(n)) return 'high';
32
- if (/^(app|main|launch|entry|bootstrap)/i.test(n)) return 'high';
55
+ if (
56
+ /protocol|interface|delegate|service|manager|provider|config|constant|router|coordinator|factory|builder/i.test(
57
+ n
58
+ )
59
+ ) {
60
+ return 'high';
61
+ }
62
+ if (/^(app|main|launch|entry|bootstrap)/i.test(n)) {
63
+ return 'high';
64
+ }
33
65
  // Low: tests, extensions, helpers, generated
34
- if (/test|spec|mock|stub|fake|\+|\bext\b|extension|helper|generated|\.pb\./i.test(n)) return 'low';
35
- if (/readme|changelog|license/i.test(n)) return 'low';
66
+ if (/test|spec|mock|stub|fake|\+|\bext\b|extension|helper|generated|\.pb\./i.test(n)) {
67
+ return 'low';
68
+ }
69
+ if (/readme|changelog|license/i.test(n)) {
70
+ return 'low';
71
+ }
36
72
  // Medium: everything else
37
73
  return 'medium';
38
74
  }
@@ -46,7 +46,9 @@ export class BootstrapSnapshot {
46
46
  * @param {object} [opts.logger]
47
47
  */
48
48
  constructor(db, { logger } = {}) {
49
- if (!db) throw new Error('BootstrapSnapshot requires a database instance');
49
+ if (!db) {
50
+ throw new Error('BootstrapSnapshot requires a database instance');
51
+ }
50
52
  this.#db = typeof db?.getDb === 'function' ? db.getDb() : db;
51
53
  this.#logger = logger || null;
52
54
 
@@ -134,9 +136,12 @@ export class BootstrapSnapshot {
134
136
  for (const [dimId, stat] of Object.entries(dimensionStats || {})) {
135
137
  const refFiles = stat.referencedFilesList || [];
136
138
  for (const filePath of refFiles) {
137
- const rel = typeof filePath === 'string'
138
- ? (filePath.startsWith('/') ? relative(projectRoot, filePath) : filePath)
139
- : filePath;
139
+ const rel =
140
+ typeof filePath === 'string'
141
+ ? filePath.startsWith('/')
142
+ ? relative(projectRoot, filePath)
143
+ : filePath
144
+ : filePath;
140
145
  this.#stmts.insertDimFile.run({
141
146
  snapshot_id: id,
142
147
  dim_id: dimId,
@@ -152,7 +157,9 @@ export class BootstrapSnapshot {
152
157
 
153
158
  saveTransaction();
154
159
 
155
- this.#log(`Snapshot saved: ${id} (${allFiles.length} files, ${Object.keys(dimensionStats || {}).length} dims)`);
160
+ this.#log(
161
+ `Snapshot saved: ${id} (${allFiles.length} files, ${Object.keys(dimensionStats || {}).length} dims)`
162
+ );
156
163
  return id;
157
164
  }
158
165
 
@@ -182,7 +189,9 @@ export class BootstrapSnapshot {
182
189
  */
183
190
  getLatest(projectRoot) {
184
191
  const row = this.#stmts.getLatest.get(projectRoot);
185
- if (!row) return null;
192
+ if (!row) {
193
+ return null;
194
+ }
186
195
  return this.#deserialize(row);
187
196
  }
188
197
 
@@ -193,7 +202,9 @@ export class BootstrapSnapshot {
193
202
  */
194
203
  getById(id) {
195
204
  const row = this.#stmts.getById.get(id);
196
- if (!row) return null;
205
+ if (!row) {
206
+ return null;
207
+ }
197
208
  return this.#deserialize(row);
198
209
  }
199
210
 
@@ -204,8 +215,7 @@ export class BootstrapSnapshot {
204
215
  * @returns {Array<object>}
205
216
  */
206
217
  list(projectRoot, limit = 10) {
207
- return this.#stmts.listByProject.all(projectRoot, limit)
208
- .map(r => this.#deserialize(r));
218
+ return this.#stmts.listByProject.all(projectRoot, limit).map((r) => this.#deserialize(r));
209
219
  }
210
220
 
211
221
  // ─── 增量 Diff 计算 ──────────────────────────────────
@@ -244,7 +254,7 @@ export class BootstrapSnapshot {
244
254
  }
245
255
 
246
256
  // 已删除的文件
247
- const deleted = Object.keys(oldHashes).filter(p => !(p in newHashes));
257
+ const deleted = Object.keys(oldHashes).filter((p) => !(p in newHashes));
248
258
 
249
259
  const totalFiles = Object.keys(newHashes).length || 1;
250
260
  const changedCount = added.length + modified.length + deleted.length;
@@ -269,8 +279,12 @@ export class BootstrapSnapshot {
269
279
  * @returns {{ mode: 'incremental'|'full', dimensions: string[], skippedDimensions: string[], reason: string }}
270
280
  */
271
281
  inferAffectedDimensions(snapshot, diff, allDimIds) {
272
- const changeRatio = (diff.added.length + diff.modified.length + diff.deleted.length) /
273
- (diff.added.length + diff.modified.length + diff.deleted.length + (diff.unchanged?.length || 0) || 1);
282
+ const changeRatio =
283
+ (diff.added.length + diff.modified.length + diff.deleted.length) /
284
+ (diff.added.length +
285
+ diff.modified.length +
286
+ diff.deleted.length +
287
+ (diff.unchanged?.length || 0) || 1);
274
288
 
275
289
  // 变更超过 50% → 全量
276
290
  if (changeRatio > FULL_REBUILD_THRESHOLD) {
@@ -322,8 +336,8 @@ export class BootstrapSnapshot {
322
336
  affected.add('project-profile');
323
337
  }
324
338
 
325
- const dimensions = allDimIds.filter(d => affected.has(d));
326
- const skippedDimensions = allDimIds.filter(d => !affected.has(d));
339
+ const dimensions = allDimIds.filter((d) => affected.has(d));
340
+ const skippedDimensions = allDimIds.filter((d) => !affected.has(d));
327
341
 
328
342
  return {
329
343
  mode: 'incremental',
@@ -344,7 +358,9 @@ export class BootstrapSnapshot {
344
358
  const rows = this.#stmts.getDimFiles.all(snapshotId);
345
359
  const map = {};
346
360
  for (const row of rows) {
347
- if (!map[row.dim_id]) map[row.dim_id] = new Set();
361
+ if (!map[row.dim_id]) {
362
+ map[row.dim_id] = new Set();
363
+ }
348
364
  map[row.dim_id].add(row.file_path);
349
365
  }
350
366
  return map;
@@ -376,19 +392,61 @@ export class BootstrapSnapshot {
376
392
  dims.push('code-standard', 'architecture');
377
393
  }
378
394
 
395
+ // TS/JS 相关
396
+ if (['ts', 'tsx', 'js', 'jsx', 'mjs', 'cjs', 'vue', 'svelte'].includes(ext)) {
397
+ dims.push('module-export-scan', 'code-standard', 'architecture');
398
+ }
399
+
400
+ // Python 相关
401
+ if (ext === 'py') {
402
+ dims.push('python-package-scan', 'code-standard', 'architecture');
403
+ }
404
+
405
+ // Java/Kotlin 相关
406
+ if (['java', 'kt', 'kts'].includes(ext)) {
407
+ dims.push('jvm-annotation-scan', 'code-standard', 'architecture');
408
+ }
409
+
379
410
  // 配置文件
380
- if (['json', 'yaml', 'yml', 'plist', 'xcconfig'].includes(ext)) {
411
+ if (
412
+ ['json', 'yaml', 'yml', 'plist', 'xcconfig', 'toml', 'properties', 'gradle'].includes(ext)
413
+ ) {
381
414
  dims.push('project-profile');
382
415
  }
383
416
 
384
417
  // 通用: 代码文件都可能影响 code-pattern 和 best-practice
385
- if (['m', 'mm', 'h', 'swift', 'js', 'ts', 'py'].includes(ext)) {
418
+ if (
419
+ [
420
+ 'm',
421
+ 'mm',
422
+ 'h',
423
+ 'swift',
424
+ 'js',
425
+ 'jsx',
426
+ 'ts',
427
+ 'tsx',
428
+ 'mjs',
429
+ 'cjs',
430
+ 'py',
431
+ 'java',
432
+ 'kt',
433
+ 'kts',
434
+ 'go',
435
+ 'rs',
436
+ 'rb',
437
+ ].includes(ext)
438
+ ) {
386
439
  dims.push('code-pattern', 'best-practice');
387
440
  }
388
441
 
389
442
  // 数据流相关
390
- if (name.includes('manager') || name.includes('service') || name.includes('event') ||
391
- name.includes('notification') || name.includes('delegate')) {
443
+ if (
444
+ name.includes('manager') ||
445
+ name.includes('service') ||
446
+ name.includes('event') ||
447
+ name.includes('notification') ||
448
+ name.includes('delegate')
449
+ ) {
392
450
  dims.push('event-and-data-flow');
393
451
  }
394
452
 
@@ -398,7 +456,10 @@ export class BootstrapSnapshot {
398
456
  // ─── 内部方法 ─────────────────────────────────────────
399
457
 
400
458
  #computeContentHash(content) {
401
- return createHash('sha256').update(content || '').digest('hex').substring(0, 16);
459
+ return createHash('sha256')
460
+ .update(content || '')
461
+ .digest('hex')
462
+ .substring(0, 16);
402
463
  }
403
464
 
404
465
  #readFileContent(filePath) {