autosnippet 3.2.21 → 3.3.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 (311) hide show
  1. package/dashboard/dist/assets/icons-BJ2mUBi8.js +1 -0
  2. package/dashboard/dist/assets/index-B659K9t5.js +128 -0
  3. package/dashboard/dist/assets/index-NCm40PMD.css +1 -0
  4. package/dashboard/dist/index.html +3 -3
  5. package/dist/bin/cli.d.ts +1 -1
  6. package/dist/bin/cli.js +244 -261
  7. package/dist/lib/agent/context/ExplorationTracker.d.ts +2 -0
  8. package/dist/lib/agent/context/ExplorationTracker.js +21 -3
  9. package/dist/lib/agent/core/ToolExecutionPipeline.d.ts +3 -1
  10. package/dist/lib/agent/core/ToolExecutionPipeline.js +8 -1
  11. package/dist/lib/agent/forge/DynamicComposer.d.ts +58 -0
  12. package/dist/lib/agent/forge/DynamicComposer.js +99 -0
  13. package/dist/lib/agent/forge/SandboxRunner.d.ts +60 -0
  14. package/dist/lib/agent/forge/SandboxRunner.js +251 -0
  15. package/dist/lib/agent/forge/TemporaryToolRegistry.d.ts +76 -0
  16. package/dist/lib/agent/forge/TemporaryToolRegistry.js +154 -0
  17. package/dist/lib/agent/forge/ToolForge.d.ts +92 -0
  18. package/dist/lib/agent/forge/ToolForge.js +239 -0
  19. package/dist/lib/agent/forge/ToolRequirementAnalyzer.d.ts +44 -0
  20. package/dist/lib/agent/forge/ToolRequirementAnalyzer.js +119 -0
  21. package/dist/lib/agent/tools/ToolRegistry.d.ts +2 -0
  22. package/dist/lib/agent/tools/ToolRegistry.js +4 -0
  23. package/dist/lib/agent/tools/composite.js +0 -1
  24. package/dist/lib/agent/tools/index.d.ts +2 -50
  25. package/dist/lib/agent/tools/index.js +2 -3
  26. package/dist/lib/agent/tools/lifecycle.d.ts +1 -58
  27. package/dist/lib/agent/tools/lifecycle.js +2 -75
  28. package/dist/lib/cli/SetupService.d.ts +46 -2
  29. package/dist/lib/cli/SetupService.js +2 -27
  30. package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
  31. package/dist/lib/cli/deploy/FileManifest.js +0 -11
  32. package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.d.ts +2 -5
  33. package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.js +159 -44
  34. package/dist/lib/core/discovery/index.d.ts +1 -1
  35. package/dist/lib/core/discovery/index.js +2 -2
  36. package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +10 -0
  37. package/dist/lib/domain/knowledge/KnowledgeEntry.js +2 -0
  38. package/dist/lib/domain/knowledge/Lifecycle.d.ts +19 -2
  39. package/dist/lib/domain/knowledge/Lifecycle.js +32 -6
  40. package/dist/lib/domain/knowledge/UnifiedValidator.d.ts +1 -5
  41. package/dist/lib/domain/knowledge/UnifiedValidator.js +7 -44
  42. package/dist/lib/domain/knowledge/values/Stats.d.ts +29 -0
  43. package/dist/lib/domain/knowledge/values/Stats.js +41 -0
  44. package/dist/lib/external/mcp/McpServer.d.ts +19 -38
  45. package/dist/lib/external/mcp/McpServer.js +145 -117
  46. package/dist/lib/external/mcp/autoApproveInjector.js +0 -2
  47. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +26 -1
  48. package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +41 -0
  49. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -0
  50. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +3 -0
  51. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +27 -0
  52. package/dist/lib/external/mcp/handlers/bootstrap/skills.js +1 -1
  53. package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -0
  54. package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
  55. package/dist/lib/external/mcp/handlers/consolidated.d.ts +116 -6
  56. package/dist/lib/external/mcp/handlers/consolidated.js +251 -71
  57. package/dist/lib/external/mcp/handlers/guard.d.ts +150 -0
  58. package/dist/lib/external/mcp/handlers/guard.js +245 -8
  59. package/dist/lib/external/mcp/handlers/knowledge.d.ts +0 -29
  60. package/dist/lib/external/mcp/handlers/knowledge.js +1 -76
  61. package/dist/lib/external/mcp/handlers/panorama.d.ts +36 -0
  62. package/dist/lib/external/mcp/handlers/panorama.js +156 -0
  63. package/dist/lib/external/mcp/handlers/system.d.ts +2 -54
  64. package/dist/lib/external/mcp/handlers/system.js +3 -113
  65. package/dist/lib/external/mcp/handlers/task.d.ts +13 -24
  66. package/dist/lib/external/mcp/handlers/task.js +217 -557
  67. package/dist/lib/external/mcp/handlers/types.d.ts +91 -8
  68. package/dist/lib/external/mcp/handlers/types.js +18 -1
  69. package/dist/lib/external/mcp/handlers/wiki-external.d.ts +18 -1
  70. package/dist/lib/external/mcp/handlers/wiki-external.js +16 -1
  71. package/dist/lib/external/mcp/tools.d.ts +14 -20
  72. package/dist/lib/external/mcp/tools.js +62 -91
  73. package/dist/lib/http/HttpServer.js +52 -6
  74. package/dist/lib/http/routes/{snippets.d.ts → audit.d.ts} +4 -2
  75. package/dist/lib/http/routes/audit.js +51 -0
  76. package/dist/lib/http/routes/commands.d.ts +1 -1
  77. package/dist/lib/http/routes/commands.js +1 -66
  78. package/dist/lib/http/routes/guardReport.d.ts +10 -0
  79. package/dist/lib/http/routes/guardReport.js +143 -0
  80. package/dist/lib/http/routes/knowledge.js +32 -1
  81. package/dist/lib/http/routes/panorama.d.ts +11 -0
  82. package/dist/lib/http/routes/panorama.js +322 -0
  83. package/dist/lib/http/routes/remote.js +0 -5
  84. package/dist/lib/http/routes/signals.d.ts +10 -0
  85. package/dist/lib/http/routes/signals.js +104 -0
  86. package/dist/lib/http/routes/task.d.ts +2 -3
  87. package/dist/lib/http/routes/task.js +17 -347
  88. package/dist/lib/http/routes/violations.js +1 -1
  89. package/dist/lib/infrastructure/audit/AuditLogger.d.ts +6 -1
  90. package/dist/lib/infrastructure/audit/AuditLogger.js +14 -1
  91. package/dist/lib/infrastructure/database/drizzle/schema.d.ts +181 -583
  92. package/dist/lib/infrastructure/database/drizzle/schema.js +28 -69
  93. package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.d.ts +8 -0
  94. package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.js +43 -0
  95. package/dist/lib/infrastructure/logging/Logger.d.ts +2 -0
  96. package/dist/lib/infrastructure/logging/Logger.js +34 -7
  97. package/dist/lib/infrastructure/monitoring/ErrorTracker.js +3 -1
  98. package/dist/lib/infrastructure/monitoring/PerformanceMonitor.d.ts +2 -2
  99. package/dist/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -10
  100. package/dist/lib/infrastructure/notification/LarkNotifier.d.ts +24 -0
  101. package/dist/lib/infrastructure/notification/LarkNotifier.js +97 -0
  102. package/dist/lib/infrastructure/report/ReportStore.d.ts +45 -0
  103. package/dist/lib/infrastructure/report/ReportStore.js +133 -0
  104. package/dist/lib/infrastructure/signal/SignalAggregator.d.ts +18 -0
  105. package/dist/lib/infrastructure/signal/SignalAggregator.js +84 -0
  106. package/dist/lib/infrastructure/signal/SignalBridge.d.ts +13 -0
  107. package/dist/lib/infrastructure/signal/SignalBridge.js +20 -0
  108. package/dist/lib/infrastructure/signal/SignalBus.d.ts +63 -0
  109. package/dist/lib/infrastructure/signal/SignalBus.js +106 -0
  110. package/dist/lib/infrastructure/signal/SignalTraceWriter.d.ts +36 -0
  111. package/dist/lib/infrastructure/signal/SignalTraceWriter.js +130 -0
  112. package/dist/lib/injection/ServiceContainer.js +6 -0
  113. package/dist/lib/injection/ServiceMap.d.ts +16 -19
  114. package/dist/lib/injection/modules/AgentModule.d.ts +1 -1
  115. package/dist/lib/injection/modules/AgentModule.js +7 -1
  116. package/dist/lib/injection/modules/AppModule.d.ts +3 -4
  117. package/dist/lib/injection/modules/AppModule.js +7 -43
  118. package/dist/lib/injection/modules/GuardModule.js +59 -2
  119. package/dist/lib/injection/modules/InfraModule.d.ts +0 -1
  120. package/dist/lib/injection/modules/InfraModule.js +9 -7
  121. package/dist/lib/injection/modules/KnowledgeModule.js +51 -0
  122. package/dist/lib/injection/modules/PanoramaModule.d.ts +18 -0
  123. package/dist/lib/injection/modules/PanoramaModule.js +76 -0
  124. package/dist/lib/injection/modules/SignalModule.d.ts +10 -0
  125. package/dist/lib/injection/modules/SignalModule.js +84 -0
  126. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +1 -0
  127. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +6 -0
  128. package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +3 -1
  129. package/dist/lib/service/bootstrap/BootstrapTaskManager.js +20 -1
  130. package/dist/lib/service/delivery/AgentInstructionsGenerator.js +4 -5
  131. package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +3 -1
  132. package/dist/lib/service/delivery/CursorDeliveryPipeline.js +13 -10
  133. package/dist/lib/service/delivery/RulesGenerator.js +3 -2
  134. package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +114 -0
  135. package/dist/lib/service/evolution/ConsolidationAdvisor.js +542 -0
  136. package/dist/lib/service/evolution/ContradictionDetector.d.ts +54 -0
  137. package/dist/lib/service/evolution/ContradictionDetector.js +253 -0
  138. package/dist/lib/service/evolution/DecayDetector.d.ts +71 -0
  139. package/dist/lib/service/evolution/DecayDetector.js +244 -0
  140. package/dist/lib/service/evolution/EnhancementSuggester.d.ts +38 -0
  141. package/dist/lib/service/evolution/EnhancementSuggester.js +220 -0
  142. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +82 -0
  143. package/dist/lib/service/evolution/KnowledgeMetabolism.js +167 -0
  144. package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +53 -0
  145. package/dist/lib/service/evolution/RedundancyAnalyzer.js +210 -0
  146. package/dist/lib/service/evolution/StagingManager.d.ts +57 -0
  147. package/dist/lib/service/evolution/StagingManager.js +201 -0
  148. package/dist/lib/service/guard/ComplianceReporter.d.ts +42 -2
  149. package/dist/lib/service/guard/ComplianceReporter.js +43 -5
  150. package/dist/lib/service/guard/CoverageAnalyzer.d.ts +54 -0
  151. package/dist/lib/service/guard/CoverageAnalyzer.js +149 -0
  152. package/dist/lib/service/guard/GuardCheckEngine.d.ts +55 -1
  153. package/dist/lib/service/guard/GuardCheckEngine.js +508 -15
  154. package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -0
  155. package/dist/lib/service/guard/GuardFeedbackLoop.js +9 -0
  156. package/dist/lib/service/guard/ReverseGuard.d.ts +73 -0
  157. package/dist/lib/service/guard/ReverseGuard.js +256 -0
  158. package/dist/lib/service/guard/RuleLearner.d.ts +12 -0
  159. package/dist/lib/service/guard/RuleLearner.js +38 -0
  160. package/dist/lib/service/guard/UncertaintyCollector.d.ts +83 -0
  161. package/dist/lib/service/guard/UncertaintyCollector.js +149 -0
  162. package/dist/lib/service/guard/ViolationsStore.d.ts +1 -0
  163. package/dist/lib/service/guard/ViolationsStore.js +33 -3
  164. package/dist/lib/service/knowledge/ConfidenceRouter.d.ts +13 -0
  165. package/dist/lib/service/knowledge/ConfidenceRouter.js +14 -0
  166. package/dist/lib/service/knowledge/KnowledgeService.js +22 -4
  167. package/dist/lib/service/module/ModuleService.js +3 -13
  168. package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +27 -0
  169. package/dist/lib/service/panorama/CouplingAnalyzer.js +192 -0
  170. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +28 -0
  171. package/dist/lib/service/panorama/DimensionAnalyzer.js +320 -0
  172. package/dist/lib/service/panorama/LayerInferrer.d.ts +19 -0
  173. package/dist/lib/service/panorama/LayerInferrer.js +182 -0
  174. package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +24 -0
  175. package/dist/lib/service/panorama/ModuleDiscoverer.js +185 -0
  176. package/dist/lib/service/panorama/PanoramaAggregator.d.ts +29 -0
  177. package/dist/lib/service/panorama/PanoramaAggregator.js +228 -0
  178. package/dist/lib/service/panorama/PanoramaScanner.d.ts +52 -0
  179. package/dist/lib/service/panorama/PanoramaScanner.js +188 -0
  180. package/dist/lib/service/panorama/PanoramaService.d.ts +108 -0
  181. package/dist/lib/service/panorama/PanoramaService.js +220 -0
  182. package/dist/lib/service/panorama/PanoramaTypes.d.ts +134 -0
  183. package/dist/lib/service/panorama/PanoramaTypes.js +6 -0
  184. package/dist/lib/service/panorama/RoleRefiner.d.ts +48 -0
  185. package/dist/lib/service/panorama/RoleRefiner.js +535 -0
  186. package/dist/lib/service/search/MultiSignalRanker.d.ts +1 -0
  187. package/dist/lib/service/search/MultiSignalRanker.js +16 -0
  188. package/dist/lib/service/search/SearchEngine.d.ts +1 -0
  189. package/dist/lib/service/search/SearchEngine.js +9 -1
  190. package/dist/lib/service/search/SearchTypes.d.ts +2 -0
  191. package/dist/lib/service/signal/HitRecorder.d.ts +68 -0
  192. package/dist/lib/service/signal/HitRecorder.js +173 -0
  193. package/dist/lib/service/skills/SignalCollector.d.ts +3 -1
  194. package/dist/lib/service/skills/SignalCollector.js +31 -1
  195. package/dist/lib/service/task/IntentExtractor.d.ts +58 -0
  196. package/dist/lib/service/task/IntentExtractor.js +142 -0
  197. package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
  198. package/dist/lib/service/task/PrimeSearchPipeline.js +98 -0
  199. package/dist/lib/shared/constants.d.ts +0 -15
  200. package/dist/lib/shared/constants.js +0 -10
  201. package/dist/lib/shared/schemas/config.d.ts +4 -1
  202. package/dist/lib/shared/schemas/config.js +8 -1
  203. package/dist/lib/shared/schemas/mcp-tools.d.ts +41 -96
  204. package/dist/lib/shared/schemas/mcp-tools.js +59 -119
  205. package/dist/scripts/analyze-signals.d.ts +20 -0
  206. package/dist/scripts/analyze-signals.js +155 -0
  207. package/dist/scripts/diagnose-mcp.js +1 -1
  208. package/dist/scripts/release.js +2 -10
  209. package/package.json +4 -19
  210. package/skills/autosnippet-devdocs/SKILL.md +11 -8
  211. package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
  212. package/templates/cursor-hooks/hooks/session-start.sh +1 -1
  213. package/templates/instructions/agent-static.md +2 -1
  214. package/templates/instructions/conventions.md +5 -6
  215. package/templates/recipes-setup/README.md +1 -2
  216. package/dashboard/dist/assets/icons-C1dUryS-.js +0 -1
  217. package/dashboard/dist/assets/index-D0whuycy.css +0 -1
  218. package/dashboard/dist/assets/index-DdvZE4Yd.js +0 -128
  219. package/dist/lib/domain/task/Task.d.ts +0 -140
  220. package/dist/lib/domain/task/Task.js +0 -254
  221. package/dist/lib/domain/task/TaskDependency.d.ts +0 -23
  222. package/dist/lib/domain/task/TaskDependency.js +0 -34
  223. package/dist/lib/domain/task/TaskIdGenerator.d.ts +0 -40
  224. package/dist/lib/domain/task/TaskIdGenerator.js +0 -75
  225. package/dist/lib/domain/task/index.d.ts +0 -4
  226. package/dist/lib/domain/task/index.js +0 -4
  227. package/dist/lib/http/routes/snippets.js +0 -49
  228. package/dist/lib/infrastructure/database/migrations/002_add_tasks.d.ts +0 -11
  229. package/dist/lib/infrastructure/database/migrations/002_add_tasks.js +0 -86
  230. package/dist/lib/platform/ClipboardManager.d.ts +0 -24
  231. package/dist/lib/platform/ClipboardManager.js +0 -142
  232. package/dist/lib/platform/NativeUi.d.ts +0 -53
  233. package/dist/lib/platform/NativeUi.js +0 -284
  234. package/dist/lib/platform/ios/index.d.ts +0 -38
  235. package/dist/lib/platform/ios/index.js +0 -42
  236. package/dist/lib/platform/ios/routes/spm.d.ts +0 -9
  237. package/dist/lib/platform/ios/routes/spm.js +0 -371
  238. package/dist/lib/platform/ios/snippet/PlaceholderConverter.d.ts +0 -21
  239. package/dist/lib/platform/ios/snippet/PlaceholderConverter.js +0 -48
  240. package/dist/lib/platform/ios/snippet/XcodeCodec.d.ts +0 -23
  241. package/dist/lib/platform/ios/snippet/XcodeCodec.js +0 -96
  242. package/dist/lib/platform/ios/spm/DependencyGraph.d.ts +0 -56
  243. package/dist/lib/platform/ios/spm/DependencyGraph.js +0 -195
  244. package/dist/lib/platform/ios/spm/PackageSwiftParser.d.ts +0 -69
  245. package/dist/lib/platform/ios/spm/PackageSwiftParser.js +0 -231
  246. package/dist/lib/platform/ios/spm/PathFinder.d.ts +0 -28
  247. package/dist/lib/platform/ios/spm/PathFinder.js +0 -117
  248. package/dist/lib/platform/ios/spm/PolicyEngine.d.ts +0 -44
  249. package/dist/lib/platform/ios/spm/PolicyEngine.js +0 -79
  250. package/dist/lib/platform/ios/spm/SpmHelper.d.ts +0 -102
  251. package/dist/lib/platform/ios/spm/SpmHelper.js +0 -464
  252. package/dist/lib/platform/ios/xcode/HeaderResolver.d.ts +0 -33
  253. package/dist/lib/platform/ios/xcode/HeaderResolver.js +0 -90
  254. package/dist/lib/platform/ios/xcode/SaveEventFilter.d.ts +0 -66
  255. package/dist/lib/platform/ios/xcode/SaveEventFilter.js +0 -142
  256. package/dist/lib/platform/ios/xcode/XcodeAutomation.d.ts +0 -71
  257. package/dist/lib/platform/ios/xcode/XcodeAutomation.js +0 -327
  258. package/dist/lib/platform/ios/xcode/XcodeImportResolver.d.ts +0 -130
  259. package/dist/lib/platform/ios/xcode/XcodeImportResolver.js +0 -404
  260. package/dist/lib/platform/ios/xcode/XcodeIntegration.d.ts +0 -89
  261. package/dist/lib/platform/ios/xcode/XcodeIntegration.js +0 -588
  262. package/dist/lib/platform/ios/xcode/XcodeWriteUtils.d.ts +0 -99
  263. package/dist/lib/platform/ios/xcode/XcodeWriteUtils.js +0 -190
  264. package/dist/lib/repository/task/TaskRepository.impl.d.ts +0 -171
  265. package/dist/lib/repository/task/TaskRepository.impl.js +0 -347
  266. package/dist/lib/service/automation/ActionPipeline.d.ts +0 -34
  267. package/dist/lib/service/automation/ActionPipeline.js +0 -53
  268. package/dist/lib/service/automation/AutomationOrchestrator.d.ts +0 -86
  269. package/dist/lib/service/automation/AutomationOrchestrator.js +0 -57
  270. package/dist/lib/service/automation/ContextCollector.d.ts +0 -24
  271. package/dist/lib/service/automation/ContextCollector.js +0 -35
  272. package/dist/lib/service/automation/DirectiveDetector.d.ts +0 -51
  273. package/dist/lib/service/automation/DirectiveDetector.js +0 -112
  274. package/dist/lib/service/automation/FileWatcher.d.ts +0 -51
  275. package/dist/lib/service/automation/FileWatcher.js +0 -366
  276. package/dist/lib/service/automation/TriggerResolver.d.ts +0 -36
  277. package/dist/lib/service/automation/TriggerResolver.js +0 -62
  278. package/dist/lib/service/automation/handlers/AlinkHandler.d.ts +0 -7
  279. package/dist/lib/service/automation/handlers/AlinkHandler.js +0 -80
  280. package/dist/lib/service/automation/handlers/CreateHandler.d.ts +0 -11
  281. package/dist/lib/service/automation/handlers/CreateHandler.js +0 -170
  282. package/dist/lib/service/automation/handlers/GuardHandler.d.ts +0 -17
  283. package/dist/lib/service/automation/handlers/GuardHandler.js +0 -218
  284. package/dist/lib/service/automation/handlers/HeaderHandler.d.ts +0 -2
  285. package/dist/lib/service/automation/handlers/HeaderHandler.js +0 -32
  286. package/dist/lib/service/automation/handlers/SearchHandler.d.ts +0 -11
  287. package/dist/lib/service/automation/handlers/SearchHandler.js +0 -278
  288. package/dist/lib/service/snippet/SnippetFactory.d.ts +0 -101
  289. package/dist/lib/service/snippet/SnippetFactory.js +0 -145
  290. package/dist/lib/service/snippet/SnippetInstaller.d.ts +0 -91
  291. package/dist/lib/service/snippet/SnippetInstaller.js +0 -276
  292. package/dist/lib/service/snippet/codecs/SnippetCodec.d.ts +0 -44
  293. package/dist/lib/service/snippet/codecs/SnippetCodec.js +0 -35
  294. package/dist/lib/service/snippet/codecs/VSCodeCodec.d.ts +0 -27
  295. package/dist/lib/service/snippet/codecs/VSCodeCodec.js +0 -82
  296. package/dist/lib/service/task/TaskGraphService.d.ts +0 -222
  297. package/dist/lib/service/task/TaskGraphService.js +0 -597
  298. package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +0 -95
  299. package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -298
  300. package/dist/lib/service/task/TaskReadyEngine.d.ts +0 -84
  301. package/dist/lib/service/task/TaskReadyEngine.js +0 -115
  302. package/dist/scripts/build-native-ui.d.ts +0 -3
  303. package/dist/scripts/build-native-ui.js +0 -62
  304. package/dist/scripts/init-snippets.d.ts +0 -30
  305. package/dist/scripts/init-snippets.js +0 -298
  306. package/dist/scripts/install-full.d.ts +0 -7
  307. package/dist/scripts/install-full.js +0 -38
  308. package/resources/native-ui/README.md +0 -29
  309. package/resources/native-ui/combined-window.swift +0 -494
  310. package/resources/native-ui/main.swift +0 -598
  311. package/scripts/postinstall-safe.mjs +0 -89
