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
@@ -1,151 +1,179 @@
1
1
  /**
2
- * MCP Handler — autosnippet_task (Unified Task & Decision Management)
2
+ * MCP Handler — autosnippet_task (Intent Lifecycle + Signal Collection)
3
3
  *
4
- * Operations:
5
- * Session: prime (session entry loads decisions + ready tasks + stats)
6
- * Tasks: create / ready / claim / close / fail / defer / progress
7
- * show / list / stats / blocked / decompose / dep_add / dep_tree
8
- * Decisions: record_decision / revise_decision / unpin_decision / list_decisions
4
+ * 5 Operations:
5
+ * prime Load knowledge context + initialize intent
6
+ * create Create in-memory task anchor (generates ID)
7
+ * close — Complete task + persist intent chain + trigger Guard
8
+ * fail — Abandon task + persist intent chain
9
+ * record_decision — Record user preference signal
10
+ *
11
+ * Architecture: Zero DB. Pure memory (IntentState) + SignalBus → JSONL signals.
9
12
  */
13
+ import { notifyTaskProgress } from '#infra/notification/LarkNotifier.js';
14
+ import { extract as extractIntent } from '#service/task/IntentExtractor.js';
10
15
  import { envelope } from '../envelope.js';
16
+ import { createIdleIntent } from './types.js';
17
+ // ─── In-memory task ID counter ───────────────────────────
18
+ let _taskCounter = 0;
19
+ function _generateTaskId() {
20
+ _taskCounter++;
21
+ return `asd-${Date.now().toString(36)}-${_taskCounter}`;
22
+ }
23
+ // ─── Task Rules Reminder ─────────────────────────────────
24
+ const _taskRules = {
25
+ reminder: [
26
+ '📋 TASK RULES (MANDATORY):',
27
+ '🔑 YOU are the task operator — user speaks naturally, you translate to task operations.',
28
+ '• MUST prime on EVERY message BEFORE anything else',
29
+ '• MUST create task for non-trivial work (≥2 files OR ≥10 lines)',
30
+ '• MUST close when done with meaningful reason',
31
+ '• When user agrees/disagrees → record_decision immediately',
32
+ '• NEVER tell user to run task commands',
33
+ ].join('\n'),
34
+ translationHint: [
35
+ 'User Says → You Run:',
36
+ '"fix bug"/"implement" → create→code→close',
37
+ '"continue" → resume in-progress→close',
38
+ '"pause"/"abandon" → fail(id, reason)',
39
+ '"agreed"/"disagree" → record_decision',
40
+ 'Quick question → No task. Just answer.',
41
+ ].join('\n'),
42
+ };
11
43
  /**
12
- * 统一入口
13
- * @param ctx { container }
14
- * @param args { operation, ...params }
44
+ * Unified entry point
15
45
  */
