catalyst-core 0.3.0-beta.5 → 0.3.0-canary.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 (316) hide show
  1. package/changelog.md +185 -71
  2. package/dist/errors/generateDocs.js +100 -0
  3. package/dist/errors/index.js +243 -0
  4. package/dist/errors/registry.js +483 -0
  5. package/dist/errors-index.json +506 -0
  6. package/dist/globals.d.ts +62 -0
  7. package/dist/index.d.ts +5 -0
  8. package/dist/index.jsx +5 -8
  9. package/dist/logger.js +1 -1
  10. package/dist/native/androidProject/app/build.gradle.kts +142 -7
  11. package/dist/native/androidProject/app/src/main/AndroidManifest.xml +4 -0
  12. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +2 -2
  13. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/BarcodeDetector.kt +3 -0
  14. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/CameraSessionManager.kt +3 -0
  15. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +43 -8
  16. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/BridgeUtilsTest.kt +181 -1
  17. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/CameraUtilsTest.kt +156 -236
  18. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FileSizeRouterUtilsTest.kt +471 -0
  19. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FileUtilsTest.kt +222 -226
  20. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FrameworkServerUtilsTest.kt +300 -0
  21. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/IntentUtilsTest.kt +244 -0
  22. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/MetricsMonitorTest.kt +359 -0
  23. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/NativeBridgeTest.kt +108 -63
  24. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/NotificationUtilsTest.kt +329 -385
  25. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/OfflineCacheServiceTest.kt +302 -0
  26. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/PerfEventBufferTest.kt +133 -0
  27. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/UtilsKtTest.kt +152 -0
  28. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/WebCacheManagerTest.kt +145 -324
  29. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/BarcodeDetectorTest.kt +132 -0
  30. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/HoldControllerTest.kt +155 -0
  31. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/TorchControllerTest.kt +150 -0
  32. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/VideoStreamStateMachineTest.kt +120 -0
  33. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/VideoStreamStateTest.kt +62 -0
  34. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/ViewfinderMapperTest.kt +143 -0
  35. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/ZoomControllerTest.kt +421 -0
  36. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/design/DesignTokensTest.kt +207 -0
  37. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/plugins/PluginBridgeTest.kt +368 -0
  38. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/FridaDetectorTest.kt +193 -0
  39. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/SecurityCheckManagerTest.kt +260 -0
  40. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/SecurityCheckSchedulerTest.kt +166 -0
  41. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/DeviceInfoUtilsTest.kt +167 -0
  42. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/DownloadUtilsTest.kt +197 -0
  43. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/NetworkMonitorTest.kt +271 -0
  44. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/PushNotificationUtilsTest.kt +119 -0
  45. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/SafeAreaUtilsTest.kt +108 -0
  46. package/dist/native/androidProject/build.gradle.kts +1 -0
  47. package/dist/native/androidProject/gradle/libs.versions.toml +26 -0
  48. package/dist/native/androidProject/settings.gradle.kts +11 -8
  49. package/dist/native/androidSetup.js +2 -2
  50. package/dist/native/bridge/WebBridge.d.ts +98 -0
  51. package/dist/native/bridge/WebBridge.js +40 -6
  52. package/dist/native/bridge/constants/NativeInterfaces.d.ts +391 -0
  53. package/dist/native/bridge/errors.d.ts +67 -0
  54. package/dist/native/bridge/errors.js +66 -151
  55. package/dist/native/bridge/hooks/index.d.ts +13 -0
  56. package/dist/native/bridge/hooks/index.js +0 -6
  57. package/dist/native/bridge/hooks/useAI.d.ts +1 -0
  58. package/dist/native/bridge/hooks/useAI.js +3 -1
  59. package/dist/native/bridge/hooks/useCamera.d.ts +86 -0
  60. package/dist/native/bridge/hooks/useCamera.js +35 -6
  61. package/dist/native/bridge/hooks/useDataProtection.d.ts +17 -0
  62. package/dist/native/bridge/hooks/useDeviceInfo.d.ts +34 -0
  63. package/dist/native/bridge/hooks/useDeviceInfo.js +5 -0
  64. package/dist/native/bridge/hooks/useFilePicker.d.ts +53 -0
  65. package/dist/native/bridge/hooks/useFilePicker.js +13 -0
  66. package/dist/native/bridge/hooks/useGoogleSignIn.d.ts +12 -0
  67. package/dist/native/bridge/hooks/useHapticFeedback.d.ts +76 -0
  68. package/dist/native/bridge/hooks/useHapticFeedback.js +6 -1
  69. package/dist/native/bridge/hooks/useIntent.d.ts +33 -0
  70. package/dist/native/bridge/hooks/useIntent.js +2 -0
  71. package/dist/native/bridge/hooks/useNativeTransition.d.ts +53 -0
  72. package/dist/native/bridge/hooks/useNativeTransition.js +12 -5
  73. package/dist/native/bridge/hooks/useNetworkStatus.d.ts +22 -0
  74. package/dist/native/bridge/hooks/useNetworkStatus.js +7 -0
  75. package/dist/native/bridge/hooks/useNotification.d.ts +83 -0
  76. package/dist/native/bridge/hooks/useNotification.js +81 -34
  77. package/dist/native/bridge/hooks/useSafeArea.d.ts +12 -0
  78. package/dist/native/bridge/hooks/useSafeArea.js +8 -0
  79. package/dist/native/bridge/hooks/useVideoStream.d.ts +67 -0
  80. package/dist/native/bridge/hooks/useVideoStream.js +38 -52
  81. package/dist/native/bridge/hooks/utils.d.ts +4 -0
  82. package/dist/native/bridge/hooks.d.ts +1 -0
  83. package/dist/native/bridge/perf/collectors/ApiCollector.d.ts +30 -0
  84. package/dist/native/bridge/perf/collectors/ApiCollector.js +4 -0
  85. package/dist/native/bridge/perf/collectors/CacheCollector.d.ts +43 -0
  86. package/dist/native/bridge/perf/collectors/CacheCollector.js +4 -0
  87. package/dist/native/bridge/perf/collectors/HookCollector.d.ts +37 -0
  88. package/dist/native/bridge/perf/collectors/HookCollector.js +4 -0
  89. package/dist/native/bridge/perf/collectors/InsightsCollector.d.ts +103 -0
  90. package/dist/native/bridge/perf/collectors/InsightsCollector.js +4 -0
  91. package/dist/native/bridge/perf/collectors/InteractionCollector.d.ts +53 -0
  92. package/dist/native/bridge/perf/collectors/InteractionCollector.js +4 -0
  93. package/dist/native/bridge/perf/collectors/KeyboardCollector.d.ts +30 -0
  94. package/dist/native/bridge/perf/collectors/KeyboardCollector.js +4 -0
  95. package/dist/native/bridge/perf/collectors/NavigationCollector.d.ts +37 -0
  96. package/dist/native/bridge/perf/collectors/NavigationCollector.js +4 -0
  97. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.d.ts +30 -0
  98. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +4 -0
  99. package/dist/native/bridge/perf/collectors/RenderCollector.d.ts +47 -0
  100. package/dist/native/bridge/perf/collectors/RenderCollector.js +8 -0
  101. package/dist/native/bridge/perf/collectors/ScrollCollector.d.ts +29 -0
  102. package/dist/native/bridge/perf/collectors/ScrollCollector.js +4 -0
  103. package/dist/native/bridge/perf/collectors/ThreadCollector.d.ts +31 -0
  104. package/dist/native/bridge/perf/collectors/ThreadCollector.js +4 -0
  105. package/dist/native/bridge/perf/core/constants.d.ts +76 -0
  106. package/dist/native/bridge/perf/core/measure.d.ts +39 -0
  107. package/dist/native/bridge/perf/core/measure.js +4 -0
  108. package/dist/native/bridge/perf/core/session.d.ts +49 -0
  109. package/dist/native/bridge/perf/core/session.js +4 -0
  110. package/dist/native/bridge/perf/core/store.d.ts +37 -0
  111. package/dist/native/bridge/perf/core/store.js +4 -0
  112. package/dist/native/bridge/perf/core/summary.d.ts +60 -0
  113. package/dist/native/bridge/perf/core/traceExport.d.ts +10 -0
  114. package/dist/native/bridge/perf/core/waterfalls.d.ts +2 -0
  115. package/dist/native/bridge/perf/index.d.ts +63 -0
  116. package/dist/native/bridge/perf/index.js +4 -0
  117. package/dist/native/bridge/safeArea.d.ts +11 -0
  118. package/dist/native/bridge/safeArea.js +2 -0
  119. package/dist/native/bridge/useBaseHook.d.ts +137 -0
  120. package/dist/native/bridge/useBaseHook.js +34 -4
  121. package/dist/native/bridge/utils/CameraUtils.d.ts +94 -0
  122. package/dist/native/bridge/utils/CameraUtils.js +4 -0
  123. package/dist/native/bridge/utils/FileObjectConverter.d.ts +36 -0
  124. package/dist/native/bridge/utils/NativeBridge.d.ts +270 -0
  125. package/dist/native/bridge/utils/NativeBridge.js +10 -0
  126. package/dist/native/buildAndroid/index.js +1 -1
  127. package/dist/native/buildAppAndroid.js +9 -0
  128. package/dist/native/buildAppIos.js +16 -1
  129. package/dist/native/buildErrorFormat.js +57 -0
  130. package/dist/native/buildIos/config.js +15 -1
  131. package/dist/native/buildIos/index.js +1 -1
  132. package/dist/native/buildIos/plugins.js +10 -1
  133. package/dist/native/iosnativeWebView/CoreLogic/Package.swift +36 -0
  134. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Camera/VideoStreamState.swift +1 -1
  135. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Camera/VideoStreamStateMachine.swift +6 -4
  136. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/BootTimingUtility.swift +3 -3
  137. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/FrameworkServerUtils.swift +14 -9
  138. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NetworkMonitor.swift +11 -9
  139. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NotificationHandlerProvider.swift +1 -1
  140. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/URLWhitelistManager.swift +7 -7
  141. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/AnyCodableTests.swift +154 -0
  142. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/BootTimingUtilityTests.swift +23 -5
  143. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/CatalystConstantsTests.swift +192 -0
  144. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/ConfigMappingTests.swift +1 -1
  145. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/FrameworkServerUtilsErrorPathTests.swift +106 -0
  146. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/FrameworkServerUtilsLoopbackTests.swift +243 -0
  147. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/FrameworkServerUtilsTests.swift +1 -1
  148. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/NetworkMonitorTests.swift +119 -0
  149. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/NotificationHandlerProviderTests.swift +59 -0
  150. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/NotificationHandlerTests.swift +1 -1
  151. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/URLWhitelistManagerTests.swift +1 -1
  152. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/VideoStreamStateMachineTests.swift +171 -0
  153. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/VideoStreamStateTests.swift +91 -0
  154. package/dist/native/iosnativeWebView/Package.swift +10 -9
  155. package/dist/native/iosnativeWebView/Sources/CatalystNotifications/LocalNotificationHandler.swift +7 -2
  156. package/dist/native/iosnativeWebView/Sources/CatalystNotifications/NotificationManager.swift +1 -2
  157. package/dist/native/iosnativeWebView/Sources/CatalystNotifications/PushNotificationHandler.swift +5 -4
  158. package/dist/native/iosnativeWebView/Sources/Core/Camera/CameraSessionManager.swift +1 -0
  159. package/dist/native/iosnativeWebView/Sources/Core/Camera/HoldController.swift +1 -0
  160. package/dist/native/iosnativeWebView/Sources/Core/Camera/NativeCameraManager.swift +6 -5
  161. package/dist/native/iosnativeWebView/Sources/Core/Camera/ZoomController.swift +1 -0
  162. package/dist/native/iosnativeWebView/Sources/Core/Plugins/PluginBridge.swift +1 -0
  163. package/dist/native/iosnativeWebView/Sources/Core/Utils/CacheManager.swift +31 -30
  164. package/dist/native/iosnativeWebView/Sources/Core/Utils/CameraTransportUtils.swift +2 -1
  165. package/dist/native/iosnativeWebView/Sources/Core/Utils/DeviceInfoUtils.swift +1 -1
  166. package/dist/native/iosnativeWebView/Sources/Core/Utils/FilePickerHandler.swift +22 -19
  167. package/dist/native/iosnativeWebView/Sources/Core/Utils/ImageHandler.swift +40 -39
  168. package/dist/native/iosnativeWebView/Sources/Core/Utils/PerfEventBuffer.swift +1 -0
  169. package/dist/native/iosnativeWebView/Sources/Core/Utils/ResourceURLProtocol.swift +15 -15
  170. package/dist/native/iosnativeWebView/Sources/Core/Utils/WebKitConfig.swift +4 -3
  171. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeCommandHandler.swift +6 -1
  172. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeDelegateHandler.swift +1 -0
  173. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeFileHandler.swift +2 -1
  174. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeJavaScriptInterface.swift +2 -1
  175. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeMessageValidator.swift +3 -5
  176. package/dist/native/iosnativeWebView/Sources/Core/WebView/NativeBridge.swift +20 -13
  177. package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashView.swift +6 -5
  178. package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashViewModel.swift +14 -13
  179. package/dist/native/iosnativeWebView/Sources/Core/WebView/TransitionManager.swift +3 -3
  180. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebView.swift +9 -8
  181. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewModel.swift +7 -6
  182. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +24 -25
  183. package/dist/native/iosnativeWebView/iosnativeWebView/AppDelegate.swift +6 -1
  184. package/dist/native/iosnativeWebView/iosnativeWebView/ContentView.swift +1 -0
  185. package/dist/native/iosnativeWebView/iosnativeWebView/iosnativeWebViewApp.swift +4 -0
  186. package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +2 -22
  187. package/dist/native/iosnativeWebView/iosnativeWebViewTests/BridgeMessageValidatorTests.swift +1 -0
  188. package/dist/native/iosnativeWebView/iosnativeWebViewTests/CacheManagerTests.swift +1 -0
  189. package/dist/native/iosnativeWebView/iosnativeWebViewTests/FilePickerHandlerTests.swift +2 -1
  190. package/dist/native/iosnativeWebView/iosnativeWebViewTests/NativeBridgeTests.swift +15 -9
  191. package/dist/native/iosnativeWebView/iosnativeWebViewTests/WebViewTests.swift +1 -0
  192. package/dist/native/setupEmulatorIos.js +2 -2
  193. package/dist/native/terminalProgress.js +17 -17
  194. package/dist/router/ClientRouter.d.ts +8 -0
  195. package/dist/router/ClientRouter.js +13 -11
  196. package/dist/router/ServerRouter.d.ts +13 -0
  197. package/dist/router/ServerRouter.js +19 -7
  198. package/dist/scripts/build.js +14 -2
  199. package/dist/scripts/loadEnvironmentVariables.js +3 -2
  200. package/dist/scripts/plugins.js +1 -1
  201. package/dist/scripts/preServerInit.js +49 -3
  202. package/dist/scripts/preflight.js +111 -0
  203. package/dist/scripts/scriptUtils.js +46 -1
  204. package/dist/scripts/serve.js +7 -3
  205. package/dist/scripts/start.js +8 -3
  206. package/dist/server/expressServer.d.ts +1 -0
  207. package/dist/server/expressServer.js +247 -271
  208. package/dist/server/manifestCache.d.ts +2 -0
  209. package/dist/server/manifestCache.js +25 -33
  210. package/dist/server/renderer/ChunkExtractor.d.ts +44 -0
  211. package/dist/server/renderer/ChunkExtractor.js +113 -125
  212. package/dist/server/renderer/document/Body.d.ts +21 -0
  213. package/dist/server/renderer/document/Body.jsx +45 -45
  214. package/dist/server/renderer/document/FastRefresh.d.ts +3 -0
  215. package/dist/server/renderer/document/FastRefresh.jsx +7 -13
  216. package/dist/server/renderer/document/Head.d.ts +20 -0
  217. package/dist/server/renderer/document/Head.jsx +32 -32
  218. package/dist/server/renderer/document/index.d.ts +2 -0
  219. package/dist/server/renderer/document/index.jsx +2 -2
  220. package/dist/server/renderer/extract.d.ts +67 -0
  221. package/dist/server/renderer/extract.js +92 -89
  222. package/dist/server/renderer/handler.d.ts +2 -0
  223. package/dist/server/renderer/handler.jsx +401 -404
  224. package/dist/server/renderer/index.d.ts +2 -0
  225. package/dist/server/renderer/index.js +5 -8
  226. package/dist/server/renderer/render.d.ts +35 -0
  227. package/dist/server/renderer/render.js +25 -32
  228. package/dist/server/utils/botDetectionMiddleware.d.ts +1 -0
  229. package/dist/server/utils/botDetectionMiddleware.js +33 -23
  230. package/dist/server/utils/cjsRequire.d.ts +8 -0
  231. package/dist/server/utils/cjsRequire.js +2 -2
  232. package/dist/server/utils/userAgentUtil.d.ts +7 -0
  233. package/dist/server/utils/userAgentUtil.js +68 -71
  234. package/dist/server/utils/validator.d.ts +31 -0
  235. package/dist/server/utils/validator.js +133 -158
  236. package/dist/vite/inject-cache-key-plugin.js +3 -27
  237. package/dist/vite/moduleAliases.js +36 -0
  238. package/dist/vite/node-loader.mjs +2 -29
  239. package/dist/vite/resolveDevServerConfig.js +4 -1
  240. package/dist/vite/vite.config.js +2 -29
  241. package/dist/web-router/components/MetaTag.d.ts +4 -0
  242. package/dist/web-router/components/MetaTag.jsx +26 -28
  243. package/dist/web-router/components/MetaTag.test.jsx +100 -0
  244. package/dist/web-router/components/RouterDataProvider.d.ts +96 -0
  245. package/dist/web-router/components/RouterDataProvider.jsx +260 -259
  246. package/dist/web-router/components/RouterDataProvider.server.test.jsx +98 -0
  247. package/dist/web-router/components/RouterDataProvider.test.jsx +310 -0
  248. package/dist/web-router/components/Split.d.ts +74 -0
  249. package/dist/web-router/components/Split.jsx +147 -156
  250. package/dist/web-router/components/Split.server.test.jsx +52 -0
  251. package/dist/web-router/components/Split.test.jsx +167 -0
  252. package/dist/web-router/components/SplitInview.d.ts +22 -0
  253. package/dist/web-router/components/SplitInview.jsx +78 -89
  254. package/dist/web-router/components/SplitInview.test.jsx +112 -0
  255. package/dist/web-router/components/SsrRequestContext.d.ts +20 -0
  256. package/dist/web-router/components/SsrRequestContext.jsx +17 -7
  257. package/dist/web-router/components/SsrRequestContext.test.jsx +53 -0
  258. package/dist/web-router/context.d.ts +15 -0
  259. package/dist/web-router/context.jsx +5 -5
  260. package/dist/web-router/context.test.jsx +10 -0
  261. package/dist/web-router/utils/metaDataUtils.d.ts +24 -0
  262. package/dist/web-router/utils/metaDataUtils.jsx +86 -86
  263. package/dist/web-router/utils/metaDataUtils.test.jsx +188 -0
  264. package/dist/web-router/vitest.setup.js +12 -0
  265. package/mcp_v2/knowledge-base.json +115 -17
  266. package/mcp_v2/mcp.js +141 -3
  267. package/mcp_v2/package-lock.json +2031 -0
  268. package/mcp_v2/package.json +13 -2
  269. package/mcp_v2/scripts/copyErrorsIndex.cjs +34 -0
  270. package/mcp_v2/test/errors.test.ts +123 -0
  271. package/mcp_v2/test/github.test.ts +177 -0
  272. package/mcp_v2/tools/errors.d.ts +20 -0
  273. package/mcp_v2/tools/errors.js +63 -0
  274. package/mcp_v2/tools/github.d.ts +41 -0
  275. package/mcp_v2/tools/github.js +231 -0
  276. package/mcp_v2/vitest.config.mjs +22 -0
  277. package/package.json +60 -11
  278. package/test/errors/docsDrift.test.ts +113 -0
  279. package/test/errors/index.test.ts +200 -0
  280. package/test/errors/registry.test.ts +108 -0
  281. package/test/scripts/preflight.test.ts +118 -0
  282. package/test/server/ChunkExtractor.test.ts +97 -0
  283. package/test/server/extract.test.ts +128 -0
  284. package/test/server/fixtures/template/server/document.jsx +19 -0
  285. package/test/server/fixtures/template/server/index.js +10 -0
  286. package/test/server/fixtures/template/src/js/containers/App/index.jsx +33 -0
  287. package/test/server/fixtures/template/src/js/routes/index.jsx +72 -0
  288. package/test/server/fixtures/template/src/js/routes/utils.jsx +39 -0
  289. package/test/server/fixtures/template/src/js/store/index.js +19 -0
  290. package/test/server/handler.assets.test.ts +330 -0
  291. package/test/server/handler.test.ts +208 -0
  292. package/test/server/manifestCache.test.ts +71 -0
  293. package/test/server/render.test.ts +71 -0
  294. package/test/server/scriptUtils.test.ts +103 -0
  295. package/test/server/userAgentUtil.test.ts +48 -0
  296. package/test/server/validator.test.ts +225 -0
  297. package/test/vite/resolveDevServerConfig.test.js +4 -1
  298. package/tsconfig.test.json +23 -0
  299. package/vitest.config.ts +93 -0
  300. package/dist/caching.js +0 -1
  301. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/DeviceInfoUtilsTest.kt +0 -187
  302. package/dist/native/bridge/standardizedHooks.js +0 -611
  303. package/dist/router.js +0 -1
  304. package/dist/scripts/validator.js +0 -149
  305. package/dist/web-router/hooks.jsx +0 -72
  306. package/dist/web-router/types/components/MetaTag.d.ts +0 -2
  307. package/dist/web-router/types/components/RouterDataProvider.d.ts +0 -95
  308. package/dist/web-router/types/context.d.ts +0 -14
  309. package/dist/web-router/types/hooks.d.ts +0 -1
  310. package/dist/web-router/types/index.d.ts +0 -3
  311. package/dist/web-router/types/utils/metaDataUtils.d.ts +0 -40
  312. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Constants/CatalystConstants.swift +0 -0
  313. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Constants/ConfigConstants.swift +0 -0
  314. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Notifications/NotificationModels.swift +0 -0
  315. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Protocols/NotificationHandlerProtocol.swift +0 -0
  316. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NullNotificationHandler.swift +0 -0