@@ -10,6 +10,7 @@ import { LanguageService } from '../../shared/LanguageService.js';
10
10
  import { runCodeLevelChecks } from './GuardCodeChecks.js';
11
11
  import { runCrossFileChecks } from './GuardCrossFileChecks.js';
12
12
  import { buildCommentMask, buildTestBlockMask, clearPatternCache, compilePattern, detectLanguage, } from './GuardPatternUtils.js';
13
+ import { UncertaintyCollector } from './UncertaintyCollector.js';
13
14
  /**
14
15
  * 内置默认规则集 — 多语言基础规则
15
16
  *
@@ -75,6 +76,13 @@ const BUILT_IN_RULES = {
75
76
  dimension: 'file',
76
77
  category: 'safety',
77
78
  fixSuggestion: '使用 as? 配合 guard let / if let 进行安全转换',
79
+ // UIKit 框架契约保证安全的 as! 场景
80
+ excludeLinePatterns: [
81
+ 'dequeueReusableCell.*as\\s*!',
82
+ 'dequeueReusableSupplementaryView.*as\\s*!',
83
+ 'dequeueReusableHeaderFooterView.*as\\s*!',
84
+ '\\blayer\\s+as\\s*!',
85
+ ],
78
86
  },
79
87
  'swift-force-try': {
80
88
  message: 'try! 在异常时崩溃,建议 do-catch 或 try?',
@@ -449,6 +457,11 @@ export class GuardCheckEngine {
449
457
  _epInjected;
450
458
  _externalRules;
451
459
  _guardConfig;
460
+ _signalBus;
461
+ /** 上次 guard 信号指纹,用于去重(相同结果不重复发射) */
462
+ _lastGuardSignalKey;
463
+ _lastBlindSpotSignalKey;
464
+ _uncertaintyCollector;
452
465
  db;