16
46
  export async function taskHandler(ctx, args) {
17
- const taskService = ctx.container.get('taskGraphService');
18
47
  let result;
19
48
  switch (args.operation) {
20
- // ── Session ──
21
49
  case 'prime':
22
- return _prime(taskService, args);
23
- // ── Task CRUD ──
50
+ return _prime(ctx, args);
24
51
  case 'create':
25
- result = await _create(taskService, args);
26
- break;
27
- case 'ready':
28
- return _ready(taskService, args);
29
- case 'claim':
30
- result = await _claim(taskService, args);
52
+ result = await _create(ctx, args);
31
53
  break;
32
54
  case 'close':
33
- result = await _close(ctx, taskService, args);
55
+ result = await _close(ctx, args);
34
56
  break;
35
57
  case 'fail':
36
- result = await _fail(taskService, args);
37
- break;
38
- case 'defer':
39
- result = await _defer(taskService, args);
58
+ result = await _fail(ctx, args);
40
59
  break;
41
- case 'progress':
42
- result = await _progress(taskService, args);
43
- break;
44
- case 'decompose':
45
- result = await _decompose(taskService, args);
46
- break;
47
- case 'show':
48
- return _show(taskService, args);
49
- case 'list':
50
- return _list(taskService, args);
51
- case 'blocked':
52
- return _blocked(taskService);
53
- case 'dep_add':
54
- return _depAdd(taskService, args);
55
- case 'dep_tree':
56
- return _depTree(taskService, args);
57
- case 'stats':
58
- return _stats(taskService);
59
- // ── Decisions ──
60
60
  case 'record_decision':
61
- result = await _recordDecision(taskService, args);
62
- break;
63
- case 'revise_decision':
64
- result = await _reviseDecision(taskService, args);
65
- break;
66
- case 'unpin_decision':
67
- result = await _unpinDecision(taskService, args);
61
+ result = await _recordDecision(ctx, args);
68
62
  break;
69
- case 'list_decisions':
70
- return _listDecisions(taskService);
71
63
  default:
72
64
  return envelope({
73
65
  success: false,
74
- message: `Unknown operation: ${args.operation}. Valid: prime, ready, create, claim, close, fail, defer, progress, decompose, dep_add, dep_tree, stats, list, record_decision, revise_decision, unpin_decision, list_decisions.`,
66
+ message: `Unknown operation: ${args.operation}. Valid: prime, create, close, fail, record_decision.`,
75
67
  meta: { tool: 'autosnippet_task' },
76
68
  });
77
69
  }
78
- // ── 飞书任务进度通知(异步非阻塞)──
79
- _notifyTaskProgress(args.operation, args, result).catch((err) => {
80
- process.stderr.write(`[MCP/Task] Notify error: ${err?.message}\n`);
70
+ // ── Lark notification (async, non-blocking) ──
71
+ notifyTaskProgress(args.operation, args, result).catch((err) => {
72
+ process.stderr.write(`[MCP/Task] Notify error: ${err instanceof Error ? err.message : String(err)}\n`);
81
73
  });
82
74
  return result;
83
75
  }
84
- // ── create ──
85
- async function _create(svc, args) {
86
- if (!args.title) {
87
- return envelope({
88
- success: false,
89
- message: 'title is required',
90
- meta: { tool: 'autosnippet_task' },
91
- });
76
+ // ═══ prime ═══════════════════════════════════════════════
77
+ async function _prime(ctx, args) {
78
+ const intent = ctx.session?.intent;
79
+ // If there is an active intent, persist it as abandoned before starting fresh
80
+ if (intent && intent.phase === 'active') {
81
+ _persistIntentChain(ctx, intent, 'abandoned', 'New prime received');
82
+ }
83
+ // ─── Intake: extract intent signals ───
84
+ const extracted = extractIntent(args.userQuery || '', args.activeFile, args.language);
85
+ // ─── Enrichment: multi-query search via PrimeSearchPipeline ───
86
+ const pipeline = _getPipeline(ctx.container);
87
+ let searchResult = null;
88
+ if (pipeline && extracted.queries[0]?.trim()) {
89
+ try {
90
+ searchResult = await pipeline.search(extracted);
91
+ }
92
+ catch {
93
+ // search failure is non-fatal
94
+ }
95
+ }
96
+ // ─── Lifecycle: initialize IntentState ───
97
+ const freshIntent = createIdleIntent();
98
+ freshIntent.phase = 'active';
99
+ freshIntent.primeQuery = args.userQuery || '';
100
+ freshIntent.primeActiveFile = args.activeFile;
101
+ freshIntent.primeLanguage = extracted.language;
102
+ freshIntent.primeModule = extracted.module;
103
+ freshIntent.primeScenario = extracted.scenario;
104
+ freshIntent.primeAt = Date.now();
105
+ if (searchResult) {
106
+ freshIntent.primeRecipeIds = [...searchResult.relatedKnowledge, ...searchResult.guardRules]
107
+ .map((r) => r.id)
108
+ .filter(Boolean);
109
+ freshIntent.searchMeta = {
110
+ queries: searchResult.searchMeta.queries,
111
+ resultCount: searchResult.searchMeta.resultCount,
112
+ filteredCount: searchResult.searchMeta.filteredCount,
113
+ };
114
+ }
115
+ // Bind intent to session
116
+ if (ctx.session) {
117
+ ctx.session.intent = freshIntent;
118
+ }
119
+ // ─── Delivery: build response ───
120
+ const relatedCount = searchResult?.relatedKnowledge.length ?? 0;
121
+ const ruleCount = searchResult?.guardRules.length ?? 0;
122
+ const lines = [];
123
+ if (relatedCount > 0 || ruleCount > 0) {
124
+ lines.push(`📋 Found ${relatedCount} recipe(s), ${ruleCount} guard rule(s).`);
125
+ for (const r of searchResult.relatedKnowledge) {
126
+ const hint = r.actionHint ? ` — ${r.actionHint}` : '';
127
+ lines.push(` • ${r.trigger || r.title}${hint}`);
128
+ }
129
+ for (const r of searchResult.guardRules) {
130
+ lines.push(` • [rule] ${r.trigger || r.title}`);
131
+ }
132
+ }
133
+ else {
134
+ lines.push('No matching recipes found.');
92
135
  }
93
- const { task, isDuplicate } = await svc.create({
94
- title: args.title,
95
- description: args.description || '',
96
- design: args.design || '',
97
- acceptance: args.acceptance || '',
98
- priority: args.priority ?? 2,
99
- taskType: args.taskType || 'task',
100
- parentId: args.parentId || null,
101
- });
102
- return envelope({
103
- success: true,
104
- data: task.toJSON(),
105
- message: isDuplicate
106
- ? `⚠ Duplicate detected: ${task.id} already exists`
107
- : `Created ${task.id}: ${task.title}`,
108
- meta: { tool: 'autosnippet_task' },
109
- });
110
- }
111
- // ── ready ──
112
- async function _ready(svc, args) {
113
- const tasks = await svc.ready({
114
- limit: args.limit || 10,
115
- withKnowledge: args.withKnowledge !== false,
116
- userQuery: args.userQuery,
117
- activeFile: args.activeFile,
118
- language: args.language,
119
- });
120
136
  return envelope({
121
137
  success: true,
122
- data: tasks.map((t) => (t.toJSON ? t.toJSON() : t)),
123
- message: `${tasks.length} task(s) ready`,
138
+ data: {
139
+ knowledge: searchResult
140
+ ? {
141
+ relatedKnowledge: searchResult.relatedKnowledge,
142
+ guardRules: searchResult.guardRules,
143
+ }
144
+ : null,
145
+ searchMeta: searchResult?.searchMeta ?? null,
146
+ _taskRules,
147
+ },
148
+ message: lines.join('\n'),
124
149
  meta: { tool: 'autosnippet_task' },
125
150
  });
126
151
  }
127
- // ── claim ──
128
- async function _claim(svc, args) {
129
- if (!args.id) {
152
+ // ═══ create ═════════════════════════════════════════════
153
+ async function _create(ctx, args) {
154
+ if (!args.title) {
130
155
  return envelope({
131
156
  success: false,
132
- message: 'id is required',
157
+ message: 'title is required',
133
158
  meta: { tool: 'autosnippet_task' },
134
159
  });
135
160
  }
136
- const knowledgeOptions = args.userQuery || args.activeFile || args.language
137
- ? { userQuery: args.userQuery, activeFile: args.activeFile, language: args.language }
138
- : undefined;
139
- const task = await svc.claim(args.id, 'agent', knowledgeOptions);
161
+ const taskId = _generateTaskId();
162
+ const intent = ctx.session?.intent;
163
+ // Bind task ID to current intent
164
+ if (intent && intent.phase === 'active') {
165
+ intent.taskId = taskId;
166
+ intent.taskTitle = args.title;
167
+ }
140
168
  return envelope({
141
169
  success: true,
142
- data: task.toJSON(),
143
- message: `Claimed ${args.id}`,
170
+ data: { id: taskId, title: args.title },
171
+ message: `📌 Created: ${taskId} — ${args.title}`,
144
172
  meta: { tool: 'autosnippet_task' },
145
173
  });
146
174
  }
147
- // ── close ──
148
- async function _close(ctx, svc, args) {
175
+ // ═══ close ══════════════════════════════════════════════
176
+ async function _close(ctx, args) {
149
177
  if (!args.id) {
150
178
  return envelope({
151
179
  success: false,
@@ -153,21 +181,23 @@ async function _close(ctx, svc, args) {
153
181
  meta: { tool: 'autosnippet_task' },
154
182
  });
155
183
  }
156
- const { task, newlyReady } = await svc.close(args.id, args.reason || 'Completed');
157
- const lines = [`✅ Closed: ${args.id} ${task.title}`];
158
- if (args.reason && args.reason !== 'Completed') {
159
- lines.push(`Reason: ${args.reason}`);
184
+ const intent = ctx.session?.intent;
185
+ const reason = args.reason || 'Completed';
186
+ // Persist intent chain via SignalBus
187
+ if (intent && intent.phase === 'active') {
188
+ _persistIntentChain(ctx, intent, 'completed', reason);
160
189
  }
161
- if (newlyReady.length > 0) {
162
- lines.push(`→ ${newlyReady.length} task(s) newly ready`);
190
+ // Reset intent to idle
191
+ if (ctx.session) {
192
+ ctx.session.intent = createIdleIntent();
163
193
  }
194
+ const lines = [`✅ Closed: ${args.id} — ${reason}`];
164
195
  lines.push('');
165
- lines.push('⚠️ REQUIRED: You MUST call autosnippet_guard (no args) NOW to review changed files for compliance violations. Do NOT proceed to the next task until guard review passes.');
196
+ lines.push('⚠️ REQUIRED: You MUST call autosnippet_guard (no args) NOW to review changed files for compliance violations.');
166
197
  return envelope({
167
198
  success: true,
168
199
  data: {
169
- closed: task.toJSON(),
170
- newlyReady,
200
+ closed: { id: args.id, reason, closedAt: Date.now() },
171
201
  nextAction: {
172
202
  tool: 'autosnippet_guard',
173
203
  args: {},
@@ -179,150 +209,8 @@ async function _close(ctx, svc, args) {
179
209
  meta: { tool: 'autosnippet_task' },
180
210
  });
181
211
  }
182
- // ── fail ──
183
- async function _fail(svc, args) {
184
- if (!args.id) {
185
- return envelope({
186
- success: false,
187
- message: 'id is required',
188
- meta: { tool: 'autosnippet_task' },
189
- });
190
- }
191
- const task = await svc.fail(args.id, args.reason || 'Agent execution failed');
192
- return envelope({
193
- success: true,
194
- data: task.toJSON(),
195
- message: `Failed ${args.id} (attempt #${task.failCount}): ${task.lastFailReason}`,
196
- meta: { tool: 'autosnippet_task' },
197
- });
198
- }
199
- // ── defer ──
200
- async function _defer(svc, args) {
201
- if (!args.id) {
202
- return envelope({
203
- success: false,
204
- message: 'id is required',
205
- meta: { tool: 'autosnippet_task' },
206
- });
207
- }
208
- const task = await svc.defer(args.id, args.reason || '');
209
- return envelope({
210
- success: true,
211
- data: task.toJSON(),
212
- message: `Deferred ${args.id}`,
213
- meta: { tool: 'autosnippet_task' },
214
- });
215
- }
216
- // ── progress ──
217
- async function _progress(svc, args) {
218
- if (!args.id) {
219
- return envelope({
220
- success: false,
221
- message: 'id is required',
222
- meta: { tool: 'autosnippet_task' },
223
- });
224
- }
225
- const note = args.reason || args.description || '';
226
- const task = await svc.progress(args.id, note);
227
- return envelope({
228
- success: true,
229
- data: task.toJSON(),
230
- message: `Progress updated for ${args.id}`,
231
- meta: { tool: 'autosnippet_task' },
232
- });
233
- }
234
- // ── decompose ──
235
- async function _decompose(svc, args) {
236
- if (!args.id) {
237
- return envelope({
238
- success: false,
239
- message: 'Epic id is required',
240
- meta: { tool: 'autosnippet_task' },
241
- });
242
- }
243
- if (!args.subtasks || !Array.isArray(args.subtasks) || args.subtasks.length === 0) {
244
- return envelope({
245
- success: false,
246
- message: 'subtasks array is required',
247
- meta: { tool: 'autosnippet_task' },
248
- });
249
- }
250
- const tasks = await svc.decompose(args.id, args.subtasks);
251
- return envelope({
252
- success: true,
253
- data: tasks.map((t) => (t.toJSON ? t.toJSON() : t)),
254
- message: `Decomposed ${args.id} into ${tasks.length} subtasks`,
255
- meta: { tool: 'autosnippet_task' },
256
- });
257
- }
258
- // ── show ──
259
- async function _show(svc, args) {
260
- if (!args.id) {
261
- return envelope({
262
- success: false,
263
- message: 'id is required',
264
- meta: { tool: 'autosnippet_task' },
265
- });
266
- }
267
- const task = await svc.show(args.id);
268
- if (!task) {
269
- return envelope({
270
- success: false,
271
- message: `Task not found: ${args.id}`,
272
- meta: { tool: 'autosnippet_task' },
273
- });
274
- }
275
- return envelope({
276
- success: true,
277
- data: task.toJSON(),
278
- meta: { tool: 'autosnippet_task' },
279
- });
280
- }
281
- // ── list ──
282
- async function _list(svc, args) {
283
- const filters = {};
284
- if (args.status) {
285
- filters.status = args.status;
286
- }
287
- if (args.taskType) {
288
- filters.taskType = args.taskType;
289
- }
290
- const tasks = await svc.list(filters, { limit: args.limit || 20 });
291
- return envelope({
292
- success: true,
293
- data: tasks.map((t) => t.toJSON()),
294
- message: `${tasks.length} task(s)`,
295
- meta: { tool: 'autosnippet_task' },
296
- });
297
- }
298
- // ── blocked ──
299
- async function _blocked(svc) {
300
- const tasks = await svc.blocked();
301
- return envelope({
302
- success: true,
303
- data: tasks,
304
- message: `${tasks.length} blocked task(s)`,
305
- meta: { tool: 'autosnippet_task' },
306
- });
307
- }
308
- // ── dep_add ──
309
- async function _depAdd(svc, args) {
310
- if (!args.id || !args.dependsOn) {
311
- return envelope({
312
- success: false,
313
- message: 'id and dependsOn are required',
314
- meta: { tool: 'autosnippet_task' },
315
- });
316
- }
317
- await svc.addDependency(args.id, args.dependsOn, args.depType || 'blocks');
318
- return envelope({
319
- success: true,
320
- message: `${args.id} ${args.depType || 'blocks'} ${args.dependsOn}`,
321
- meta: { tool: 'autosnippet_task' },
322
- });
323
- }
324
- // ── dep_tree ──
325
- async function _depTree(svc, args) {
212
+ // ═══ fail ═══════════════════════════════════════════════
213
+ async function _fail(ctx, args) {
326
214
  if (!args.id) {
327
215
  return envelope({
328
216
  success: false,
@@ -330,104 +218,27 @@ async function _depTree(svc, args) {
330
218
  meta: { tool: 'autosnippet_task' },
331
219
  });
332
220
  }
333
- const tree = await svc.depTree(args.id);
334
- return envelope({
335
- success: true,
336
- data: tree,
337
- message: `${tree.length} node(s) in dependency tree`,
338
- meta: { tool: 'autosnippet_task' },
339
- });
340
- }
341
- // ── stats ──
342
- async function _stats(svc) {
343
- const stats = await svc.stats();
344
- return envelope({
345
- success: true,
346
- data: stats,
347
- meta: { tool: 'autosnippet_task' },
348
- });
349
- }
350
- // ═══ Session (prime) ═══════════════════════════════════
351
- async function _prime(svc, args) {
352
- const result = await svc.prime({
353
- limit: args.limit || 10,
354
- withKnowledge: args.withKnowledge !== false,
355
- userQuery: args.userQuery,
356
- activeFile: args.activeFile,
357
- language: args.language,
358
- });
359
- const decisionCount = (result.decisions || []).length;
360
- const staleCount = (result.staleDecisions || []).length;
361
- const decisionTitles = (result.decisions || []).map((d) => d.title).join('; ');
362
- const statsLine = `${result.inProgress.length} in-progress, ${result.ready.length} ready, ${result.stats.total} total`;
363
- // ── Behavioral Rules Reminder (survives compaction) ──
364
- result._taskRules = {
365
- reminder: [
366
- '📋 TASK RULES (MANDATORY):',
367
- '🔑 YOU are the task operator — user speaks naturally, you translate to task operations. NEVER tell user to run task commands.',
368
- '• MUST prime on EVERY message BEFORE anything else',
369
- '• MUST create task for non-trivial work (≥2 files OR ≥10 lines)',
370
- '• MUST claim before coding, close when done with meaningful reason',
371
- '• MUST handle unfinished tasks before starting new work (ask user: Continue/Defer/Abandon)',
372
- '• NEVER skip prime, NEVER start new work with open in_progress tasks',
373
- '• NEVER leave tasks in in_progress when session ends — close or defer ALL',
374
- '• When in doubt → create a task. When idle → ready()',
375
- '• Session end → close all tasks, defer incomplete, verify zero in_progress',
376
- ].join('\n'),
377
- translationHint: [
378
- 'User Says → You Run:',
379
- '"fix bug"/"implement" → create→claim→code→close',
380
- '"continue" → resume in-progress→close',
381
- '"pause" → defer | "abandon" → fail | "break down" → decompose',
382
- '"what\'s next" → ready() | "agreed" → record_decision',
383
- 'Quick question → No task. Just answer.',
384
- ].join('\n'),
385
- };
386
- let message;
387
- if (decisionCount > 0) {
388
- const stalePart = staleCount > 0 ? ` ${staleCount} stale.` : '';
389
- message = `⚠️ ${decisionCount} ACTIVE DECISION(S): [${decisionTitles}].${stalePart} ${statsLine}.`;
221
+ const intent = ctx.session?.intent;
222
+ const reason = args.reason || 'Agent execution failed';
223
+ // Persist intent chain via SignalBus
224
+ if (intent && intent.phase === 'active') {
225
+ _persistIntentChain(ctx, intent, 'failed', reason);
390
226
  }
391
- else {
392
- message = `${statsLine}.`;
393
- }
394
- // ── Resume Prompt: 有 inProgress 任务时,提示 Agent 让用户选择 ──
395
- if (result.inProgress.length > 0) {
396
- const taskList = result.inProgress
397
- .map((t) => {
398
- const age = t.updatedAt
399
- ? `${Math.floor((Date.now() / 1000 - t.updatedAt) / 86400)}d ago`
400
- : '';
401
- return `• **${t.id}** — ${t.title}${age ? ` (${age})` : ''}`;
402
- })
403
- .join('\n');
404
- result._resumePrompt = {
405
- instruction: [
406
- 'There are unfinished tasks. You MUST present these options to the user BEFORE doing anything else:',
407
- '',
408
- '**Unfinished tasks:**',
409
- taskList,
410
- '',
411
- 'Ask the user to choose:',
412
- '1. **Continue** — resume the unfinished task(s)',
413
- '2. **Defer** — pause it and work on something else',
414
- '3. **Abandon** — close/fail it and start fresh',
415
- '',
416
- "Wait for the user's answer. Do NOT auto-resume.",
417
- ].join('\n'),
418
- taskIds: result.inProgress.map((t) => t.id),
419
- };
420
- message += ` ⏸️ ${result.inProgress.length} unfinished task(s) — ask user before resuming.`;
227
+ // Reset intent to idle
228
+ if (ctx.session) {
229
+ ctx.session.intent = createIdleIntent();
421
230
  }
422
231
  return envelope({
423
232
  success: true,
424
- data: result,
425
- message,
233
+ data: {
234
+ failed: { id: args.id, reason, failedAt: Date.now() },
235
+ },
236
+ message: `❌ Failed: ${args.id} — ${reason}`,
426
237
  meta: { tool: 'autosnippet_task' },
427
238
  });
428
239
  }
429
- // ═══ Decisions ═══════════════════════════════════════
430
- async function _recordDecision(svc, args) {
240
+ // ═══ record_decision ════════════════════════════════════
241
+ async function _recordDecision(ctx, args) {
431
242
  if (!args.title) {
432
243
  return envelope({
433
244
  success: false,
@@ -442,229 +253,78 @@ async function _recordDecision(svc, args) {
442
253
  meta: { tool: 'autosnippet_task' },
443
254
  });
444
255
  }
445
- const { task, isDuplicate } = await svc.recordDecision({
256
+ const decisionId = `dec-${Date.now().toString(36)}`;
257
+ const decision = {
258
+ id: decisionId,
446
259
  title: args.title,
447
260
  description: args.description,
448
- rationale: args.rationale || '',
449
- tags: args.tags || [],
450
- relatedTaskId: args.relatedTaskId || null,
451
- });
452
- return envelope({
453
- success: true,
454
- data: task.toJSON(),
455
- message: isDuplicate
456
- ? `⚠ Decision already recorded: ${task.id}`
457
- : `✅ Decision pinned: ${task.id} — "${args.title}"`,
458
- meta: { tool: 'autosnippet_task' },
459
- });
460
- }
461
- async function _reviseDecision(svc, args) {
462
- if (!args.id) {
463
- return envelope({
464
- success: false,
465
- message: 'id of old decision is required',
466
- meta: { tool: 'autosnippet_task' },
467
- });
468
- }
469
- if (!args.title) {
470
- return envelope({
471
- success: false,
472
- message: 'title of new decision is required',
473
- meta: { tool: 'autosnippet_task' },
474
- });
475
- }
476
- if (!args.description) {
477
- return envelope({
478
- success: false,
479
- message: 'description of new decision is required',
480
- meta: { tool: 'autosnippet_task' },
481
- });
482
- }
483
- const result = await svc.reviseDecision({
484
- oldDecisionId: args.id,
485
- title: args.title,
486
- description: args.description,
487
- rationale: args.rationale || '',
488
- reason: args.reason || '',
489
- });
490
- return envelope({
491
- success: true,
492
- data: {
493
- newDecision: result.newDecision.toJSON(),
494
- superseded: result.oldDecisionId,
495
- },
496
- message: `✅ Decision revised: ${result.oldDecisionId} → ${result.newDecision.id}`,
497
- meta: { tool: 'autosnippet_task' },
498
- });
499
- }
500
- async function _unpinDecision(svc, args) {
501
- if (!args.id) {
502
- return envelope({
503
- success: false,
504
- message: 'id is required',
505
- meta: { tool: 'autosnippet_task' },
506
- });
261
+ rationale: args.rationale,
262
+ tags: args.tags,
263
+ recordedAt: Date.now(),
264
+ };
265
+ // Push to current intent's decisions
266
+ const intent = ctx.session?.intent;
267
+ if (intent && intent.phase === 'active') {
268
+ intent.decisions.push(decision);
507
269
  }
508
- const task = await svc.unpinDecision(args.id, args.reason || '');
509
- return envelope({
510
- success: true,
511
- data: task.toJSON(),
512
- message: `Decision ${args.id} unpinned and closed`,
513
- meta: { tool: 'autosnippet_task' },
514
- });
515
- }
516
- async function _listDecisions(svc) {
517
- const decisions = await svc.list({ status: 'pinned', taskType: 'decision' }, { limit: 50 });
518
270
  return envelope({
519
271
  success: true,
520
- data: decisions.map((d) => d.toJSON()),
521
- message: `${decisions.length} active decision(s)`,
272
+ data: { decision: { id: decisionId, title: args.title } },
273
+ message: `📌 Decision recorded: ${args.title}`,
522
274
  meta: { tool: 'autosnippet_task' },
523
275
  });
524
276
  }
525
- // ═══ 飞书任务进度通知(通过 API Server 中转)═══════════════
526
- //
527
- // MCP Server 与 API Server 是独立进程。
528
- // 飞书 WSClient 连接在 API Server 中,因此通知需 HTTP 中转。
529
- // ═══════════════════════════════════════════════════════════
530
- const PRIORITY_LABELS = ['P0 紧急', 'P1 高', 'P2 中', 'P3 低', 'P4 微'];
531
- /** 通过 API Server 的 /api/v1/remote/notify 发送飞书通知 */
532
- async function _sendLarkViaApi(text) {
277
+ // ═══ Intent Chain Persistence (via SignalBus) ═══════════
278
+ function _persistIntentChain(ctx, intent, outcome, reason) {
279
+ const now = Date.now();
280
+ const chain = {
281
+ sessionId: ctx.session?.id || 'unknown',
282
+ taskId: intent.taskId,
283
+ outcome,
284
+ primeQuery: intent.primeQuery,
285
+ primeActiveFile: intent.primeActiveFile,
286
+ primeRecipeIds: intent.primeRecipeIds,
287
+ primeAt: intent.primeAt || now,
288
+ primeLanguage: intent.primeLanguage ?? null,
289
+ primeModule: intent.primeModule ?? null,
290
+ primeScenario: intent.primeScenario ?? 'search',
291
+ searchMeta: intent.searchMeta,
292
+ toolCalls: intent.toolCalls,
293
+ searchQueries: intent.searchQueries,
294
+ mentionedFiles: intent.mentionedFiles,
295
+ decisions: intent.decisions,
296
+ driftEvents: intent.driftEvents,
297
+ driftScore: _computeDriftScore(intent),
298
+ closeReason: outcome === 'completed' ? reason : undefined,
299
+ failReason: outcome !== 'completed' ? reason : undefined,
300
+ startedAt: intent.primeAt || now,
301
+ endedAt: now,
302
+ duration: now - (intent.primeAt || now),
303
+ };
304
+ // Emit via SignalBus — subscribers handle JSONL persistence
533
305
  try {
534
- const port = process.env.PORT || 3000;
535
- const resp = await fetch(`http://localhost:${port}/api/v1/remote/notify`, {
536
- method: 'POST',
537
- headers: { 'Content-Type': 'application/json' },
538
- body: JSON.stringify({ text }),
539
- signal: AbortSignal.timeout(5000),
306
+ const signalBus = ctx.container.get('signalBus');
307
+ signalBus.send('intent', 'TaskHandler', _computeDriftScore(intent), {
308
+ target: intent.taskId ?? null,
309
+ metadata: { chain },
540
310
  });
541
- if (!resp.ok) {
542
- process.stderr.write(`[MCP/Task] Lark notify HTTP ${resp.status}\n`);
543
- return false;
544
- }
545
- const body = (await resp.json());
546
- return body.success === true;
547
311
  }
548
- catch (err) {
549
- process.stderr.write(`[MCP/Task] Lark notify failed: ${err instanceof Error ? err.message : String(err)}\n`);
550
- return false;
312
+ catch {
313
+ // signalBus unavailable silent failure, non-blocking
551
314
  }
552
315
  }
553
- /**
554
- * 通过 API Server 截取 IDE 窗口截图并发送到飞书
555
- * @param [caption] 可选文字说明
556
- */
557
- async function _sendScreenshotViaApi(caption = '') {
558
- try {
559
- const port = process.env.PORT || 3000;
560
- const resp = await fetch(`http://localhost:${port}/api/v1/remote/screenshot`, {
561
- method: 'POST',
562
- headers: { 'Content-Type': 'application/json' },
563
- body: JSON.stringify({ caption }),
564
- signal: AbortSignal.timeout(15000),
565
- });
566
- if (!resp.ok) {
567
- process.stderr.write(`[MCP/Task] Screenshot HTTP ${resp.status}\n`);
568
- return false;
569
- }
570
- const body = (await resp.json());
571
- return body.success === true;
572
- }
573
- catch (err) {
574
- process.stderr.write(`[MCP/Task] Screenshot failed: ${err instanceof Error ? err.message : String(err)}\n`);
575
- return false;
316
+ function _computeDriftScore(intent) {
317
+ if (intent.driftEvents.length === 0) {
318
+ return 0;
576
319
  }
320
+ const sum = intent.driftEvents.reduce((acc, d) => acc + (1 - d.primeOverlap), 0);
321
+ return sum / intent.driftEvents.length;
577
322
  }
578
- /**
579
- * 根据任务操作向飞书发送进度通知(异步非阻塞)
580
- * result 是 envelope() 返回的 { success, data, message, meta }
581
- */
582
- async function _notifyTaskProgress(operation, args, result) {
583
- if (!result || result.success === false) {
584
- return;
585
- }
586
- const data = result.data;
587
- let text = '';
588
- switch (operation) {
589
- case 'create': {
590
- const title = data?.title || args.title || '';
591
- const id = data?.id || '';
592
- const type = data?.taskType || args.taskType || 'task';
593
- const pri = PRIORITY_LABELS[(data?.priority ?? args.priority ?? 2)] || 'P2';
594
- const dup = result.message?.includes('Duplicate') || result.message?.startsWith('⚠') ? ' (重复)' : '';
595
- text = `📋 新任务${dup}: ${id}\n${title}\n类型: ${type} | ${pri}`;
596
- break;
597
- }
598
- case 'claim': {
599
- const id = data?.id || args.id;
600
- const title = data?.title || '';
601
- text = `🔨 开始执行: ${id}\n${title}`;
602
- break;
603
- }
604
- case 'close': {
605
- const closed = (data?.closed || data);
606
- const title = closed?.title || '';
607
- const id = closed?.id || args.id;
608
- const reason = closed?.closeReason || args.reason || '';
609
- const readyCount = Array.isArray(data?.newlyReady) ? data.newlyReady.length : 0;
610
- const readyInfo = readyCount > 0 ? `\n→ ${readyCount} 个任务新就绪` : '';
611
- text = `✅ 完成: ${id}\n${title}\n原因: ${reason}${readyInfo}`;
612
- break;
613
- }
614
- case 'fail': {
615
- const title = data?.title || '';
616
- const id = data?.id || args.id;
617
- const reason = data?.lastFailReason || args.reason || '未知';
618
- const count = Number(data?.failCount || 0);
619
- text = `❌ 失败: ${id}\n${title}\n原因: ${reason}${count > 1 ? ` (第${count}次)` : ''}`;
620
- break;
621
- }
622
- case 'defer': {
623
- const id = data?.id || args.id;
624
- const title = data?.title || '';
625
- text = `⏸️ 暂缓: ${id} — ${title}`;
626
- break;
627
- }
628
- case 'progress': {
629
- const id = data?.id || args.id;
630
- const note = args.reason || args.description || '';
631
- text = note ? `📝 进度: ${id}\n${note.slice(0, 200)}` : `📝 进度: ${id}`;
632
- break;
633
- }
634
- case 'decompose': {
635
- const epicId = args.id;
636
- const count = Array.isArray(data) ? data.length : 0;
637
- const subTitles = Array.isArray(data)
638
- ? data
639
- .slice(0, 5)
640
- .map((t, i) => ` ${i + 1}. ${t.title || t.id}`)
641
- .join('\n')
642
- : '';
643
- text = `📂 拆解: ${epicId} → ${count} 个子任务${subTitles ? `\n${subTitles}` : ''}`;
644
- break;
645
- }
646
- case 'record_decision': {
647
- const title = data?.title || args.title || '';
648
- text = `📌 决策: ${title}`;
649
- break;
650
- }
651
- case 'revise_decision': {
652
- const oldId = data?.superseded || args.id;
653
- const newTitle = data?.newDecision?.title || args.title;
654
- text = `🔄 决策更新: ${oldId} → ${newTitle}`;
655
- break;
656
- }
657
- case 'unpin_decision': {
658
- const id = data?.id || args.id;
659
- text = `🔓 决策取消: ${id}`;
660
- break;
661
- }
662
- default:
663
- return;
323
+ function _getPipeline(container) {
324
+ try {
325
+ return container.get('primeSearchPipeline');
664
326
  }
665
- if (text) {
666
- await _sendLarkViaApi(text);
667
- // 发送文字通知后,附带 IDE 窗口截图
668
- await _sendScreenshotViaApi();
327
+ catch {
328
+ return null;
669
329
  }
670
330
  }