@@ -474,9 +474,9 @@
474
474
  {
475
475
  "section": "config_structure",
476
476
  "title": "Full config/config.json Schema",
477
- "content": "config/config.json contains all runtime config. Required keys (enforced by validator.js at startup \u2014 missing any = server crash): NODE_SERVER_HOSTNAME (string), NODE_SERVER_PORT (number), WEBPACK_DEV_SERVER_HOSTNAME (string), WEBPACK_DEV_SERVER_PORT (number), BUILD_OUTPUT_PATH (string, e.g. 'build'), PUBLIC_STATIC_ASSET_PATH (string, e.g. '/assets/'), PUBLIC_STATIC_ASSET_URL (string, CDN base URL), CLIENT_ENV_VARIABLES (array of env var names to expose to client bundle), ANALYZE_BUNDLE (boolean). Optional top-level keys: API_URL (string, app convention not enforced), WEBVIEW_CONFIG (object, required for native builds \u2014 contains splashScreen, appInfo, android, ios, etc.). Common mistake: CLIENT_ENV_KEYS is WRONG \u2014 the actual key is CLIENT_ENV_VARIABLES. Common mistake: splashScreen is NOT a top-level key \u2014 it lives inside WEBVIEW_CONFIG. Example: { NODE_SERVER_HOSTNAME: 'localhost', NODE_SERVER_PORT: 3000, WEBPACK_DEV_SERVER_HOSTNAME: 'localhost', WEBPACK_DEV_SERVER_PORT: 3001, BUILD_OUTPUT_PATH: 'build', PUBLIC_STATIC_ASSET_PATH: '/assets/', PUBLIC_STATIC_ASSET_URL: 'https://cdn.example.com', CLIENT_ENV_VARIABLES: ['API_URL'], ANALYZE_BUNDLE: false }",
477
+ "content": "config/config.json contains all runtime config. Required keys (enforced by validator.js at startup \u2014 missing any = server crash): NODE_SERVER_HOSTNAME (string), NODE_SERVER_PORT (number), BUILD_OUTPUT_PATH (string, e.g. 'build'), PUBLIC_STATIC_ASSET_PATH (string, e.g. '/assets/'), PUBLIC_STATIC_ASSET_URL (string, CDN base URL), CLIENT_ENV_VARIABLES (array of env var names to expose to client bundle). WEBPACK_DEV_SERVER_HOSTNAME, WEBPACK_DEV_SERVER_PORT, and ANALYZE_BUNDLE are no longer required or read \u2014 they are ignored if present. Optional top-level keys: API_URL (string, app convention not enforced), WEBVIEW_CONFIG (object, required for native builds \u2014 contains splashScreen, appInfo, android, ios, etc.). Common mistake: CLIENT_ENV_KEYS is WRONG \u2014 the actual key is CLIENT_ENV_VARIABLES. Common mistake: splashScreen is NOT a top-level key \u2014 it lives inside WEBVIEW_CONFIG. Example: { NODE_SERVER_HOSTNAME: 'localhost', NODE_SERVER_PORT: 3000, BUILD_OUTPUT_PATH: 'build', PUBLIC_STATIC_ASSET_PATH: '/assets/', PUBLIC_STATIC_ASSET_URL: 'https://cdn.example.com', CLIENT_ENV_VARIABLES: ['API_URL'] }",
478
478
  "layer": "Config",
479
- "source": "extracted:src/scripts/validator.js",
479
+ "source": "extracted:src/server/utils/validator.ts",
480
480
  "tags": ["config", "schema", "required-fields"]
481
481
  },