453
466
  logger;
454
467
  constructor(db, options = {}) {
@@ -466,6 +479,10 @@ export class GuardCheckEngine {
466
479
  this._epInjected = false;
467
480
  /** Guard 配置 — 允许禁用特定规则或调整 Code-Level 检查阈值 */
468
481
  this._guardConfig = options.guardConfig || {};
482
+ this._signalBus = options.signalBus || null;
483
+ this._lastGuardSignalKey = '';
484
+ this._lastBlindSpotSignalKey = '';
485
+ this._uncertaintyCollector = new UncertaintyCollector();
469
486
  }
470
487
  /**
471
488
  * 注入 Enhancement Pack 外部规则(支持 RegExp 和 string pattern)
@@ -527,10 +544,10 @@ export class GuardCheckEngine {
527
544
  let rows = [];
528
545
  try {
529
546
  rows = this.db
530
- .prepare(`SELECT id, title, description, language, scope, constraints
547
+ .prepare(`SELECT id, title, description, language, scope, constraints, lifecycle
531
548
  FROM knowledge_entries
532
549
  WHERE (kind = 'rule' OR knowledgeType = 'boundary-constraint')
533
- AND lifecycle = 'active'`)
550
+ AND lifecycle IN ('active', 'staging', 'evolving', 'decaying')`)
534
551
  .all();
535
552
  }
536
553
  catch {
@@ -550,12 +567,14 @@ export class GuardCheckEngine {
550
567
  for (const g of guards) {
551
568
  const ruleType = g.type || 'regex';
552
569
  const lang = r.language;
570
+ const isDecaying = r.lifecycle === 'decaying';
571
+ const rawSeverity = (g.severity || 'warning');
553
572
  const base = {
554
573
  id: (g.id || r.id),
555
574
  name: (g.name || r.title),
556
575
  message: (g.message || r.description || r.title),
557
576
  languages: lang ? [lang, LanguageService.toGuardLangId(lang)] : [],
558
- severity: (g.severity || 'warning'),
577
+ severity: isDecaying && rawSeverity === 'error' ? 'warning' : rawSeverity,
559
578
  dimension: (r.scope || 'file'),
560
579
  source: 'database',
561
580
  fixSuggestion: (g.fixSuggestion || null),
@@ -600,6 +619,7 @@ export class GuardCheckEngine {
600
619
  ...(rule.excludePaths ? { excludePaths: rule.excludePaths } : {}),
601
620
  ...(rule.skipComments ? { skipComments: true } : {}),
602
621
  ...(rule.skipTestBlocks ? { skipTestBlocks: true } : {}),
622
+ ...(rule.excludeLinePatterns ? { excludeLinePatterns: rule.excludeLinePatterns } : {}),
603
623
  });
604
624
  }
605
625
  }
@@ -685,10 +705,15 @@ export class GuardCheckEngine {
685
705
  }
686
706
  catch {
687
707
  this.logger.debug(`Invalid regex in rule ${rule.id}: ${rule.pattern}`);
708
+ this._uncertaintyCollector.recordSkip('regex', 'invalid_regex', `Rule ${rule.id}: pattern "${rule.pattern}" failed to compile`, { ruleId: rule.id || rule.name });
709
+ this._uncertaintyCollector.addUncertain(rule.id || rule.name, rule.message, 'regex', 'invalid_regex', `Pattern compilation failed: ${rule.pattern}`);
688
710
  continue;
689
711
  }
690
712
  const shouldSkipComments = !!rule.skipComments;
691
713
  const shouldSkipTestBlocks = !!rule.skipTestBlocks;
714
+ // 合并内置 + 配置级排除行模式
715
+ const ruleId = rule.id || rule.name;
716
+ const excludeLineRegexes = this._getExcludeLineRegexes(ruleId, rule.excludeLinePatterns);
692
717
  for (let i = 0; i < lines.length; i++) {
693
718
  // skipComments: 跳过注释行(doc comments / 行注释 / 块注释内)
694
719
  if (shouldSkipComments && commentLines[i]) {
@@ -699,6 +724,10 @@ export class GuardCheckEngine {
699
724
  continue;
700
725
  }
701
726
  if (re.test(lines[i])) {
727
+ // excludeLinePatterns: 跳过匹配排除模式的行(UIKit 框架契约安全等场景)
728
+ if (excludeLineRegexes.length > 0 && excludeLineRegexes.some((ep) => ep.test(lines[i]))) {
729
+ continue;
730
+ }
702
731
  violations.push({
703
732
  ruleId: rule.id || rule.name,
704
733
  message: rule.message,
@@ -711,13 +740,21 @@ export class GuardCheckEngine {
711
740
  }
712
741
  }
713
742
  }
714
- // Code-level 检查(不依赖正则)
743
+ // Code-level 检查(不依赖正则)— 仅传递数字类型阈值
744
+ const numericThresholds = {};
745
+ for (const [k, v] of Object.entries(this._guardConfig.codeLevelThresholds || {})) {
746
+ if (typeof v === 'number') {
747
+ numericThresholds[k] = v;
748
+ }
749
+ }
715
750
  violations.push(...runCodeLevelChecks(code, language, lines, {
716
751
  disabledRules: this._guardConfig.disabledRules,
717
- codeLevelThresholds: this._guardConfig.codeLevelThresholds,
752
+ codeLevelThresholds: numericThresholds,
718
753
  }));
719
- // AST 语义规则检查
754
+ // AST 语义规则检查(Layer 1: 3 查询函数)
720
755
  violations.push(...this._runAstRuleChecks(code, language));
756
+ // AST Layer 2: analyzeFile() 深层检查(复杂度、类膨胀、深嵌套)
757
+ violations.push(...this._runAstLayer2Checks(code, language, filePath));
721
758
  // 跟踪 Guard 命中次数(回写 Recipe 统计)
722
759
  this.trackGuardHits(violations);
723
760
  // ── Reasoning Enrichment: 推理信息跟随数据流动 ──
@@ -760,11 +797,24 @@ export class GuardCheckEngine {
760
797
  // AstAnalyzer 作为 ESM 模块,在 constructor 时已被引入
761
798
  AstAnalyzer = this._getAstAnalyzer();
762
799
  if (!AstAnalyzer || !AstAnalyzer.isAvailable()) {
800
+ // AST 不可用 — 记录 uncertain
801
+ for (const rule of astRules) {
802
+ this._uncertaintyCollector.recordSkip('ast', 'ast_unavailable', `AST check skipped: tree-sitter not available for lang "${language}"`, { ruleId: rule.id });
803
+ this._uncertaintyCollector.addUncertain(rule.id, rule.message, 'ast', 'ast_unavailable', `Tree-sitter not available for language "${language}"`);
804
+ }
805
+ this._uncertaintyCollector.recordLayerStats('ast', astRules.length, 0);
763
806
  return [];
764
807
  }
765
808
  }
766
809
  catch {
767
810
  this.logger.debug('AstAnalyzer not available, skipping AST rules');
811
+ for (const rule of astRules) {
812
+ this._uncertaintyCollector.recordSkip('ast', 'ast_unavailable', `AST module load failed`, {
813
+ ruleId: rule.id,
814
+ });
815
+ this._uncertaintyCollector.addUncertain(rule.id, rule.message, 'ast', 'ast_unavailable', 'AstAnalyzer module failed to load');
816
+ }
817
+ this._uncertaintyCollector.recordLayerStats('ast', astRules.length, 0);
768
818
  return [];
769
819
  }
770
820
  const violations = [];
@@ -847,12 +897,399 @@ export class GuardCheckEngine {
847
897
  this.logger.debug(`AST rule ${rule.id} check failed: ${err.message}`);
848
898
  }
849
899
  }
900
+ // AST 层统计
901
+ this._uncertaintyCollector.recordLayerStats('ast', astRules.length, astRules.length);
902
+ return violations;
903
+ }
904
+ /**
905
+ * AST Layer 2: analyzeFile() 深层检查
906
+ *
907
+ * 利用 AstAnalyzer.analyzeFile() 的完整输出产出 violations:
908
+ *
909
+ * --- 方法度量 ---
910
+ * - ast_class_bloat: 类方法数过多 (>20)
911
+ * - ast_method_complexity: 高圈复杂度 (>15)
912
+ * - ast_method_too_long: 方法行数过长 (>80)
913
+ * - ast_deep_nesting: 方法嵌套过深 (>5)
914
+ *
915
+ * --- 继承图检查 ---
916
+ * - ast_deep_inheritance: 继承链过深 (>4)
917
+ * - ast_wide_protocol_conformance: 单类遵守协议过多 (>5)
918
+ * - ast_missing_super: 子类未调用 super 的关键方法
919
+ *
920
+ * --- 属性规范 ---
921
+ * - ast_assign_object_property: ObjC assign 修饰对象类型属性
922
+ * - ast_missing_nonatomic: ObjC 属性缺少 nonatomic
923
+ * - ast_mutable_public_collection: 公开可变集合属性
924
+ *
925
+ * --- 设计模式/反模式检测 ---
926
+ * - ast_god_class: 方法+属性过多的上帝类 (>30 methods + >15 properties)
927
+ * - ast_singleton_abuse: 过多单例模式
928
+ * - ast_missing_weakify: block 内 self 捕获但未使用 weakify
929
+ */
930
+ _runAstLayer2Checks(code, language, filePath) {
931
+ const disabled = this._guardConfig.disabledRules || [];
932
+ const allLayer2Rules = [
933
+ 'ast_class_bloat',
934
+ 'ast_method_complexity',
935
+ 'ast_method_too_long',
936
+ 'ast_deep_nesting',
937
+ 'ast_deep_inheritance',
938
+ 'ast_wide_protocol_conformance',
939
+ 'ast_missing_super',
940
+ 'ast_assign_object_property',
941
+ 'ast_missing_nonatomic',
942
+ 'ast_mutable_public_collection',
943
+ 'ast_god_class',
944
+ 'ast_singleton_abuse',
945
+ 'ast_missing_weakify',
946
+ ];
947
+ const allDisabled = allLayer2Rules.every((id) => disabled.includes(id));
948
+ if (allDisabled) {
949
+ return [];
950
+ }
951
+ // 语言标准化
952
+ const astLang = LanguageService.isKnownLang(language)
953
+ ? language
954
+ : language === 'objc'
955
+ ? 'objectivec'
956
+ : language;
957
+ if (!LanguageService.isKnownLang(astLang)) {
958
+ return [];
959
+ }
960
+ let AstAnalyzer;
961
+ try {
962
+ AstAnalyzer = this._getAstAnalyzer();
963
+ if (!AstAnalyzer || !AstAnalyzer.isAvailable()) {
964
+ this._uncertaintyCollector.recordSkip('ast', 'ast_unavailable', `AST Layer 2 skipped: tree-sitter not available for "${language}"`);
965
+ return [];
966
+ }
967
+ }
968
+ catch {
969
+ return [];
970
+ }
971
+ let fileSummary;
972
+ try {
973
+ fileSummary = AstAnalyzer.analyzeFile(code, astLang, { extractCallSites: false });
974
+ }
975
+ catch (err) {
976
+ this.logger.debug(`AST Layer 2 analyzeFile failed: ${err.message}`);
977
+ return [];
978
+ }
979
+ if (!fileSummary) {
980
+ return [];
981
+ }
982
+ const violations = [];
983
+ // — 阈值配置(可通过 codeLevelThresholds 覆盖) —
984
+ const thresholds = this._guardConfig.codeLevelThresholds || {};
985
+ const classBloatLimit = (typeof thresholds['ast_class_bloat'] === 'number' ? thresholds['ast_class_bloat'] : 20);
986
+ const complexityLimit = (typeof thresholds['ast_method_complexity'] === 'number'
987
+ ? thresholds['ast_method_complexity']
988
+ : 15);
989
+ const methodLengthLimit = (typeof thresholds['ast_method_too_long'] === 'number' ? thresholds['ast_method_too_long'] : 80);
990
+ const nestingLimit = (typeof thresholds['ast_deep_nesting'] === 'number' ? thresholds['ast_deep_nesting'] : 5);
991
+ const inheritanceDepthLimit = (typeof thresholds['ast_deep_inheritance'] === 'number'
992
+ ? thresholds['ast_deep_inheritance']
993
+ : 4);
994
+ const protocolConformanceLimit = (typeof thresholds['ast_wide_protocol_conformance'] === 'number'
995
+ ? thresholds['ast_wide_protocol_conformance']
996
+ : 5);
997
+ const godClassMethodLimit = (typeof thresholds['ast_god_class_methods'] === 'number'
998
+ ? thresholds['ast_god_class_methods']
999
+ : 30);
1000
+ const godClassPropertyLimit = (typeof thresholds['ast_god_class_properties'] === 'number'
1001
+ ? thresholds['ast_god_class_properties']
1002
+ : 15);
1003
+ // ══════════════════════════════════════════════════════════
1004
+ // Section A: 方法度量(原有 4 条规则)
1005
+ // ══════════════════════════════════════════════════════════
1006
+ // 1. Class bloat — 类方法数过多
1007
+ if (!disabled.includes('ast_class_bloat')) {
1008
+ const methodCountByClass = {};
1009
+ for (const m of fileSummary.methods) {
1010
+ if (m.className && m.kind === 'definition') {
1011
+ if (!methodCountByClass[m.className]) {
1012
+ const cls = fileSummary.classes.find((c) => c.name === m.className);
1013
+ methodCountByClass[m.className] = { count: 0, line: cls?.line || 1 };
1014
+ }
1015
+ methodCountByClass[m.className].count++;
1016
+ }
1017
+ }
1018
+ for (const [className, { count, line }] of Object.entries(methodCountByClass)) {
1019
+ if (count > classBloatLimit) {
1020
+ violations.push({
1021
+ ruleId: 'ast_class_bloat',
1022
+ message: `类 ${className} 有 ${count} 个方法,超过阈值 ${classBloatLimit},建议拆分职责`,
1023
+ severity: 'warning',
1024
+ line,
1025
+ snippet: `class ${className} — ${count} methods`,
1026
+ dimension: 'file',
1027
+ fixSuggestion: '将职责拆分到多个类或使用 Extension/Category 分组',
1028
+ });
1029
+ }
1030
+ }
1031
+ }
1032
+ // 2. Method complexity — 高圈复杂度
1033
+ if (!disabled.includes('ast_method_complexity')) {
1034
+ for (const m of fileSummary.methods) {
1035
+ if (m.complexity && m.complexity > complexityLimit) {
1036
+ violations.push({
1037
+ ruleId: 'ast_method_complexity',
1038
+ message: `方法 ${m.className ? `${m.className}.` : ''}${m.name} 圈复杂度 ${m.complexity},超过阈值 ${complexityLimit}`,
1039
+ severity: 'warning',
1040
+ line: m.line || 1,
1041
+ snippet: `${m.name} — complexity: ${m.complexity}`,
1042
+ dimension: 'file',
1043
+ fixSuggestion: '提取子方法、使用 early return 或策略模式降低复杂度',
1044
+ });
1045
+ }
1046
+ }
1047
+ }
1048
+ // 3. Method too long — 方法行数过长
1049
+ if (!disabled.includes('ast_method_too_long')) {
1050
+ for (const m of fileSummary.methods) {
1051
+ if (m.bodyLines && m.bodyLines > methodLengthLimit) {
1052
+ violations.push({
1053
+ ruleId: 'ast_method_too_long',
1054
+ message: `方法 ${m.className ? `${m.className}.` : ''}${m.name} 有 ${m.bodyLines} 行,超过阈值 ${methodLengthLimit}`,
1055
+ severity: 'warning',
1056
+ line: m.line || 1,
1057
+ snippet: `${m.name} — ${m.bodyLines} lines`,
1058
+ dimension: 'file',
1059
+ fixSuggestion: '将长方法拆分为多个更小的、职责单一的方法',
1060
+ });
1061
+ }
1062
+ }
1063
+ }
1064
+ // 4. Deep nesting — 方法嵌套过深
1065
+ if (!disabled.includes('ast_deep_nesting')) {
1066
+ for (const m of fileSummary.methods) {
1067
+ if (m.nestingDepth && m.nestingDepth > nestingLimit) {
1068
+ violations.push({
1069
+ ruleId: 'ast_deep_nesting',
1070
+ message: `方法 ${m.className ? `${m.className}.` : ''}${m.name} 嵌套深度 ${m.nestingDepth},超过阈值 ${nestingLimit}`,
1071
+ severity: 'warning',
1072
+ line: m.line || 1,
1073
+ snippet: `${m.name} — nesting depth: ${m.nestingDepth}`,
1074
+ dimension: 'file',
1075
+ fixSuggestion: '使用 guard/early return 减少嵌套,或提取内层逻辑为独立方法',
1076
+ });
1077
+ }
1078
+ }
1079
+ }
1080
+ // ══════════════════════════════════════════════════════════
1081
+ // Section B: 继承图检查(inheritanceGraph + classes.protocols)
1082
+ // ══════════════════════════════════════════════════════════
1083
+ // 5. Deep inheritance — 继承链过深
1084
+ if (!disabled.includes('ast_deep_inheritance') && fileSummary.inheritanceGraph?.length > 0) {
1085
+ // 构建父类映射: child → parent
1086
+ const parentMap = {};
1087
+ for (const edge of fileSummary.inheritanceGraph) {
1088
+ if (edge.type === 'extends' || edge.type === 'inherits') {
1089
+ parentMap[edge.from] = edge.to;
1090
+ }
1091
+ }
1092
+ // 计算每个类的继承深度
1093
+ for (const cls of fileSummary.classes) {
1094
+ let depth = 0;
1095
+ let current = cls.name;
1096
+ const visited = new Set();
1097
+ while (parentMap[current] && !visited.has(current)) {
1098
+ visited.add(current);
1099
+ current = parentMap[current];
1100
+ depth++;
1101
+ }
1102
+ if (depth > inheritanceDepthLimit) {
1103
+ violations.push({
1104
+ ruleId: 'ast_deep_inheritance',
1105
+ message: `类 ${cls.name} 继承链深度 ${depth},超过阈值 ${inheritanceDepthLimit},过深继承增加理解和维护成本`,
1106
+ severity: 'warning',
1107
+ line: cls.line || 1,
1108
+ snippet: `class ${cls.name} — inheritance depth: ${depth}`,
1109
+ dimension: 'file',
1110
+ fixSuggestion: '优先使用组合(Composition)替代继承,或使用协议/接口解耦',
1111
+ });
1112
+ }
1113
+ }
1114
+ }
1115
+ // 6. Wide protocol conformance — 单类遵守协议过多
1116
+ if (!disabled.includes('ast_wide_protocol_conformance')) {
1117
+ for (const cls of fileSummary.classes) {
1118
+ const protocolCount = cls.protocols?.length || 0;
1119
+ if (protocolCount > protocolConformanceLimit) {
1120
+ violations.push({
1121
+ ruleId: 'ast_wide_protocol_conformance',
1122
+ message: `类 ${cls.name} 遵守 ${protocolCount} 个协议,超过阈值 ${protocolConformanceLimit},职责可能过重`,
1123
+ severity: 'warning',
1124
+ line: cls.line || 1,
1125
+ snippet: `class ${cls.name} — ${protocolCount} protocols: ${cls.protocols.slice(0, 5).join(', ')}${protocolCount > 5 ? '...' : ''}`,
1126
+ dimension: 'file',
1127
+ fixSuggestion: '将协议实现拆分到 Extension/Category 中,或拆分类职责',
1128
+ });
1129
+ }
1130
+ }
1131
+ }
1132
+ // ══════════════════════════════════════════════════════════
1133
+ // Section C: 属性规范(properties + attributes)
1134
+ // ══════════════════════════════════════════════════════════
1135
+ const isObjcLike = ['objc', 'objectivec', 'objective-c'].includes(language.toLowerCase());
1136
+ if (isObjcLike && fileSummary.properties?.length > 0) {
1137
+ for (const prop of fileSummary.properties) {
1138
+ const attrs = prop.attributes || [];
1139
+ const attrsLower = attrs.map((a) => a.toLowerCase());
1140
+ // 7. assign 修饰对象类型属性
1141
+ if (!disabled.includes('ast_assign_object_property')) {
1142
+ if (attrsLower.includes('assign') && !attrsLower.includes('readonly')) {
1143
+ // assign 用于对象类型(通过属性名启发:delegate, block, handler 等常为对象)
1144
+ const likelyObject = /delegate|block|handler|callback|completion|dataSource|view|controller|manager|service/i.test(prop.name);
1145
+ if (likelyObject) {
1146
+ violations.push({
1147
+ ruleId: 'ast_assign_object_property',
1148
+ message: `属性 ${prop.className ? `${prop.className}.` : ''}${prop.name} 使用 assign 修饰,疑似对象类型,应改为 weak`,
1149
+ severity: 'warning',
1150
+ line: prop.line || 1,
1151
+ snippet: `@property (assign) ... ${prop.name}`,
1152
+ dimension: 'file',
1153
+ fixSuggestion: '对象类型属性使用 weak(delegate)或 strong/copy,避免悬垂指针',
1154
+ });
1155
+ }
1156
+ }
1157
+ }
1158
+ // 8. 缺少 nonatomic
1159
+ if (!disabled.includes('ast_missing_nonatomic')) {
1160
+ if (!attrsLower.includes('nonatomic') &&
1161
+ !attrsLower.includes('atomic') &&
1162
+ attrs.length > 0) {
1163
+ violations.push({
1164
+ ruleId: 'ast_missing_nonatomic',
1165
+ message: `属性 ${prop.className ? `${prop.className}.` : ''}${prop.name} 缺少 nonatomic,iOS 中应默认使用 nonatomic 提升性能`,
1166
+ severity: 'info',
1167
+ line: prop.line || 1,
1168
+ snippet: `@property (${attrs.join(', ')}) ... ${prop.name}`,
1169
+ dimension: 'file',
1170
+ fixSuggestion: '添加 nonatomic 修饰符:@property (nonatomic, ...) ...',
1171
+ });
1172
+ }
1173
+ }
1174
+ // 9. 公开可变集合属性
1175
+ if (!disabled.includes('ast_mutable_public_collection')) {
1176
+ const isMutable = /NSMutableArray|NSMutableDictionary|NSMutableSet|NSMutableString|NSMutableData|NSMutableOrderedSet/i.test(`${attrs.join(' ')} ${prop.name}`);
1177
+ if (isMutable && !attrsLower.includes('readonly')) {
1178
+ violations.push({
1179
+ ruleId: 'ast_mutable_public_collection',
1180
+ message: `属性 ${prop.className ? `${prop.className}.` : ''}${prop.name} 暴露可变集合,外部可直接修改内部状态`,
1181
+ severity: 'warning',
1182
+ line: prop.line || 1,
1183
+ snippet: `@property ... NSMutable* ${prop.name}`,
1184
+ dimension: 'file',
1185
+ fixSuggestion: '对外使用 readonly + 不可变类型(NSArray/NSDictionary),内部用 readwrite + 可变类型',
1186
+ });
1187
+ }
1188
+ }
1189
+ }
1190
+ }
1191
+ // ══════════════════════════════════════════════════════════
1192
+ // Section D: 设计模式 / 反模式检测(patterns + aggregated metrics)
1193
+ // ══════════════════════════════════════════════════════════
1194
+ // 10. God class — 方法+属性过多的上帝类
1195
+ if (!disabled.includes('ast_god_class')) {
1196
+ // 按类聚合方法数和属性数
1197
+ const classStats = {};
1198
+ for (const m of fileSummary.methods) {
1199
+ if (m.className && m.kind === 'definition') {
1200
+ if (!classStats[m.className]) {
1201
+ const cls = fileSummary.classes.find((c) => c.name === m.className);
1202
+ classStats[m.className] = { methods: 0, properties: 0, line: cls?.line || 1 };
1203
+ }
1204
+ classStats[m.className].methods++;
1205
+ }
1206
+ }
1207
+ for (const p of fileSummary.properties) {
1208
+ if (p.className) {
1209
+ if (!classStats[p.className]) {
1210
+ const cls = fileSummary.classes.find((c) => c.name === p.className);
1211
+ classStats[p.className] = { methods: 0, properties: 0, line: cls?.line || 1 };
1212
+ }
1213
+ classStats[p.className].properties++;
1214
+ }
1215
+ }
1216
+ for (const [className, stats] of Object.entries(classStats)) {
1217
+ if (stats.methods > godClassMethodLimit && stats.properties > godClassPropertyLimit) {
1218
+ violations.push({
1219
+ ruleId: 'ast_god_class',
1220
+ message: `类 ${className} 有 ${stats.methods} 个方法和 ${stats.properties} 个属性,疑似上帝类(God Class),职责过重`,
1221
+ severity: 'warning',
1222
+ line: stats.line,
1223
+ snippet: `class ${className} — ${stats.methods} methods, ${stats.properties} properties`,
1224
+ dimension: 'file',
1225
+ fixSuggestion: '遵循单一职责原则(SRP),将类拆分为多个更小的、职责明确的类',
1226
+ });
1227
+ }
1228
+ }
1229
+ }
1230
+ // 11. Singleton abuse — 过多单例模式(文件级别)
1231
+ if (!disabled.includes('ast_singleton_abuse') && fileSummary.patterns?.length > 0) {
1232
+ const singletonPatterns = fileSummary.patterns.filter((p) => p.type === 'singleton');
1233
+ if (singletonPatterns.length > 2) {
1234
+ violations.push({
1235
+ ruleId: 'ast_singleton_abuse',
1236
+ message: `文件中检测到 ${singletonPatterns.length} 个单例模式,过多单例增加耦合和测试难度`,
1237
+ severity: 'info',
1238
+ line: singletonPatterns[0]?.line || 1,
1239
+ snippet: `${singletonPatterns.length} singletons: ${singletonPatterns
1240
+ .map((p) => p.className || p.methodName || 'unknown')
1241
+ .slice(0, 3)
1242
+ .join(', ')}`,
1243
+ dimension: 'file',
1244
+ fixSuggestion: '考虑使用依赖注入(DI)替代单例,提升可测试性和解耦',
1245
+ });
1246
+ }
1247
+ }
1248
+ // 12. Missing weakify — block 内 self 捕获但未使用 weakify 模式
1249
+ if (!disabled.includes('ast_missing_weakify') &&
1250
+ isObjcLike &&
1251
+ fileSummary.patterns?.length > 0) {
1252
+ const selfCaptures = fileSummary.patterns.filter((p) => p.type === 'block_self_capture' && !p.isWeakRef);
1253
+ for (const cap of selfCaptures) {
1254
+ violations.push({
1255
+ ruleId: 'ast_missing_weakify',
1256
+ message: `${cap.className ? `${cap.className}.` : ''}${cap.methodName || 'block'} 中 block 捕获 self 但未使用 @weakify/@strongify`,
1257
+ severity: 'warning',
1258
+ line: cap.line || 1,
1259
+ snippet: `block captures self without weakify in ${cap.methodName || 'anonymous block'}`,
1260
+ dimension: 'file',
1261
+ fixSuggestion: '使用 @weakify(self) / @strongify(self) 或 __weak typeof(self) weakSelf = self',
1262
+ });
1263
+ }
1264
+ }
850
1265
  return violations;
851
1266
  }
852
1267
  /** 获取 AstAnalyzer 模块(静态 import,带可用性检测) */
853
1268
  _getAstAnalyzer() {
854
1269
  return AstAnalyzerModule;
855
1270
  }
1271
+ /**
1272
+ * 合并内置 + 配置级行排除模式,编译为 RegExp 数组
1273
+ * 配置来自 guardConfig.codeLevelThresholds[ruleId].exclude
1274
+ */
1275
+ _getExcludeLineRegexes(ruleId, builtIn) {
1276
+ const patterns = [...(builtIn || [])];
1277
+ // 合并项目配置中的 exclude
1278
+ const override = this._guardConfig.codeLevelThresholds?.[ruleId];
1279
+ if (override && typeof override === 'object' && Array.isArray(override.exclude)) {
1280
+ patterns.push(...override.exclude);
1281
+ }
1282
+ const regexes = [];
1283
+ for (const p of patterns) {
1284
+ try {
1285
+ regexes.push(new RegExp(p));
1286
+ }
1287
+ catch {
1288
+ this.logger.debug(`Invalid excludeLinePattern in rule ${ruleId}: ${p}`);
1289
+ }
1290
+ }
1291
+ return regexes;
1292
+ }
856
1293
  /**
857
1294
  * 将 Guard 命中计数回写到对应 Recipe 的 guard_hit_count
858
1295
  * @param violations
@@ -901,15 +1338,20 @@ export class GuardCheckEngine {
901
1338
  */
902
1339
  auditFile(filePath, code, options = {}) {
903
1340
  const language = detectLanguage(filePath);
1341
+ // 每次文件审计前重置 collector(单文件粒度)
1342
+ this._uncertaintyCollector.reset();
904
1343
  const violations = this.checkCode(code, language, { ...options, filePath });
1344
+ const report = this._uncertaintyCollector.buildReport();
905
1345
  return {
906
1346
  filePath,
907
1347
  language,
908
1348
  violations,
1349
+ uncertainResults: report.uncertainResults,
909
1350
  summary: {
910
1351
  total: violations.length,
911
1352
  errors: violations.filter((v) => v.severity === 'error').length,
912
1353
  warnings: violations.filter((v) => v.severity === 'warning').length,
1354
+ uncertain: report.uncertainResults.length,
913
1355
  },
914
1356
  };
915
1357
  }
@@ -935,16 +1377,67 @@ export class GuardCheckEngine {
935
1377
  });