482
482
  {
@@ -570,10 +570,10 @@
570
570
  {
571
571
  "section": "server_structure",
572
572
  "title": "Required Server Files",
573
- "content": "Catalyst requires 3 specific files in server/: server/index.js (lifecycle hooks), server/server.js (Express middleware), server/document.js (HTML template). These are NOT optional. Missing any one = server startup fails. Any repo using custom Express, Next.js, CRA, or Vite must rebuild all 3 from scratch.",
573
+ "content": "Catalyst requires 3 specific files in server/: server/index.js (lifecycle hooks), server/server.js (Express middleware), server/document.js (HTML template). These are NOT optional. Missing any one = server startup fails. Any repo using custom Express, Next.js, CRA, or Vite must rebuild all 3 from scratch. From 1.0.0, a file that exists but lacks a required export is reported once at startup, naming the file and the export; the server still boots (log-and-continue) and the affected feature fails instead.",
574
574
  "layer": "Build",
575
575
  "source": "static",
576
- "tags": ["server", "required-files", "structure"]
576
+ "tags": ["server", "required-files", "structure", "1.0.0"]
577
577
  },
578
578
  {
579
579
  "section": "server_structure",
@@ -610,7 +610,7 @@
610
610
  {
611
611
  "section": "native_hooks",
612
612
  "title": "Native Hooks \u2014 Overview & Common Interface",
613
- "content": "All catalyst-core hooks share a standardized base interface: { data, loading, progress, error, isWeb, isNative, execute, clear, clearError }. isNative is true when running inside the native shell (Android/iOS WebView). isWeb is true on browser. All return SSR-safe stubs when window is undefined. Import from catalyst-core/hooks.\n\nWEB FALLBACK SYSTEM: Hooks that implement browser fallbacks additionally expose: { webFallbackActive: boolean, webFallbackDisabled: boolean, setWebFallback: (enabled: boolean) => void }. webFallbackActive=true means the hook is currently running its browser fallback (not native bridge). setWebFallback(false) disables the built-in fallback at runtime \u2014 React re-runs effects and cleans up side effects automatically (e.g. stops MediaStream, removes event listeners). webFallbackDisabled=true means the hook returned an inert no-op shape (all actions are no-ops, data/error/loading are null/false) \u2014 consumer must render its own UI.\n\nDYNAMIC PROP SYNC: The webFallback prop syncs dynamically after mount in all hooks (both useBaseHook consumers and thin-state hooks) via useEffect. Passing a new webFallback prop value re-evaluates webFallbackActive without remounting the component.\n\nRULES OF HOOKS: All hooks (useState, useRef, useCallback, useEffect) are always called unconditionally at top level, regardless of webFallbackActive/webFallbackDisabled. Branching only happens in return statements.\n\nHooks with web fallbacks: useCamera, useFilePicker, useHapticFeedback, useVideoStream, useDataProtection, useCameraPermission, useNetworkStatus, useSafeArea, useDeviceInfo.",
613
+ "content": "catalyst-core hooks fall into TWO CATEGORIES.\n\nSINGLE-ACTION HOOKS wrap exactly one native operation and share a standardized base interface: { data, loading, progress, error, isWeb, isNative, execute, clear, clearError }. execute takes the operation's own arguments — it NEVER takes an operation-name string. Each also exposes a domain alias for execute: useCamera->takePhoto, useFilePicker->pickFile, useIntent->openFile, useGoogleSignIn->signIn, useHapticFeedback->trigger/triggerHaptic, useCameraPermission->request.\n\nMULTI-ACTION HOOKS wrap several distinct operations, so their NAMED FUNCTIONS ARE THE API and they have NO execute: useNotification (scheduleLocal, cancelLocal, registerForPush, updateBadge, subscribeToTopic, unsubscribeFromTopic, getSubscribedTopics, requestPermission), useVideoStream (start, stop, sendCommand, flip), useDataProtection (setScreenSecure, clearWebData), useNativeTransition (navigate, cancelTransition). EXCEPTION: useNotification carries execute as a frozen-but-discouraged alias of scheduleLocal — do NOT copy that pattern for other multi-action hooks.\n\nREAD-ONLY HOOKS report ambient state with no action functions: useNetworkStatus, useDeviceInfo, useSafeArea.\n\nisNative is true when running inside the native shell (Android/iOS WebView). isWeb is true on browser. All return SSR-safe stubs when window is undefined. Import from catalyst-core/hooks.\n\nWEB FALLBACK SYSTEM: Hooks that implement browser fallbacks additionally expose: { webFallbackActive: boolean, webFallbackDisabled: boolean, setWebFallback: (enabled: boolean) => void }. webFallbackActive=true means the hook is currently running its browser fallback (not native bridge). setWebFallback(false) disables the built-in fallback at runtime \u2014 React re-runs effects and cleans up side effects automatically (e.g. stops MediaStream, removes event listeners). webFallbackDisabled=true means the hook returned an inert no-op shape (all actions are no-ops, data/error/loading are null/false) \u2014 consumer must render its own UI.\n\nDYNAMIC PROP SYNC: The webFallback prop syncs dynamically after mount in all hooks (both useBaseHook consumers and thin-state hooks) via useEffect. Passing a new webFallback prop value re-evaluates webFallbackActive without remounting the component.\n\nRULES OF HOOKS: All hooks (useState, useRef, useCallback, useEffect) are always called unconditionally at top level, regardless of webFallbackActive/webFallbackDisabled. Branching only happens in return statements.\n\nHooks with web fallbacks: useCamera, useFilePicker, useHapticFeedback, useVideoStream, useDataProtection, useCameraPermission, useNetworkStatus, useSafeArea, useDeviceInfo.",
614
614
  "layer": "Runtime",
615
615
  "source": "static",
616
616
  "tags": [
@@ -673,7 +673,7 @@
673
673
  {
674
674
  "section": "native_hooks",
675
675
  "title": "useNotification \u2014 return shape",
676
- "content": "useNotification() returns: { data, loading, progress, error, execute (=scheduleLocal), clear, clearError, isNative, isWeb, permissionStatus, pushToken, badges, lastNotification, subscribedTopics, scheduleLocal(config), schedule (alias for scheduleLocal), cancelLocal(id), registerForPush(), updateBadge(count), subscribeToTopic(topic), unsubscribeFromTopic(topic), getSubscribedTopics(), requestPermission() }. requestPermission() triggers native permission prompt (wraps requestNotificationPermission(), errors routed through base.handleNativeError). schedule is an alias for scheduleLocal. Requires WEBVIEW_CONFIG.notifications.enabled=true + Firebase files.",
676
+ "content": "useNotification() is a MULTI-ACTION hook — its named functions are the API. Returns: { data, loading, progress, error, clear, clearError, isNative, isWeb, permissionStatus, pushToken, badges, lastNotification, subscribedTopics, scheduleLocal(config), cancelLocal(id), registerForPush(), updateBadge(count), subscribeToTopic(topic), unsubscribeFromTopic(topic), getSubscribedTopics(), requestPermission() }. requestPermission() triggers native permission prompt (wraps requestNotificationPermission(), errors routed through base.handleNativeError).\n\nFROZEN-BUT-DISCOURAGED ALIASES: execute and schedule both alias scheduleLocal, kept for backward compatibility only. They are the sole exception among multi-action hooks and must NOT be treated as the pattern to copy — other multi-action hooks have no execute. Both aliases are removed at 2.0; write new code against scheduleLocal. Requires WEBVIEW_CONFIG.notifications.enabled=true + Firebase files.",
677
677
  "layer": "Runtime",
678
678
  "source": "static",
679
679
  "tags": ["native-hooks", "useNotification", "return-shape"]
@@ -729,7 +729,7 @@
729
729
  "title": "moduleAliases \u2014 Required Path Aliases in package.json",
730
730
  "content": "package.json must have a _moduleAliases key (used by module-alias package) with these 6 required entries (enforced by validator.js \u2014 missing any = server crash): @api -> api/ (WARNING: common bug \u2014 @api accidentally set to src/static/css in legacy repos, causes all API imports to break silently), @containers -> src/js/containers, @server -> server, @config -> config, @css -> src/static/css, @routes -> src/js/routes/. Additional aliases (@store, @utils, @components, etc.) are optional but recommended. Dollar-prefix aliases (, , , , ) are server-side only \u2014 do not import in client code. Restriction: alias names containing catalyst are reserved. Migration check: always verify @api points to the actual API module, not a static asset path.",
731
731
  "layer": "Config",
732
- "source": "extracted:src/scripts/validator.js",
732
+ "source": "extracted:src/server/utils/validator.ts",
733
733
  "tags": ["module-aliases", "package-json", "required", "config"]
734
734
  },
735
735
  {
@@ -1072,7 +1072,7 @@
1072
1072
  {
1073
1073
  "section": "native_hooks",
1074
1074
  "title": "Native Hooks \u2014 Full List and Standard Interface",
1075
- "content": "All hooks live in src/native/bridge/hooks/ (one file per domain). hooks.js is a 2-line re-export shim for backwards compat.\n\nSTANDARD BASE INTERFACE (useBaseHook consumers):\n{ data, loading, progress, error, isWeb, isNative, execute, clear, clearError,\n webFallbackActive, webFallbackDisabled, setWebFallback }\n\nprogress shape: { state, percentage, message, phase, transport, bytesLoaded, bytesTotal }\n\nENVIRONMENT DETECTION (useBaseHook):\nisNative = window.WebBridge && (window.NativeBridge || window.webkit?.messageHandlers?.NativeBridge)\nisWeb = !isNative\n\nWEB FALLBACK SYSTEM:\n- Hooks that support a browser fallback declare hasWebFallback: true in useBaseHook options.\n- webFallbackActive defaults to true on web when a fallback exists (unless webFallback prop === false).\n- webFallback prop syncs dynamically after mount \u2014 all hooks (useBaseHook consumers and thin-state hooks) update webFallbackActive via a useEffect that watches the prop.\n- setWebFallback(false) disables fallback at runtime \u2014 React re-runs effects + cleanups (e.g. stops MediaStream, removes event listeners).\n- When disabled: webFallbackDisabled=true, all action methods are no-ops, data/error/loading are null/false.\n- Thin-state hooks (useNetworkStatus, useSafeArea, useDeviceInfo, useCameraPermission) manage webFallback locally and expose isNative, isWeb, webFallbackActive, webFallbackDisabled, setWebFallback \u2014 same surface as useBaseHook consumers.\n- Rules of Hooks: all hooks are always called unconditionally at top level \u2014 early returns and conditional branches only in return statements, never around hook calls.\n\nFULL HOOK LIST:\nWith web fallback:\n- useCamera \u2014 capture photo. Web: <input type=file capture=environment>.\n- useFilePicker \u2014 pick file. Web: <input type=file>.\n- useHapticFeedback \u2014 haptic/vibration. Web: navigator.vibrate.\n- useVideoStream \u2014 live camera stream + sendCommand (zoom/torch/fps). Web: getUserMedia (requires secure context) with track.applyConstraints. Stream auto-stopped on mode change or unmount.\n- useDataProtection \u2014 setScreenSecure + clearWebData. Web: overlay div on visibilitychange + localStorage/sessionStorage/cookie/IndexedDB clear.\n- useCameraPermission \u2014 camera permission state + request(). Web: navigator.permissions API (query) + getUserMedia side-effect for request().\n- useNetworkStatus \u2014 online/type. Web: navigator.onLine (defaults true if not boolean) + online/offline events (live updates).\n- useSafeArea \u2014 inset pixels. Web: CSS env() vars.\n- useDeviceInfo \u2014 device metadata. Web: navigator/screen APIs.\n\nNo web fallback (native-only or scoped out):\n- useNotification \u2014 push notifications. Web: scoped out (Service Worker required, unreliable in WebView).\n- useNotificationPermission \u2014 notification permission.\n- useGoogleSignIn \u2014 Google sign-in via native.\n- useIntent \u2014 open file with external app.",
1075
+ "content": "All hooks live in src/native/bridge/hooks/ (one file per domain). hooks.js is a 2-line re-export shim for backwards compat.\n\nTWO CATEGORIES:\n- SINGLE-ACTION hooks wrap one operation and expose it as execute (plus a domain alias). execute takes the operation's arguments, never an operation-name string. These are: useCamera (takePhoto), useFilePicker (pickFile), useIntent (openFile), useGoogleSignIn (signIn), useHapticFeedback (trigger/triggerHaptic), useCameraPermission (request).\n- MULTI-ACTION hooks wrap several operations, so the named functions ARE the API and there is NO execute: useNotification, useVideoStream, useDataProtection, useNativeTransition. useNotification is the sole exception carrying execute as a frozen-but-discouraged alias of scheduleLocal — never copy that pattern.\n- READ-ONLY hooks have no action functions: useNetworkStatus, useDeviceInfo, useSafeArea.\n\nSTANDARD BASE INTERFACE (single-action useBaseHook consumers):\n{ data, loading, progress, error, isWeb, isNative, execute, clear, clearError,\n webFallbackActive, webFallbackDisabled, setWebFallback }\n\nMulti-action hooks share the same state keys (data, loading, error, isWeb, isNative, clear, clearError) but replace execute with their named functions.\n\nERROR SHAPE: error is a standard error object everywhere EXCEPT useDeviceInfo and useNetworkStatus, where it remains a plain string until 2.0. useNativeTransition and useSafeArea are error-exempt — they have no error key at all (transition failures self-heal into a plain navigate; safe-area insets always resolve to numeric defaults). useAI's shape is owned by the catalyst-ai package and is outside this contract.\n\nprogress shape: { state, percentage, message, phase, transport, bytesLoaded, bytesTotal }\n\nENVIRONMENT DETECTION (useBaseHook):\nisNative = window.WebBridge && (window.NativeBridge || window.webkit?.messageHandlers?.NativeBridge)\nisWeb = !isNative\n\nWEB FALLBACK SYSTEM:\n- Hooks that support a browser fallback declare hasWebFallback: true in useBaseHook options.\n- webFallbackActive defaults to true on web when a fallback exists (unless webFallback prop === false).\n- webFallback prop syncs dynamically after mount \u2014 all hooks (useBaseHook consumers and thin-state hooks) update webFallbackActive via a useEffect that watches the prop.\n- setWebFallback(false) disables fallback at runtime \u2014 React re-runs effects + cleanups (e.g. stops MediaStream, removes event listeners).\n- When disabled: webFallbackDisabled=true, all action methods are no-ops, data/error/loading are null/false.\n- Thin-state hooks (useNetworkStatus, useSafeArea, useDeviceInfo, useCameraPermission) manage webFallback locally and expose isNative, isWeb, webFallbackActive, webFallbackDisabled, setWebFallback \u2014 same surface as useBaseHook consumers.\n- Rules of Hooks: all hooks are always called unconditionally at top level \u2014 early returns and conditional branches only in return statements, never around hook calls.\n\nFULL HOOK LIST:\nWith web fallback:\n- useCamera \u2014 capture photo. Web: <input type=file capture=environment>.\n- useFilePicker \u2014 pick file. Web: <input type=file>.\n- useHapticFeedback \u2014 haptic/vibration. Web: navigator.vibrate.\n- useVideoStream \u2014 live camera stream + sendCommand (zoom/torch/fps). Web: getUserMedia (requires secure context) with track.applyConstraints. Stream auto-stopped on mode change or unmount.\n- useDataProtection \u2014 setScreenSecure + clearWebData. Web: overlay div on visibilitychange + localStorage/sessionStorage/cookie/IndexedDB clear.\n- useCameraPermission \u2014 camera permission state + request(). Web: navigator.permissions API (query) + getUserMedia side-effect for request().\n- useNetworkStatus \u2014 online/type. Web: navigator.onLine (defaults true if not boolean) + online/offline events (live updates).\n- useSafeArea \u2014 inset pixels. Web: CSS env() vars.\n- useDeviceInfo \u2014 device metadata. Web: navigator/screen APIs.\n\nNo web fallback (native-only or scoped out):\n- useNotification \u2014 push notifications. Web: scoped out (Service Worker required, unreliable in WebView).\n- useNotificationPermission \u2014 notification permission.\n- useGoogleSignIn \u2014 Google sign-in via native.\n- useIntent \u2014 open file with external app.\n- useNativeTransition \u2014 navigate with native slide/fade transitions. Web: CSS overlay on document.body driven by the same state machine (not a webFallback-prop hook).",
1076
1076
  "layer": "Bridge",
1077
1077
  "source": "static",
1078
1078
  "tags": [
@@ -1108,7 +1108,7 @@
1108
1108
  {
1109
1109
  "section": "native_hooks",
1110
1110
  "title": "useVideoStream \u2014 return shape",
1111
- "content": "useVideoStream(options?) returns: { isStreaming: boolean, streamState: { zoom, minZoom, maxZoom, torchOn, fpsMin, fpsMax }, error, isNative, webFallbackActive, webFallbackDisabled, setWebFallback, mediaStream: MediaStream|null (web only), viewfinderRef, start, stop, sendCommand, flip, clearError }.\n\nstart(options?) / stop() / flip() \u2014 stream lifecycle. sendCommand(type, value) controls live stream: 'zoom' (number \u2265 1.0), 'torch' (boolean), 'fps' ({ min, max }).\n\nOn native: sendCommand routes to WebBridge native commands. streamState updates only on native confirmation events (ON_TORCH_CHANGED, ON_ZOOM_CHANGED). On web fallback: sendCommand maps to track.applyConstraints().\n\nWEB FALLBACK (getUserMedia):\n- Requires secure context (HTTPS or localhost) \u2014 hook returns error if window.isSecureContext is false.\n- Requires navigator.mediaDevices.getUserMedia \u2014 hook returns error if unavailable.\n- mediaStream is returned directly (attach to <video> srcObject).\n- All tracks stopped automatically when setWebFallback(false) is called or component unmounts.\n- start()/stop()/flip() are async on web.\n- Rules of Hooks: all hooks (useState, useRef, useCallback, useEffect) declared unconditionally at top level \u2014 branching only in return statements.",
1111
+ "content": "useVideoStream(options?) is a MULTI-ACTION hook — start/stop/sendCommand/flip are the API and there is NO execute key. Returns: { isStreaming: boolean, streamState: { zoom, minZoom, maxZoom, torchOn, fpsMin, fpsMax }, loading, error, isNative, isWeb, webFallbackActive, webFallbackDisabled, setWebFallback, mediaStream: MediaStream|null (web only), viewfinderRef, start, stop, sendCommand, flip, clearError }.\n\nstart(options?) / stop() / flip() \u2014 stream lifecycle. sendCommand(type, value) controls live stream: 'zoom' (number \u2265 1.0), 'torch' (boolean), 'fps' ({ min, max }).\n\nOn native: sendCommand routes to WebBridge native commands. streamState updates only on native confirmation events (ON_TORCH_CHANGED, ON_ZOOM_CHANGED). On web fallback: sendCommand maps to track.applyConstraints().\n\nWEB FALLBACK (getUserMedia):\n- Requires secure context (HTTPS or localhost) \u2014 hook returns error if window.isSecureContext is false.\n- Requires navigator.mediaDevices.getUserMedia \u2014 hook returns error if unavailable.\n- mediaStream is returned directly (attach to <video> srcObject).\n- All tracks stopped automatically when setWebFallback(false) is called or component unmounts.\n- start()/stop()/flip() are async on web.\n- Rules of Hooks: all hooks (useState, useRef, useCallback, useEffect) declared unconditionally at top level \u2014 branching only in return statements.",
1112
1112
  "layer": "Runtime",
1113
1113
  "source": "static",
1114
1114
  "tags": [
@@ -1126,7 +1126,7 @@
1126
1126
  {
1127
1127
  "section": "native_hooks",
1128
1128
  "title": "useDeviceInfo \u2014 return shape",
1129
- "content": "useDeviceInfo() returns: { data: { model, manufacturer, platform, osVersion, screenWidth, screenHeight, screenDensity, appVersion, appInfo }, loading, error, isWeb, isNative, webFallbackActive, webFallbackDisabled, setWebFallback }.\n\nThis is a NEW React hook (did not exist before \u2014 only WebBridge.getDeviceInfo() imperative method existed). Use useDeviceInfo() in React components instead of calling WebBridge.getDeviceInfo() imperatively.\n\nOn native: wraps WebBridge.getDeviceInfo() promise, resolves on ON_DEVICE_INFO_SUCCESS callback.\n\nWEB FALLBACK: Populates device info from browser APIs:\n- platform: navigator.platform or 'web'\n- model/manufacturer: derived from navigator.userAgent (best-effort)\n- screenWidth/Height: screen.width/height\n- screenDensity: window.devicePixelRatio\n- appVersion/appInfo: null on web (no native app context)\n\nManages webFallback state locally (thin-state hook, not via useBaseHook).",
1129
+ "content": "useDeviceInfo() is a READ-ONLY hook (no action functions, no execute). Returns: { data: { model, manufacturer, platform, screenWidth, screenHeight, screenDensity, appInfo }, deviceInfo (=data, deprecated alias removed at 2.0), loading, error, isWeb, isNative, webFallbackActive, webFallbackDisabled, setWebFallback }. NOTE: error is a plain STRING here, not a standard error object — this stays a string until 2.0.\n\nThis is a NEW React hook (did not exist before \u2014 only WebBridge.getDeviceInfo() imperative method existed). Use useDeviceInfo() in React components instead of calling WebBridge.getDeviceInfo() imperatively.\n\nOn native: wraps WebBridge.getDeviceInfo() promise, resolves on ON_DEVICE_INFO_SUCCESS callback.\n\nWEB FALLBACK: Populates device info from browser APIs:\n- platform: navigator.platform or 'web'\n- model/manufacturer: derived from navigator.userAgent (best-effort)\n- screenWidth/Height: screen.width/height\n- screenDensity: window.devicePixelRatio\n- appVersion/appInfo: null on web (no native app context)\n\nManages webFallback state locally (thin-state hook, not via useBaseHook).",
1130
1130
  "layer": "Runtime",
1131
1131
  "source": "static",
1132
1132
  "tags": [
@@ -1142,7 +1142,7 @@
1142
1142
  {
1143
1143
  "section": "native_hooks",
1144
1144
  "title": "useDataProtection \u2014 return shape",
1145
- "content": "useDataProtection() returns: { data, loading, error, isWeb, isNative, execute, clear, clearError, setScreenSecure: (enabled: boolean) => void, clearWebData: () => void, isScreenSecure: boolean, webFallbackActive, webFallbackDisabled, setWebFallback }.\n\nsetScreenSecure(true/false) \u2014 enables/disables screen security (prevents screenshots/recents).\nclearWebData() \u2014 clears all web storage.\n\nOn native (Android): setScreenSecure sets FLAG_SECURE on WebView. clearWebData clears cookies, localStorage, WebView cache.\nOn native (iOS): setScreenSecure applies blur overlay. clearWebData uses WKWebsiteDataStore.\n\nWEB FALLBACK:\n- setScreenSecure(true): injects a fixed black overlay div (position:fixed, z-index:9999, 100vw/100vh) that shows/hides on document.visibilitychange \u2014 best-effort screenshot prevention (cannot block OS-level screenshots on web).\n- setScreenSecure(false): removes the overlay div and visibilitychange listener.\n- clearWebData(): clears localStorage, sessionStorage, all cookies (document.cookie), and all IndexedDB databases (indexedDB.databases() + deleteDatabase()).\n- setWebFallback(false): removes overlay + listener, returns inert no-op shape.",
1145
+ "content": "useDataProtection() is a MULTI-ACTION hook — its named functions are the API and there is NO execute key. Returns: { data, loading, progress, error, isWeb, isNative, clear, clearError, screenSecure: boolean, setScreenSecure: (enabled: boolean) => void, clearWebData: () => void, webFallbackActive, webFallbackDisabled, setWebFallback }. Note the state key is screenSecure, not isScreenSecure.\n\nsetScreenSecure(true/false) \u2014 enables/disables screen security (prevents screenshots/recents).\nclearWebData() \u2014 clears all web storage.\n\nOn native (Android): setScreenSecure sets FLAG_SECURE on WebView. clearWebData clears cookies, localStorage, WebView cache.\nOn native (iOS): setScreenSecure applies blur overlay. clearWebData uses WKWebsiteDataStore.\n\nWEB FALLBACK:\n- setScreenSecure(true): injects a fixed black overlay div (position:fixed, z-index:9999, 100vw/100vh) that shows/hides on document.visibilitychange \u2014 best-effort screenshot prevention (cannot block OS-level screenshots on web).\n- setScreenSecure(false): removes the overlay div and visibilitychange listener.\n- clearWebData(): clears localStorage, sessionStorage, all cookies (document.cookie), and all IndexedDB databases (indexedDB.databases() + deleteDatabase()).\n- setWebFallback(false): removes overlay + listener, returns inert no-op shape.",
1146
1146
  "layer": "Runtime",
1147
1147
  "source": "static",
1148
1148
  "tags": [
@@ -1157,6 +1157,41 @@
1157
1157
  "IndexedDB"
1158
1158
  ]
1159
1159
  },
1160
+ {
1161
+ "section": "native_hooks",
1162
+ "title": "useNativeTransition \u2014 return shape",
1163
+ "content": "useNativeTransition(defaults?) is a MULTI-ACTION hook \u2014 navigate/cancelTransition are the API and there is NO execute key. Returns: { navigate: (to, options?) => void, cancelTransition: () => void, transitioning: boolean, loading (=transitioning, deprecated alias direction is reversed here \u2014 loading is canonical, transitioning is the alias removed at 2.0), isNative, isWeb }.\n\nERROR-EXEMPT: there is NO error key. Transition failures self-heal \u2014 if native startTransition or commitTransition throws, the hook logs, clears transitioning, and falls through to a plain router navigate, so the user always lands on the destination route.\n\nnavigate(to, options) accepts standard react-router NavigateOptions plus: type ('slide'|'fade', default 'slide'), direction ('left'|'right'|'up'|'down', default 'left'), duration (ms, default 300), timeout (ms safety timer, default max(duration*3, 800)). The same options can be passed once to the hook as per-call defaults.\n\nNative path: startTransition (native snapshots screen) \u2192 router.navigate(to) \u2192 double-rAF \u2192 commitTransition (native animates overlay out). Native-side safety timer force-fades the overlay if commit never arrives (ON_TRANSITION_TIMEOUT).\n\nWeb path: CSS overlay div on document.body (position:fixed, z-index:9999, opacity transition) driven by the same state machine, with its own setTimeout safety net. Not a webFallback-prop hook \u2014 it has no webFallbackActive/webFallbackDisabled/setWebFallback keys.",
1164
+ "layer": "Runtime",
1165
+ "source": "static",
1166
+ "tags": [
1167
+ "native-hooks",
1168
+ "useNativeTransition",
1169
+ "return-shape",
1170
+ "navigation",
1171
+ "transition",
1172
+ "react-router",
1173
+ "multi-action",
1174
+ "error-exempt"
1175
+ ]
1176
+ },
1177
+ {
1178
+ "section": "native_hooks",
1179
+ "title": "Native hooks \u2014 aliases and deprecations (removed at 2.0)",
1180
+ "content": "Alias keys kept from earlier releases. Both names work and return the same value. ALL ALIASES ARE REMOVED AT 2.0 \u2014 write new code against the canonical key.\n\nALIAS -> CANONICAL:\n- isLoading -> loading (useCamera, useFilePicker, useIntent, useCameraPermission, useNotificationPermission)\n- transitioning -> loading (useNativeTransition)\n- deviceInfo -> data (useDeviceInfo)\n- permission -> data (useCameraPermission, useNotificationPermission)\n- request -> execute (useCameraPermission)\n- photo -> data (useCamera)\n- clearPhoto -> clear (useCamera)\n- clearFile -> clear (useFilePicker)\n- reset -> clear (useIntent)\n\nuseNotification.execute and useNotification.schedule both alias scheduleLocal. They are frozen for backward compatibility but DISCOURAGED, and they are explicitly NOT the pattern to copy for multi-action hooks \u2014 every other multi-action hook (useVideoStream, useDataProtection, useNativeTransition) has no execute key at all. With useNotification.execute and schedule, the list above is the complete set of 16 aliases as of 1.0.0; every one carries an @deprecated marker in the shipped type declarations.\n\nERROR SHAPE EXCEPTIONS: error is a standard error object everywhere EXCEPT useDeviceInfo and useNetworkStatus, where it stays a plain string until 2.0. useNativeTransition and useSafeArea are error-exempt \u2014 no error key at all. useAI's shape is owned by the catalyst-ai package and sits outside this contract.\n\nDUAL SURFACES: requestHapticFeedback and requestCameraPermission exist BOTH as catalyst-core/hooks exports and as WebBridge methods, with different defaults and return types. requestHapticFeedback: hooks export defaults to 'light' and resolves the raw status string; WebBridge.requestHapticFeedback defaults to 'VIRTUAL_KEY' and resolves the parsed result object. requestCameraPermission: hooks export takes no arguments and REJECTS on denial; WebBridge.requestCameraPermission takes a config object ({ includeDetails }) and RESOLVES with the denied status. The hooks exports are SSR-safe (return Promise<null> when window is undefined). The two surfaces are unified at 2.0.",
1181
+ "layer": "Runtime",
1182
+ "source": "static",
1183
+ "tags": [
1184
+ "native-hooks",
1185
+ "aliases",
1186
+ "deprecations",
1187
+ "2.0",
1188
+ "api-freeze",
1189
+ "error-shape",
1190
+ "WebBridge",
1191
+ "requestHapticFeedback",
1192
+ "requestCameraPermission"
1193
+ ]
1194
+ },
1160
1195
  {
1161
1196
  "section": "seo_metadata",
1162
1197
  "title": "Legacy 0.2.x Server-Side Meta Tags \u2014 setMetaData()",
@@ -1222,11 +1257,11 @@
1222
1257
  {
1223
1258
  "section": "framework_identity",
1224
1259
  "title": "Catalyst Runtime Generations",
1225
- "content": "Always determine the installed catalyst-core version before giving web runtime guidance. Catalyst 0.2.x is the legacy webpack generation and uses @tata1mg/router plus @loadable/component. Catalyst 0.3.x, beginning with 0.3.0-beta.1, is the Vite/ESM generation: router APIs are exported by catalyst-core and split()/hydrationReady() replace loadable APIs. Do not combine instructions from the two generations. If no version can be detected, ask which version the project targets.",
1260
+ "content": "Always determine the installed catalyst-core version before giving web runtime guidance. Catalyst 0.2.x is the legacy webpack generation and uses @tata1mg/router plus @loadable/component. Catalyst 0.3.x, beginning with 0.3.0-beta.1, is the Vite/ESM generation: router APIs are exported by catalyst-core and split()/hydrationReady() replace loadable APIs. Catalyst 1.0.0 is the API freeze (there is no 0.4.0 release); see 'Upgrading catalyst-core 0.3.x to 1.0.0'. Do not combine instructions from different generations. If no version can be detected, ask which version the project targets.",
1226
1261
  "layer": "Framework",
1227
1262
  "source": "static",
1228
- "tags": ["versions", "0.2.x", "0.3.x", "migration", "webpack", "vite"],
1229
- "github_files": ["packages/catalyst-core/package.json", "packages/catalyst-core/src/index.jsx"]
1263
+ "tags": ["versions", "0.2.x", "0.3.x", "1.0.0", "migration", "webpack", "vite"],
1264
+ "github_files": ["packages/catalyst-core/package.json", "packages/catalyst-core/src/index.tsx"]
1230
1265
  },
1231
1266
  {
1232
1267
  "section": "build_system",
@@ -1268,12 +1303,21 @@
1268
1303
  {
1269
1304
  "section": "routing",
1270
1305
  "title": "Catalyst 0.3.x Integrated Router",
1271
- "content": "Catalyst 0.3.x removes the @tata1mg/router package dependency. catalyst-core exports React Router APIs plus RouterDataProvider, MetaTag, routing data hooks, metadata utilities, split, and hydrationReady. Existing route arrays and preparedRoutes structure remain, but imports must move from @tata1mg/router to catalyst-core. Keeping both router packages can create duplicate runtime contracts and invalid React element errors.",
1306
+ "content": "Catalyst 0.3.x removes the @tata1mg/router package dependency. As of 1.0.0 (the API freeze), catalyst-core does NOT re-export React Router. Its root entry exports exactly eight names: RouterDataProvider, useCurrentRouteData, useRouterData, MetaTag, split, hydrationReady, Head, Body. There is no default export (split was previously also the default). React Router is a peerDependency (^7.18.2): install react-router in the application and import RouterProvider, Outlet, Link, useParams, useNavigate, useLocation, Navigate and every other router name from 'react-router' directly. Metadata utilities (getMetaData, mergeHeadElements, deleteHeadTagsByDataAttribute), RouterContext, serverDataFetcher and useNavigateWithTransition are no longer public. Existing route arrays and preparedRoutes structure remain unchanged. Keeping both router packages can create duplicate runtime contracts and invalid React element errors.",
1272
1307
  "layer": "Runtime",
1273
1308
  "source": "static",
1274
- "tags": ["0.3.x", "router", "react-router", "RouterDataProvider", "migration"],
1309
+ "tags": [
1310
+ "0.3.x",
1311
+ "1.0.0",
1312
+ "router",
1313
+ "react-router",
1314
+ "peer-dependency",
1315
+ "RouterDataProvider",
1316
+ "migration",
1317
+ "api-freeze"
1318
+ ],
1275
1319
  "github_files": [
1276
- "packages/catalyst-core/src/index.jsx",
1320
+ "packages/catalyst-core/src/index.tsx",
1277
1321
  "packages/catalyst-core/src/web-router/components/RouterDataProvider.jsx"
1278
1322
  ]
1279
1323
  },
@@ -1329,5 +1373,59 @@
1329
1373
  "layer": "Runtime",
1330
1374
  "source": "static",
1331
1375
  "tags": ["known-error", "0.3.x", "offline", "start", "build", "serve"]
1376
+ },
1377
+ {
1378
+ "section": "version_migration",
1379
+ "title": "Upgrading catalyst-core 0.3.x to 1.0.0",
1380
+ "content": "Upgrade path for an application on catalyst-core 0.3.0-beta.5. Older applications first move to 0.3.x (see 'Legacy 0.2.x Migration Phase 0' and 'Catalyst 0.3.x React Runtime Contract'). 1.0.0 is the API freeze; there is no 0.4.0 release. Do the steps in order.\n\n1. DEPENDENCIES: set catalyst-core to 1.0.0. Add react-router ^7.18.2 as an application dependency: it is now a peer dependency and the server throws at startup if it is missing or outside that range. Keep react and react-dom pinned to 19.0.0. TypeScript applications also need @types/react ^19.0.0.\n\n2. NODE: run node -v. catalyst-core 1.0.0 requires >=22.12; on Node 20, importing catalyst-core/hooks or catalyst-core/WebBridge fails with ERR_REQUIRE_ESM. If the runtime is older, stop and tell the user; do not change the project's Node pin yourself.\n\n3. IMPORTS: the root entry exports exactly RouterDataProvider, useCurrentRouteData, useRouterData, MetaTag, split, hydrationReady, Head, Body. Move every React Router name (Link, Outlet, RouterProvider, useParams, useNavigate, useLocation, Navigate, ...) from 'catalyst-core' to 'react-router'. Replace `import split from 'catalyst-core'` with `import { split } from 'catalyst-core'`; there is no default export. Replace imports from 'catalyst-core/document' with Head and Body from 'catalyst-core'. 'catalyst-core/caching' is removed with no replacement. RouterContext, serverDataFetcher, mergeHeadElements, deleteHeadTagsByDataAttribute, getMetaData, useNavigateWithTransition and sanitizeFilePickerOptions (catalyst-core/hooks) are internal with no replacement: if the application uses one, stop and tell the user instead of inventing a substitute.\n\n4. BUILD AND START: run the build, then start the server once. The build catches removed imports (they fail instead of resolving to undefined); startup catches the react-router range and the Node version.\n\n5. HOOK ERROR FIELDS (not caught by the build): hook errors are now CatalystError instances. Rename reads of error.action to error.suggestedAction and error.nativeError to error.cause; error.recoverable and error.timestamp no longer exist. error.code values are registry codes (RUNTIME-NATIVE-xxx) instead of names like PERMISSION_DENIED, so replace string-literal comparisons with ERROR_CODES from catalyst-core/errors (for example ERROR_CODES.RUNTIME_NATIVE_PERMISSION_DENIED). See 'CatalystError shape (1.0.0)'.\n\n6. OPTIONAL, NON-BREAKING: rename deprecated hook alias keys to the canonical ones (see 'Native hooks \u2014 aliases and deprecations'); aliases keep working until 2.0.\n\nUnchanged: route arrays, preparedRoutes, server hooks, config/config.json keys and module aliases. Full guide: docs/content/12-Migration/02-Version-Upgrades.md.",
1381
+ "layer": "Framework",
1382
+ "source": "static",
1383
+ "tags": [
1384
+ "migration",
1385
+ "migrate",
1386
+ "upgrade",
1387
+ "update",
1388
+ "bump",
1389
+ "1.0.0",
1390
+ "0.3.x",
1391
+ "breaking-changes",
1392
+ "api-freeze",
1393
+ "react-router",
1394
+ "peer-dependency",
1395
+ "peerDependency",
1396
+ "node"
1397
+ ],
1398
+ "github_files": ["docs/content/12-Migration/02-Version-Upgrades.md"]
1399
+ },
1400
+ {
1401
+ "section": "known_errors",
1402
+ "title": "ERR_REQUIRE_ESM importing catalyst-core/hooks on Node 20",
1403
+ "content": "Symptom: importing catalyst-core/hooks or catalyst-core/WebBridge throws ERR_REQUIRE_ESM on Node 20. Cause: the CommonJS native bridge require()s the ESM error registry, which older Node runtimes refuse without a flag; the package's engines field sets the supported minimum. Fix: run Node 22.12 or newer (catalyst-core 1.0.0 declares engines node >=22.12). Do not change the project's Node pin without telling the user.",
1404
+ "layer": "Runtime",
1405
+ "source": "static",
1406
+ "tags": ["1.0.0", "node", "22.12", "ERR_REQUIRE_ESM", "error", "hooks", "WebBridge"]
1407
+ },
1408
+ {
1409
+ "section": "native_hooks",
1410
+ "title": "CatalystError shape (1.0.0)",
1411
+ "content": "From 1.0.0, hook failures are CatalystError instances (class exported from catalyst-core/errors) with fields code, message, category, suggestedAction, docUrl, details and cause (the originating platform error). code is a registry code such as RUNTIME-NATIVE-001; compare against ERROR_CODES from catalyst-core/errors (ERROR_CODES.RUNTIME_NATIVE_PERMISSION_DENIED and so on), never against string literals.\n\nCHANGED FROM 0.3.x: the error used to be a plain object { code, category, message, details, recoverable, action, nativeError, timestamp } with code values like PERMISSION_DENIED. action is now suggestedAction, nativeError is now cause, recoverable and timestamp are gone, and code values changed. These renames are not caught by a build.\n\nCatalystError extends Error, so message is non-enumerable: JSON.stringify(error) omits it. Log error.message explicitly or use code and docUrl. Render error.message in JSX, never the error object. Exceptions to the object shape (string errors, error-exempt hooks) are listed under 'Native hooks \u2014 aliases and deprecations'.",
1412
+ "layer": "Runtime",
1413
+ "source": "static",
1414
+ "tags": [
1415
+ "1.0.0",
1416
+ "CatalystError",
1417
+ "error",
1418
+ "error-shape",
1419
+ "suggestedAction",
1420
+ "cause",
1421
+ "ERROR_CODES",
1422
+ "RUNTIME-NATIVE",
1423
+ "JSON.stringify",
1424
+ "native-hooks"
1425
+ ],
1426
+ "github_files": [
1427
+ "packages/catalyst-core/src/errors/index.js",
1428
+ "packages/catalyst-core/src/native/bridge/errors.ts"
1429
+ ]
1332
1430
  }
1333
1431
  ]
package/mcp_v2/mcp.js CHANGED
@@ -26,6 +26,7 @@ const tasks = require("./tools/tasks")
26
26
  const sync = require("./tools/sync")
27
27
  const knowledge = require("./tools/knowledge")
28
28
  const github = require("./tools/github")
29
+ const errors = require("./tools/errors")
29
30
 
30
31
  const MCP_DIR = __dirname
31
32
  const DB_PATH = path.join(MCP_DIR, "context.db")
@@ -121,6 +122,7 @@ tasks.init(db)
121
122
  sync.init(db)
122
123
  knowledge.init(db)
123
124
  github.init(projectInfo)
125
+ errors.init()
124
126
 
125
127
  // ── Intent classification (internal, not exposed as tool) ─────────────────────
126
128
 
@@ -131,9 +133,9 @@ const INTENT_PATTERNS = {
131
133
  guidance:
132
134
  /\b(what\s+is|what\s+are|how\s+does|how\s+do|explain|show\s+me|tell\s+me|hook|api|usage|example)\b/i,
133
135
  status: /status|done|complet|finish|check.*config|config.*check|what.*(left|remain|todo|next|pending)|how far|progress/i,
134
- // feedback = wants to raise an issue or discussion on GitHub
136
+ // feedback = wants to raise an issue, PR, or discussion on GitHub
135
137
  feedback:
136
- /\b(issue|bug\s+report|report\s+(a\s+)?bug|open\s+(an?\s+)?issue|create\s+(an?\s+)?issue|raise\s+(an?\s+)?issue|discussion|discuss|feature\s+request|proposal|suggest)\b/i,
138
+ /\b(issue|bug\s+report|report\s+(a\s+)?bug|open\s+(an?\s+)?issue|create\s+(an?\s+)?issue|raise\s+(an?\s+)?issue|pull\s*request|open\s+(a\s+)?pr|raise\s+(a\s+)?pr|create\s+(a\s+)?pr|discussion|discuss|feature\s+request|proposal|suggest)\b/i,
137
139
  debug: /error|fail|broken|not work|crash|issue|bug|why|wrong/i,
138
140
  build: /build|compile|webpack|vite|bundle|android|ios|platform/i,
139
141
  sync: /sync|update.*doc|fetch.*doc|latest.*doc/i,
@@ -148,7 +150,7 @@ const INTENT_NEXT_ACTION = {
148
150
  build: "answer_only — explain build flow. Do NOT call create_task_plan.",
149
151
  sync: "answer_only — sync complete. Do NOT call create_task_plan.",
150
152
  feedback:
151
- "answer_only — run the GitHub issue workflow and show the created issue URL or markdown fallback. Do NOT call create_task_plan.",
153
+ "answer_only — run the GitHub issue or PR workflow and show the created URL or markdown fallback. Do NOT call create_task_plan.",
152
154
  unknown: "answer_only — unclear intent. Return what you found. Do NOT call create_task_plan.",
153
155
  }
154
156
 
@@ -234,6 +236,21 @@ const TOOLS = [
234
236
  required: ["symptom"],
235
237
  },
236
238
  },
239
+ {
240
+ name: "explain_error",
241
+ description:
242
+ "Use when the developer has a specific catalyst-core error code (e.g. 'PREFLIGHT-001', 'BUNDLE-000') and wants to know what it means and how to fix it. Looks it up against the generated errors/ registry. If the code isn't catalyst-owned (e.g. a raw Vite/Rollup/Gradle/Xcode code), says so rather than guessing — those are not reinterpreted.",
243
+ inputSchema: {
244
+ type: "object",
245
+ properties: {
246
+ code: {
247
+ type: "string",
248
+ description: "The error code to explain, e.g. 'PREFLIGHT-001'.",
249
+ },
250
+ },
251
+ required: ["code"],
252
+ },
253
+ },
237
254
  {
238
255
  name: "check_config",
239
256
  description:
@@ -419,6 +436,7 @@ const TOOLS = [
419
436
  "seo_metadata",
420
437
  "transport_architecture",
421
438
  "webview_config",
439
+ "version_migration",
422
440
  ],
423
441
  description:
424
442
  "Optional: only pass when you are certain of the section. Omit if unsure — wrong section returns zero results.",
@@ -589,6 +607,124 @@ const TOOLS = [
589
607
  },
590
608
  },
591
609
  },
610
+ {
611
+ name: "create_github_pr",
612
+ description:
613
+ "Use when the developer wants to open, raise, create, or publish a GitHub pull request for catalyst-core. Resolves the head branch from the current git checkout (or the head arg), renders the PR body in the shape of the matching .github/PULL_REQUEST_TEMPLATE (fix / feature / chore) from the structured fields, appends the shared checklist, and previews with dry_run:true. Publishes via the GitHub API only when dry_run:false is explicitly passed, and only if the head branch is already pushed to origin (it does not push for you). Default to dry_run:true first. Intent: feedback.",
614
+ inputSchema: {
615
+ type: "object",
616
+ properties: {
617
+ dry_run: {
618
+ type: "boolean",
619
+ description:
620
+ "Defaults to true. When true, returns the rendered PR preview (title, head → base, change type, body, commits ahead of base) without publishing. Pass false only after explicit developer approval.",
621
+ },
622
+ change_type: {
623
+ type: "string",
624
+ enum: ["fix", "feature", "chore"],
625
+ description:
626
+ "Which PR template to render. Omit to infer from the title/summary. fix = bug fix, feature = new capability, chore = no behaviour change (deps, CI, refactor, docs).",
627
+ },
628
+ title: {
629
+ type: "string",
630
+ description:
631
+ "PR title. Use a conventional-commit prefix (fix: / feat: / chore:) to match the repo's commitlint config.",
632
+ },
633
+ body: {
634
+ type: "string",
635
+ description:
636
+ "Full PR description. Already-structured markdown (with ## headings) is preserved as-is; plain text and the structured fields below are laid out in the template's section order.",
637
+ },
638
+ summary: {
639
+ type: "string",
640
+ description:
641
+ "One or two sentences on what the PR changes. Used when body is not composed.",
642
+ },
643
+ head: {
644
+ type: "string",
645
+ description:
646
+ "Head branch. Defaults to the current branch (git rev-parse --abbrev-ref HEAD).",
647
+ },
648
+ base: {
649
+ type: "string",
650
+ description:
651
+ "Base branch to merge into. Defaults to 'main'. Pass the epic/story branch when the PR rides a stack (e.g. epic/329).",
652
+ },
653
+ draft: {
654
+ type: "boolean",
655
+ description: "Open as a draft PR. Defaults to true.",
656
+ },
657
+ closes_issue: {
658
+ type: ["string", "number"],
659
+ description:
660
+ "Issue number this PR closes. Renders a 'Closes #<n>' line at the top of the body.",
661
+ },
662
+ root_cause: {
663
+ type: "string",
664
+ description:
665
+ "fix: what was actually wrong, at the level of the offending line or contract.",
666
+ },
667
+ repro: {
668
+ type: "string",
669
+ description:
670
+ "fix: minimal steps or the failing input that triggered the bug before this change.",
671
+ },
672
+ fix: {
673
+ type: "string",
674
+ description: "fix: what this PR changes and why that closes the root cause.",
675
+ },
676
+ regression_test: {
677
+ type: "string",
678
+ description:
679
+ "fix: the test added that fails without the fix and passes with it, or why none was added.",
680
+ },
681
+ affected_error_codes: {
682
+ type: "string",
683
+ description:
684
+ "fix: CatalystError codes whose behaviour or wording this touches, or 'none'.",
685
+ },
686
+ what: {
687
+ type: "string",
688
+ description: "feature: the capability being added, in one or two sentences.",
689
+ },
690
+ why: {
691
+ type: "string",
692
+ description: "feature: the problem it solves or the use case it unblocks.",
693
+ },
694
+ new_error_codes: {
695
+ type: "string",
696
+ description:
697
+ "feature: new CatalystError code(s) introduced + confirmation errors/ docs were regenerated (node packages/catalyst-core/src/errors/generateDocs.js), or 'No new error codes'.",
698
+ },
699
+ coverage_delta: {
700
+ type: "string",
701
+ description: "feature: what is now covered that was not, and the delta if known.",
702
+ },
703
+ change_trigger: {
704
+ type: "string",
705
+ description:
706
+ "chore: what triggered this — dependency bump, CI tweak, flaky job, refactor, doc drift.",
707
+ },
708
+ change: {
709
+ type: "string",
710
+ description: "chore: what this PR does.",
711
+ },
712
+ no_behaviour_change: {
713
+ type: ["boolean", "string"],
714
+ description:
715
+ "chore: pass true to check the 'no runtime behaviour change' confirmation box in the rendered body.",
716
+ },
717
+ project_path: {
718
+ type: "string",
719
+ description: "Path to the catalyst repo root. Defaults to detected project root.",
720
+ },
721
+ _query: {
722
+ type: "string",
723
+ description: "Original user query for intent classification.",
724
+ },
725
+ },
726
+ },
727
+ },
592
728
  ]
593
729
 
594
730
  // ── Tool handler dispatch ─────────────────────────────────────────────────────
@@ -607,6 +743,8 @@ const TOOL_HANDLERS = {
607
743
  sync_knowledge_base: sync.handle_sync_knowledge_base,
608
744
  query_knowledge: knowledge.handle_query_knowledge,
609
745
  create_github_issue: github.handle_create_github_issue,
746
+ create_github_pr: github.handle_create_github_pr,
747
+ explain_error: errors.handle_explain_error,
610
748
  }
611
749
 
612
750
  // ── MCP JSON-RPC over stdio ───────────────────────────────────────────────────