936
1378
  totalViolations += crossFileViolations.length;
937
1379
  totalErrors += crossFileViolations.filter((v) => v.severity === 'error').length;
938
- return {
939
- files: results,
940
- crossFileViolations,
941
- summary: {
942
- filesChecked: results.length,
943
- totalViolations,
944
- totalErrors,
945
- filesWithViolations: results.filter((r) => r.summary.total > 0).length,
946
- },
1380
+ const summary = {
1381
+ filesChecked: results.length,
1382
+ totalViolations,
1383
+ totalErrors,
1384
+ totalUncertain: results.reduce((s, r) => s + r.summary.uncertain, 0),
1385
+ filesWithViolations: results.filter((r) => r.summary.total > 0).length,
947
1386
  };
1387
+ // ── Signal emission (去重:相同检查结果不重复发射) ──
1388
+ if (this._signalBus && totalViolations > 0) {
1389
+ const signalKey = `${summary.filesChecked}:${summary.totalViolations}:${summary.totalErrors}:${summary.totalUncertain}:${summary.filesWithViolations}`;
1390
+ if (signalKey !== this._lastGuardSignalKey) {
1391
+ this._lastGuardSignalKey = signalKey;
1392
+ this._signalBus.send('guard', 'GuardCheckEngine', totalErrors > 0 ? 1 : 0.5, {
1393
+ metadata: { ...summary },
1394
+ });
1395
+ }
1396
+ }
1397
+ // ── 聚合 capability report ──
1398
+ const aggregateCollector = new UncertaintyCollector();
1399
+ for (const r of results) {
1400
+ for (const u of r.uncertainResults) {
1401
+ aggregateCollector.addUncertain(u.ruleId, u.message, u.layer, u.reason, u.detail);
1402
+ }
1403
+ }
1404
+ const capabilityReport = aggregateCollector.buildReport();
1405
+ // ── guard_blind_spot: uncertain 超阈值时发射 CapabilityRequest 信号(去重) ──
1406
+ if (this._signalBus && capabilityReport.uncertainResults.length > 0) {
1407
+ const uncertainTotal = capabilityReport.uncertainResults.length;
1408
+ const blindSpotThreshold = 5; // 触发阈值
1409
+ if (uncertainTotal >= blindSpotThreshold) {
1410
+ const blindSpotKey = `${uncertainTotal}:${capabilityReport.checkCoverage}`;
1411
+ if (blindSpotKey !== this._lastBlindSpotSignalKey) {
1412
+ this._lastBlindSpotSignalKey = blindSpotKey;
1413
+ // 按 layer 聚合盲区
1414
+ const byLayer = {};
1415
+ for (const u of capabilityReport.uncertainResults) {
1416
+ byLayer[u.layer] = (byLayer[u.layer] || 0) + 1;
1417
+ }
1418
+ this._signalBus.send('guard_blind_spot', 'GuardCheckEngine', uncertainTotal >= 20 ? 1 : 0.5, {
1419
+ metadata: {
1420
+ type: 'CapabilityRequest',
1421
+ uncertainTotal,
1422
+ checkCoverage: capabilityReport.checkCoverage,
1423
+ byLayer,
1424
+ boundaries: capabilityReport.boundaries.map((b) => ({
1425
+ type: b.type,
1426
+ description: b.description,
1427
+ affectedRules: b.affectedRules,
1428
+ suggestedAction: b.suggestedAction,
1429
+ })),
1430
+ suggestedAction: 'Extend Guard capability: add AST support for uncovered languages or implement missing cross-file checks',
1431
+ },
1432
+ });
1433
+ }
1434
+ }
1435
+ }
1436
+ return { files: results, crossFileViolations, summary, capabilityReport };
1437
+ }
1438
+ /** 获取 uncertainty collector(供外部读取单文件 uncertain 状态) */
1439
+ getUncertaintyCollector() {
1440
+ return this._uncertaintyCollector;
948
1441
  }
949
1442
  /** 清除规则缓存 */
950
1443
  clearCache() {
@@ -7,6 +7,7 @@
7
7
  * 3. 集成到 guardAuditFiles MCP handler 和 GuardHandler (FileWatcher)
8
8
  */
9
9
  import Logger from '../../infrastructure/logging/Logger.js';
10
+ import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
10
11
  interface ViolationsStoreLike {
11
12
  getRunsByFile(filePath: string): {
12
13
  violations: {
@@ -40,9 +41,11 @@ export declare class GuardFeedbackLoop {
40
41
  guardCheckEngine: GuardCheckEngineLike | null;
41
42
  logger: ReturnType<typeof Logger.getInstance>;
42
43
  violationsStore: ViolationsStoreLike | null;
44
+ _signalBus: SignalBus | null;
43
45
  /** @param [options.guardCheckEngine] 用于查找规则 */
44
46
  constructor(violationsStore: ViolationsStoreLike | null, feedbackCollector: FeedbackCollectorLike | null, options?: {
45
47
  guardCheckEngine?: GuardCheckEngineLike;
48
+ signalBus?: SignalBus;
46
49
  });
47
50
  /**
48
51
  * 对比当前和历史 violations,检测已修复的违规