@cat-factory/server 0.6.0

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 (338) hide show
  1. package/LICENSE +21 -0
  2. package/dist/agents/CompositeAgentExecutor.d.ts +39 -0
  3. package/dist/agents/CompositeAgentExecutor.d.ts.map +1 -0
  4. package/dist/agents/CompositeAgentExecutor.js +169 -0
  5. package/dist/agents/CompositeAgentExecutor.js.map +1 -0
  6. package/dist/agents/ContainerAgentExecutor.d.ts +235 -0
  7. package/dist/agents/ContainerAgentExecutor.d.ts.map +1 -0
  8. package/dist/agents/ContainerAgentExecutor.js +825 -0
  9. package/dist/agents/ContainerAgentExecutor.js.map +1 -0
  10. package/dist/agents/ContainerRepoBootstrapper.d.ts +78 -0
  11. package/dist/agents/ContainerRepoBootstrapper.d.ts.map +1 -0
  12. package/dist/agents/ContainerRepoBootstrapper.js +279 -0
  13. package/dist/agents/ContainerRepoBootstrapper.js.map +1 -0
  14. package/dist/agents/ModelRouter.d.ts +69 -0
  15. package/dist/agents/ModelRouter.d.ts.map +1 -0
  16. package/dist/agents/ModelRouter.js +84 -0
  17. package/dist/agents/ModelRouter.js.map +1 -0
  18. package/dist/agents/RunnerJobClient.d.ts +41 -0
  19. package/dist/agents/RunnerJobClient.d.ts.map +1 -0
  20. package/dist/agents/RunnerJobClient.js +43 -0
  21. package/dist/agents/RunnerJobClient.js.map +1 -0
  22. package/dist/agents/modelProviderResolver.d.ts +33 -0
  23. package/dist/agents/modelProviderResolver.d.ts.map +1 -0
  24. package/dist/agents/modelProviderResolver.js +48 -0
  25. package/dist/agents/modelProviderResolver.js.map +1 -0
  26. package/dist/agents/providerCapabilities.d.ts +22 -0
  27. package/dist/agents/providerCapabilities.d.ts.map +1 -0
  28. package/dist/agents/providerCapabilities.js +43 -0
  29. package/dist/agents/providerCapabilities.js.map +1 -0
  30. package/dist/agents/resolveRepoTarget.d.ts +33 -0
  31. package/dist/agents/resolveRepoTarget.d.ts.map +1 -0
  32. package/dist/agents/resolveRepoTarget.js +81 -0
  33. package/dist/agents/resolveRepoTarget.js.map +1 -0
  34. package/dist/app.d.ts +12 -0
  35. package/dist/app.d.ts.map +1 -0
  36. package/dist/app.js +102 -0
  37. package/dist/app.js.map +1 -0
  38. package/dist/auth/GitHubOAuth.d.ts +39 -0
  39. package/dist/auth/GitHubOAuth.d.ts.map +1 -0
  40. package/dist/auth/GitHubOAuth.js +90 -0
  41. package/dist/auth/GitHubOAuth.js.map +1 -0
  42. package/dist/auth/GoogleOAuth.d.ts +35 -0
  43. package/dist/auth/GoogleOAuth.d.ts.map +1 -0
  44. package/dist/auth/GoogleOAuth.js +66 -0
  45. package/dist/auth/GoogleOAuth.js.map +1 -0
  46. package/dist/auth/middleware.d.ts +15 -0
  47. package/dist/auth/middleware.d.ts.map +1 -0
  48. package/dist/auth/middleware.js +63 -0
  49. package/dist/auth/middleware.js.map +1 -0
  50. package/dist/auth/signing.d.ts +50 -0
  51. package/dist/auth/signing.d.ts.map +1 -0
  52. package/dist/auth/signing.js +96 -0
  53. package/dist/auth/signing.js.map +1 -0
  54. package/dist/auth/wsTicket.d.ts +34 -0
  55. package/dist/auth/wsTicket.d.ts.map +1 -0
  56. package/dist/auth/wsTicket.js +50 -0
  57. package/dist/auth/wsTicket.js.map +1 -0
  58. package/dist/config/types.d.ts +294 -0
  59. package/dist/config/types.d.ts.map +1 -0
  60. package/dist/config/types.js +2 -0
  61. package/dist/config/types.js.map +1 -0
  62. package/dist/config/url-safety.d.ts +8 -0
  63. package/dist/config/url-safety.d.ts.map +1 -0
  64. package/dist/config/url-safety.js +11 -0
  65. package/dist/config/url-safety.js.map +1 -0
  66. package/dist/containers/ContainerSessionService.d.ts +67 -0
  67. package/dist/containers/ContainerSessionService.d.ts.map +1 -0
  68. package/dist/containers/ContainerSessionService.js +44 -0
  69. package/dist/containers/ContainerSessionService.js.map +1 -0
  70. package/dist/crypto/WebCryptoPasswordHasher.d.ts +9 -0
  71. package/dist/crypto/WebCryptoPasswordHasher.d.ts.map +1 -0
  72. package/dist/crypto/WebCryptoPasswordHasher.js +67 -0
  73. package/dist/crypto/WebCryptoPasswordHasher.js.map +1 -0
  74. package/dist/crypto/WebCryptoPersonalSecretCipher.d.ts +6 -0
  75. package/dist/crypto/WebCryptoPersonalSecretCipher.d.ts.map +1 -0
  76. package/dist/crypto/WebCryptoPersonalSecretCipher.js +57 -0
  77. package/dist/crypto/WebCryptoPersonalSecretCipher.js.map +1 -0
  78. package/dist/crypto/WebCryptoSecretCipher.d.ts +23 -0
  79. package/dist/crypto/WebCryptoSecretCipher.d.ts.map +1 -0
  80. package/dist/crypto/WebCryptoSecretCipher.js +60 -0
  81. package/dist/crypto/WebCryptoSecretCipher.js.map +1 -0
  82. package/dist/crypto/encoding.d.ts +14 -0
  83. package/dist/crypto/encoding.d.ts.map +1 -0
  84. package/dist/crypto/encoding.js +58 -0
  85. package/dist/crypto/encoding.js.map +1 -0
  86. package/dist/events/FanOutEventPublisher.d.ts +32 -0
  87. package/dist/events/FanOutEventPublisher.d.ts.map +1 -0
  88. package/dist/events/FanOutEventPublisher.js +76 -0
  89. package/dist/events/FanOutEventPublisher.js.map +1 -0
  90. package/dist/events/InAppNotificationChannel.d.ts +20 -0
  91. package/dist/events/InAppNotificationChannel.d.ts.map +1 -0
  92. package/dist/events/InAppNotificationChannel.js +23 -0
  93. package/dist/events/InAppNotificationChannel.js.map +1 -0
  94. package/dist/github/FetchGitHubClient.d.ts +72 -0
  95. package/dist/github/FetchGitHubClient.d.ts.map +1 -0
  96. package/dist/github/FetchGitHubClient.js +485 -0
  97. package/dist/github/FetchGitHubClient.js.map +1 -0
  98. package/dist/github/FetchGitHubProvisioningClient.d.ts +13 -0
  99. package/dist/github/FetchGitHubProvisioningClient.d.ts.map +1 -0
  100. package/dist/github/FetchGitHubProvisioningClient.js +59 -0
  101. package/dist/github/FetchGitHubProvisioningClient.js.map +1 -0
  102. package/dist/github/GitHubAppAuth.d.ts +30 -0
  103. package/dist/github/GitHubAppAuth.d.ts.map +1 -0
  104. package/dist/github/GitHubAppAuth.js +95 -0
  105. package/dist/github/GitHubAppAuth.js.map +1 -0
  106. package/dist/github/GitHubAppRegistry.d.ts +57 -0
  107. package/dist/github/GitHubAppRegistry.d.ts.map +1 -0
  108. package/dist/github/GitHubAppRegistry.js +51 -0
  109. package/dist/github/GitHubAppRegistry.js.map +1 -0
  110. package/dist/github/GitHubCiStatusProvider.d.ts +21 -0
  111. package/dist/github/GitHubCiStatusProvider.d.ts.map +1 -0
  112. package/dist/github/GitHubCiStatusProvider.js +39 -0
  113. package/dist/github/GitHubCiStatusProvider.js.map +1 -0
  114. package/dist/github/GitHubMergeabilityProvider.d.ts +26 -0
  115. package/dist/github/GitHubMergeabilityProvider.d.ts.map +1 -0
  116. package/dist/github/GitHubMergeabilityProvider.js +38 -0
  117. package/dist/github/GitHubMergeabilityProvider.js.map +1 -0
  118. package/dist/github/GitHubPullRequestMerger.d.ts +23 -0
  119. package/dist/github/GitHubPullRequestMerger.d.ts.map +1 -0
  120. package/dist/github/GitHubPullRequestMerger.js +38 -0
  121. package/dist/github/GitHubPullRequestMerger.js.map +1 -0
  122. package/dist/github/WebCryptoWebhookVerifier.d.ts +9 -0
  123. package/dist/github/WebCryptoWebhookVerifier.d.ts.map +1 -0
  124. package/dist/github/WebCryptoWebhookVerifier.js +40 -0
  125. package/dist/github/WebCryptoWebhookVerifier.js.map +1 -0
  126. package/dist/github/ensureWorkBranch.d.ts +26 -0
  127. package/dist/github/ensureWorkBranch.d.ts.map +1 -0
  128. package/dist/github/ensureWorkBranch.js +97 -0
  129. package/dist/github/ensureWorkBranch.js.map +1 -0
  130. package/dist/github/state.d.ts +19 -0
  131. package/dist/github/state.d.ts.map +1 -0
  132. package/dist/github/state.js +55 -0
  133. package/dist/github/state.js.map +1 -0
  134. package/dist/http/authGate.d.ts +21 -0
  135. package/dist/http/authGate.d.ts.map +1 -0
  136. package/dist/http/authGate.js +77 -0
  137. package/dist/http/authGate.js.map +1 -0
  138. package/dist/http/cors.d.ts +13 -0
  139. package/dist/http/cors.d.ts.map +1 -0
  140. package/dist/http/cors.js +30 -0
  141. package/dist/http/cors.js.map +1 -0
  142. package/dist/http/env.d.ts +68 -0
  143. package/dist/http/env.d.ts.map +1 -0
  144. package/dist/http/env.js +2 -0
  145. package/dist/http/env.js.map +1 -0
  146. package/dist/http/errorHandler.d.ts +4 -0
  147. package/dist/http/errorHandler.d.ts.map +1 -0
  148. package/dist/http/errorHandler.js +33 -0
  149. package/dist/http/errorHandler.js.map +1 -0
  150. package/dist/http/params.d.ts +8 -0
  151. package/dist/http/params.d.ts.map +1 -0
  152. package/dist/http/params.js +13 -0
  153. package/dist/http/params.js.map +1 -0
  154. package/dist/http/validation.d.ts +12 -0
  155. package/dist/http/validation.d.ts.map +1 -0
  156. package/dist/http/validation.js +21 -0
  157. package/dist/http/validation.js.map +1 -0
  158. package/dist/index.d.ts +46 -0
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +63 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/modules/accounts/AccountController.d.ts +10 -0
  163. package/dist/modules/accounts/AccountController.d.ts.map +1 -0
  164. package/dist/modules/accounts/AccountController.js +197 -0
  165. package/dist/modules/accounts/AccountController.js.map +1 -0
  166. package/dist/modules/agentRuns/AgentRunController.d.ts +10 -0
  167. package/dist/modules/agentRuns/AgentRunController.d.ts.map +1 -0
  168. package/dist/modules/agentRuns/AgentRunController.js +65 -0
  169. package/dist/modules/agentRuns/AgentRunController.js.map +1 -0
  170. package/dist/modules/auth/AuthController.d.ts +12 -0
  171. package/dist/modules/auth/AuthController.d.ts.map +1 -0
  172. package/dist/modules/auth/AuthController.js +457 -0
  173. package/dist/modules/auth/AuthController.js.map +1 -0
  174. package/dist/modules/board/BoardController.d.ts +8 -0
  175. package/dist/modules/board/BoardController.d.ts.map +1 -0
  176. package/dist/modules/board/BoardController.js +89 -0
  177. package/dist/modules/board/BoardController.js.map +1 -0
  178. package/dist/modules/boardScan/BoardScanController.d.ts +10 -0
  179. package/dist/modules/boardScan/BoardScanController.d.ts.map +1 -0
  180. package/dist/modules/boardScan/BoardScanController.js +53 -0
  181. package/dist/modules/boardScan/BoardScanController.js.map +1 -0
  182. package/dist/modules/bootstrap/BootstrapController.d.ts +10 -0
  183. package/dist/modules/bootstrap/BootstrapController.d.ts.map +1 -0
  184. package/dist/modules/bootstrap/BootstrapController.js +75 -0
  185. package/dist/modules/bootstrap/BootstrapController.js.map +1 -0
  186. package/dist/modules/clarity/ClarityReviewController.d.ts +11 -0
  187. package/dist/modules/clarity/ClarityReviewController.d.ts.map +1 -0
  188. package/dist/modules/clarity/ClarityReviewController.js +97 -0
  189. package/dist/modules/clarity/ClarityReviewController.js.map +1 -0
  190. package/dist/modules/consensus/ConsensusController.d.ts +12 -0
  191. package/dist/modules/consensus/ConsensusController.d.ts.map +1 -0
  192. package/dist/modules/consensus/ConsensusController.js +23 -0
  193. package/dist/modules/consensus/ConsensusController.js.map +1 -0
  194. package/dist/modules/documents/DocumentSourceController.d.ts +10 -0
  195. package/dist/modules/documents/DocumentSourceController.d.ts.map +1 -0
  196. package/dist/modules/documents/DocumentSourceController.js +116 -0
  197. package/dist/modules/documents/DocumentSourceController.js.map +1 -0
  198. package/dist/modules/environments/EnvironmentController.d.ts +10 -0
  199. package/dist/modules/environments/EnvironmentController.d.ts.map +1 -0
  200. package/dist/modules/environments/EnvironmentController.js +95 -0
  201. package/dist/modules/environments/EnvironmentController.js.map +1 -0
  202. package/dist/modules/events/EventsController.d.ts +26 -0
  203. package/dist/modules/events/EventsController.d.ts.map +1 -0
  204. package/dist/modules/events/EventsController.js +56 -0
  205. package/dist/modules/events/EventsController.js.map +1 -0
  206. package/dist/modules/execution/ExecutionController.d.ts +10 -0
  207. package/dist/modules/execution/ExecutionController.d.ts.map +1 -0
  208. package/dist/modules/execution/ExecutionController.js +156 -0
  209. package/dist/modules/execution/ExecutionController.js.map +1 -0
  210. package/dist/modules/fragmentLibrary/FragmentLibraryController.d.ts +14 -0
  211. package/dist/modules/fragmentLibrary/FragmentLibraryController.d.ts.map +1 -0
  212. package/dist/modules/fragmentLibrary/FragmentLibraryController.js +128 -0
  213. package/dist/modules/fragmentLibrary/FragmentLibraryController.js.map +1 -0
  214. package/dist/modules/github/GitHubController.d.ts +12 -0
  215. package/dist/modules/github/GitHubController.d.ts.map +1 -0
  216. package/dist/modules/github/GitHubController.js +234 -0
  217. package/dist/modules/github/GitHubController.js.map +1 -0
  218. package/dist/modules/github/GitHubWebhookController.d.ts +13 -0
  219. package/dist/modules/github/GitHubWebhookController.d.ts.map +1 -0
  220. package/dist/modules/github/GitHubWebhookController.js +74 -0
  221. package/dist/modules/github/GitHubWebhookController.js.map +1 -0
  222. package/dist/modules/llmProxy/LlmProxyController.d.ts +18 -0
  223. package/dist/modules/llmProxy/LlmProxyController.d.ts.map +1 -0
  224. package/dist/modules/llmProxy/LlmProxyController.js +567 -0
  225. package/dist/modules/llmProxy/LlmProxyController.js.map +1 -0
  226. package/dist/modules/localModels/LocalModelEndpointController.d.ts +4 -0
  227. package/dist/modules/localModels/LocalModelEndpointController.d.ts.map +1 -0
  228. package/dist/modules/localModels/LocalModelEndpointController.js +58 -0
  229. package/dist/modules/localModels/LocalModelEndpointController.js.map +1 -0
  230. package/dist/modules/merge/MergePresetController.d.ts +9 -0
  231. package/dist/modules/merge/MergePresetController.d.ts.map +1 -0
  232. package/dist/modules/merge/MergePresetController.js +46 -0
  233. package/dist/modules/merge/MergePresetController.js.map +1 -0
  234. package/dist/modules/modelDefaults/ModelDefaultsController.d.ts +9 -0
  235. package/dist/modules/modelDefaults/ModelDefaultsController.d.ts.map +1 -0
  236. package/dist/modules/modelDefaults/ModelDefaultsController.js +32 -0
  237. package/dist/modules/modelDefaults/ModelDefaultsController.js.map +1 -0
  238. package/dist/modules/models/ModelController.d.ts +11 -0
  239. package/dist/modules/models/ModelController.d.ts.map +1 -0
  240. package/dist/modules/models/ModelController.js +38 -0
  241. package/dist/modules/models/ModelController.js.map +1 -0
  242. package/dist/modules/notifications/NotificationController.d.ts +13 -0
  243. package/dist/modules/notifications/NotificationController.d.ts.map +1 -0
  244. package/dist/modules/notifications/NotificationController.js +67 -0
  245. package/dist/modules/notifications/NotificationController.js.map +1 -0
  246. package/dist/modules/pipelines/PipelineController.d.ts +5 -0
  247. package/dist/modules/pipelines/PipelineController.d.ts.map +1 -0
  248. package/dist/modules/pipelines/PipelineController.js +46 -0
  249. package/dist/modules/pipelines/PipelineController.js.map +1 -0
  250. package/dist/modules/promptFragments/PromptFragmentController.d.ts +11 -0
  251. package/dist/modules/promptFragments/PromptFragmentController.d.ts.map +1 -0
  252. package/dist/modules/promptFragments/PromptFragmentController.js +18 -0
  253. package/dist/modules/promptFragments/PromptFragmentController.js.map +1 -0
  254. package/dist/modules/providers/ApiKeyController.d.ts +13 -0
  255. package/dist/modules/providers/ApiKeyController.d.ts.map +1 -0
  256. package/dist/modules/providers/ApiKeyController.js +98 -0
  257. package/dist/modules/providers/ApiKeyController.js.map +1 -0
  258. package/dist/modules/providers/PersonalSubscriptionController.d.ts +4 -0
  259. package/dist/modules/providers/PersonalSubscriptionController.d.ts.map +1 -0
  260. package/dist/modules/providers/PersonalSubscriptionController.js +48 -0
  261. package/dist/modules/providers/PersonalSubscriptionController.js.map +1 -0
  262. package/dist/modules/providers/VendorCredentialController.d.ts +4 -0
  263. package/dist/modules/providers/VendorCredentialController.d.ts.map +1 -0
  264. package/dist/modules/providers/VendorCredentialController.js +55 -0
  265. package/dist/modules/providers/VendorCredentialController.js.map +1 -0
  266. package/dist/modules/providers/personalCredentialGate.d.ts +34 -0
  267. package/dist/modules/providers/personalCredentialGate.d.ts.map +1 -0
  268. package/dist/modules/providers/personalCredentialGate.js +106 -0
  269. package/dist/modules/providers/personalCredentialGate.js.map +1 -0
  270. package/dist/modules/recurring/RecurringPipelineController.d.ts +8 -0
  271. package/dist/modules/recurring/RecurringPipelineController.d.ts.map +1 -0
  272. package/dist/modules/recurring/RecurringPipelineController.js +58 -0
  273. package/dist/modules/recurring/RecurringPipelineController.js.map +1 -0
  274. package/dist/modules/recurring/TrackerSettingsController.d.ts +8 -0
  275. package/dist/modules/recurring/TrackerSettingsController.d.ts.map +1 -0
  276. package/dist/modules/recurring/TrackerSettingsController.js +30 -0
  277. package/dist/modules/recurring/TrackerSettingsController.js.map +1 -0
  278. package/dist/modules/releaseHealth/ReleaseHealthController.d.ts +9 -0
  279. package/dist/modules/releaseHealth/ReleaseHealthController.d.ts.map +1 -0
  280. package/dist/modules/releaseHealth/ReleaseHealthController.js +58 -0
  281. package/dist/modules/releaseHealth/ReleaseHealthController.js.map +1 -0
  282. package/dist/modules/requirements/RequirementReviewController.d.ts +12 -0
  283. package/dist/modules/requirements/RequirementReviewController.d.ts.map +1 -0
  284. package/dist/modules/requirements/RequirementReviewController.js +107 -0
  285. package/dist/modules/requirements/RequirementReviewController.js.map +1 -0
  286. package/dist/modules/runners/RunnerPoolController.d.ts +10 -0
  287. package/dist/modules/runners/RunnerPoolController.d.ts.map +1 -0
  288. package/dist/modules/runners/RunnerPoolController.js +52 -0
  289. package/dist/modules/runners/RunnerPoolController.js.map +1 -0
  290. package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.d.ts +9 -0
  291. package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.d.ts.map +1 -0
  292. package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.js +32 -0
  293. package/dist/modules/serviceFragmentDefaults/ServiceFragmentDefaultsController.js.map +1 -0
  294. package/dist/modules/services/ServiceMountController.d.ts +11 -0
  295. package/dist/modules/services/ServiceMountController.d.ts.map +1 -0
  296. package/dist/modules/services/ServiceMountController.js +64 -0
  297. package/dist/modules/services/ServiceMountController.js.map +1 -0
  298. package/dist/modules/settings/WorkspaceSettingsController.d.ts +9 -0
  299. package/dist/modules/settings/WorkspaceSettingsController.d.ts.map +1 -0
  300. package/dist/modules/settings/WorkspaceSettingsController.js +32 -0
  301. package/dist/modules/settings/WorkspaceSettingsController.js.map +1 -0
  302. package/dist/modules/slack/SlackController.d.ts +17 -0
  303. package/dist/modules/slack/SlackController.d.ts.map +1 -0
  304. package/dist/modules/slack/SlackController.js +135 -0
  305. package/dist/modules/slack/SlackController.js.map +1 -0
  306. package/dist/modules/tasks/TaskSourceController.d.ts +9 -0
  307. package/dist/modules/tasks/TaskSourceController.d.ts.map +1 -0
  308. package/dist/modules/tasks/TaskSourceController.js +103 -0
  309. package/dist/modules/tasks/TaskSourceController.js.map +1 -0
  310. package/dist/modules/webSearch/WebSearchProxyController.d.ts +4 -0
  311. package/dist/modules/webSearch/WebSearchProxyController.d.ts.map +1 -0
  312. package/dist/modules/webSearch/WebSearchProxyController.js +78 -0
  313. package/dist/modules/webSearch/WebSearchProxyController.js.map +1 -0
  314. package/dist/modules/webSearch/upstreams.d.ts +50 -0
  315. package/dist/modules/webSearch/upstreams.d.ts.map +1 -0
  316. package/dist/modules/webSearch/upstreams.js +107 -0
  317. package/dist/modules/webSearch/upstreams.js.map +1 -0
  318. package/dist/modules/workspaces/WorkspaceController.d.ts +5 -0
  319. package/dist/modules/workspaces/WorkspaceController.d.ts.map +1 -0
  320. package/dist/modules/workspaces/WorkspaceController.js +167 -0
  321. package/dist/modules/workspaces/WorkspaceController.js.map +1 -0
  322. package/dist/observability/logger.d.ts +9 -0
  323. package/dist/observability/logger.d.ts.map +1 -0
  324. package/dist/observability/logger.js +39 -0
  325. package/dist/observability/logger.js.map +1 -0
  326. package/dist/persistence/mappers.d.ts +101 -0
  327. package/dist/persistence/mappers.d.ts.map +1 -0
  328. package/dist/persistence/mappers.js +260 -0
  329. package/dist/persistence/mappers.js.map +1 -0
  330. package/dist/runtime/escalateNotifications.d.ts +12 -0
  331. package/dist/runtime/escalateNotifications.d.ts.map +1 -0
  332. package/dist/runtime/escalateNotifications.js +25 -0
  333. package/dist/runtime/escalateNotifications.js.map +1 -0
  334. package/dist/runtime/gateways.d.ts +159 -0
  335. package/dist/runtime/gateways.d.ts.map +1 -0
  336. package/dist/runtime/gateways.js +2 -0
  337. package/dist/runtime/gateways.js.map +1 -0
  338. package/package.json +44 -0
@@ -0,0 +1,95 @@
1
+ import { base64url, pkcs8PemToDer } from '../crypto/encoding.js';
2
+ // GitHub App authentication, implemented entirely on Web Crypto (`crypto.subtle`)
3
+ // so it runs in a plain Workers isolate without Node `crypto` — and identically
4
+ // under Node, where `crypto.subtle` is a global too:
5
+ // - the *app JWT* (RS256) authenticates as the App itself, used to mint tokens
6
+ // and read installation metadata;
7
+ // - *installation tokens* (short-lived, ~1h) authenticate as a specific
8
+ // installation for repo reads/writes, cached in the installation row.
9
+ //
10
+ // The signing key is imported once and reused. Tokens are treated as expired a
11
+ // few minutes early to avoid using one that lapses mid-request; a cache miss is
12
+ // harmless since a fresh token is cheaply minted from the app JWT.
13
+ const TOKEN_SKEW_MS = 5 * 60 * 1000;
14
+ const USER_AGENT = 'cat-factory';
15
+ const API_VERSION = '2022-11-28';
16
+ /**
17
+ * Installation tokens (live ~1h repo read/write credentials) are cached IN
18
+ * MEMORY, per isolate/process — never persisted. Persisting them put a plaintext
19
+ * credential at rest (readable from any DB dump / console / SQLi elsewhere); an
20
+ * in-memory cache keeps the hit rate high for a warm process while the token never
21
+ * outlives it. A cache miss just re-mints cheaply from the app JWT. The
22
+ * module-level map intentionally persists across requests within the same process.
23
+ */
24
+ const tokenCache = new Map();
25
+ export class GitHubAppAuth {
26
+ deps;
27
+ keyPromise;
28
+ constructor(deps) {
29
+ this.deps = deps;
30
+ }
31
+ /** A short-lived RS256 JWT authenticating as the App. */
32
+ async appJwt() {
33
+ const key = await this.importKey();
34
+ const nowSec = Math.floor(this.deps.clock.now() / 1000);
35
+ const header = { alg: 'RS256', typ: 'JWT' };
36
+ // `iat` is backdated 60s to tolerate clock skew; GitHub caps `exp` at 10min.
37
+ const payload = { iat: nowSec - 60, exp: nowSec + 9 * 60, iss: this.deps.appId };
38
+ const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(payload))}`;
39
+ const signature = await crypto.subtle.sign({ name: 'RSASSA-PKCS1-v1_5' }, key, new TextEncoder().encode(signingInput));
40
+ return `${signingInput}.${base64url(signature)}`;
41
+ }
42
+ /** A valid installation access token, minting + caching one if needed. */
43
+ async installationToken(installationId) {
44
+ return (await this.cachedToken(installationId)).token;
45
+ }
46
+ /**
47
+ * The permissions the installation token actually carries (App ∩ what the
48
+ * install approved) — the source of truth for capability checks. Comes free
49
+ * with the mint response and is cached alongside the token, so a warm process
50
+ * answers without a network call. Used by the provisioner to guard privileged
51
+ * actions (e.g. repo creation) before attempting them.
52
+ */
53
+ async installationPermissions(installationId) {
54
+ return (await this.cachedToken(installationId)).permissions;
55
+ }
56
+ async cachedToken(installationId) {
57
+ const cached = tokenCache.get(installationId);
58
+ if (cached && cached.expiresAt - TOKEN_SKEW_MS > this.deps.clock.now()) {
59
+ return cached;
60
+ }
61
+ return this.mintInstallationToken(installationId);
62
+ }
63
+ async mintInstallationToken(installationId) {
64
+ const jwt = await this.appJwt();
65
+ const res = await fetch(`${this.deps.apiBase}/app/installations/${installationId}/access_tokens`, {
66
+ method: 'POST',
67
+ headers: {
68
+ authorization: `Bearer ${jwt}`,
69
+ accept: 'application/vnd.github+json',
70
+ 'user-agent': USER_AGENT,
71
+ 'x-github-api-version': API_VERSION,
72
+ },
73
+ });
74
+ if (!res.ok) {
75
+ throw new Error(`Failed to mint installation token for ${installationId} (HTTP ${res.status})`);
76
+ }
77
+ const body = (await res.json());
78
+ const expiresAt = Date.parse(body.expires_at);
79
+ const entry = {
80
+ token: body.token,
81
+ permissions: body.permissions ?? {},
82
+ expiresAt: Number.isNaN(expiresAt) ? this.deps.clock.now() + 30 * 60 * 1000 : expiresAt,
83
+ };
84
+ // In-memory only (see tokenCache note) — never persisted.
85
+ tokenCache.set(installationId, entry);
86
+ return entry;
87
+ }
88
+ importKey() {
89
+ if (!this.keyPromise) {
90
+ this.keyPromise = crypto.subtle.importKey('pkcs8', pkcs8PemToDer(this.deps.privateKeyPem), { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['sign']);
91
+ }
92
+ return this.keyPromise;
93
+ }
94
+ }
95
+ //# sourceMappingURL=GitHubAppAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubAppAuth.js","sourceRoot":"","sources":["../../src/github/GitHubAppAuth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { GitHubInstallation, GitHubInstallationRepository, InstallationPermissions } from '@cat-factory/kernel';
2
+ import type { GitHubAppAuth } from './GitHubAppAuth.js';
3
+ /** One configured App: its id and the auth that signs/mint for it. */
4
+ export interface RegisteredApp {
5
+ appId: string;
6
+ auth: GitHubAppAuth;
7
+ }
8
+ /**
9
+ * The narrow token-minting surface {@link FetchGitHubClient} needs, so the client can
10
+ * be driven by something OTHER than the App registry — e.g. a static-PAT source in
11
+ * local mode. {@link GitHubAppRegistry} satisfies it structurally; a PAT source
12
+ * implements `installationToken` to return the token and may throw on the app-JWT
13
+ * paths (which only the installation discovery/listing calls use).
14
+ */
15
+ export interface AppTokenSource {
16
+ /** The default App id used for app-JWT calls that don't name one. */
17
+ readonly defaultAppId: string;
18
+ /** Every configured App, iterated for cross-App installation discovery. */
19
+ apps(): readonly {
20
+ appId: string;
21
+ }[];
22
+ /** The auth (app-JWT signer) for an appId. */
23
+ authForApp(appId: string | null | undefined): {
24
+ appJwt(): Promise<string>;
25
+ };
26
+ /** An installation token (the repo-call credential). */
27
+ installationToken(installationId: number): Promise<string>;
28
+ }
29
+ export interface GitHubAppRegistryDependencies {
30
+ /** The default (restricted) App — always present; owns legacy installations. */
31
+ default: RegisteredApp;
32
+ /** The privileged App, when configured. */
33
+ privileged?: RegisteredApp;
34
+ /** Resolves an installation's owning appId from its persisted binding. */
35
+ installationRepository: GitHubInstallationRepository;
36
+ }
37
+ export declare class GitHubAppRegistry {
38
+ private readonly deps;
39
+ constructor(deps: GitHubAppRegistryDependencies);
40
+ get defaultAppId(): string;
41
+ /** Every configured App, for cross-App discovery (connect probe, listing). */
42
+ apps(): RegisteredApp[];
43
+ /** The auth for an appId, falling back to the default App for null/legacy/unknown ids. */
44
+ authForApp(appId: string | null | undefined): GitHubAppAuth;
45
+ /** An installation token, minted by the App that owns the installation. */
46
+ installationToken(installationId: number): Promise<string>;
47
+ /** The installation's granted permissions, via its owning App. */
48
+ installationPermissions(installationId: number): Promise<InstallationPermissions>;
49
+ /**
50
+ * Whether this installation's owning App can create repos — i.e. it's the
51
+ * privileged tier (ADR 0005). A null appId means the default App, which never
52
+ * can. Used to flag `canCreateRepos` on the connection.
53
+ */
54
+ canCreateRepos(installation: GitHubInstallation): boolean;
55
+ private ownerAuth;
56
+ }
57
+ //# sourceMappingURL=GitHubAppRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubAppRegistry.d.ts","sourceRoot":"","sources":["../../src/github/GitHubAppRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,4BAA4B,EAC5B,uBAAuB,EACxB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAevD,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,aAAa,CAAA;CACpB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,2EAA2E;IAC3E,IAAI,IAAI,SAAS;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACpC,8CAA8C;IAC9C,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG;QAAE,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IAC3E,wDAAwD;IACxD,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CAC3D;AAED,MAAM,WAAW,6BAA6B;IAC5C,gFAAgF;IAChF,OAAO,EAAE,aAAa,CAAA;IACtB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,aAAa,CAAA;IAC1B,0EAA0E;IAC1E,sBAAsB,EAAE,4BAA4B,CAAA;CACrD;AAOD,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,6BAA6B,EAAI;IAEpE,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,8EAA8E;IAC9E,IAAI,IAAI,aAAa,EAAE,CAEtB;IAED,0FAA0F;IAC1F,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,CAK1D;IAED,2EAA2E;IACrE,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE/D;IAED,kEAAkE;IAC5D,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAEtF;IAED;;;;OAIG;IACH,cAAc,CAAC,YAAY,EAAE,kBAAkB,GAAG,OAAO,CAGxD;YAEa,SAAS;CASxB"}
@@ -0,0 +1,51 @@
1
+ // installationId → owning appId. The mapping is immutable on GitHub (an
2
+ // installation belongs to one App forever), so caching per-process is safe and
3
+ // spares a read on the hot token-mint path.
4
+ const ownerAppCache = new Map();
5
+ export class GitHubAppRegistry {
6
+ deps;
7
+ constructor(deps) {
8
+ this.deps = deps;
9
+ }
10
+ get defaultAppId() {
11
+ return this.deps.default.appId;
12
+ }
13
+ /** Every configured App, for cross-App discovery (connect probe, listing). */
14
+ apps() {
15
+ return this.deps.privileged ? [this.deps.default, this.deps.privileged] : [this.deps.default];
16
+ }
17
+ /** The auth for an appId, falling back to the default App for null/legacy/unknown ids. */
18
+ authForApp(appId) {
19
+ if (appId && this.deps.privileged && appId === this.deps.privileged.appId) {
20
+ return this.deps.privileged.auth;
21
+ }
22
+ return this.deps.default.auth;
23
+ }
24
+ /** An installation token, minted by the App that owns the installation. */
25
+ async installationToken(installationId) {
26
+ return (await this.ownerAuth(installationId)).installationToken(installationId);
27
+ }
28
+ /** The installation's granted permissions, via its owning App. */
29
+ async installationPermissions(installationId) {
30
+ return (await this.ownerAuth(installationId)).installationPermissions(installationId);
31
+ }
32
+ /**
33
+ * Whether this installation's owning App can create repos — i.e. it's the
34
+ * privileged tier (ADR 0005). A null appId means the default App, which never
35
+ * can. Used to flag `canCreateRepos` on the connection.
36
+ */
37
+ canCreateRepos(installation) {
38
+ const owner = installation.appId ?? this.defaultAppId;
39
+ return this.deps.privileged !== undefined && owner === this.deps.privileged.appId;
40
+ }
41
+ async ownerAuth(installationId) {
42
+ let appId = ownerAppCache.get(installationId);
43
+ if (appId === undefined) {
44
+ const record = await this.deps.installationRepository.getByInstallationId(installationId);
45
+ appId = record?.appId ?? this.defaultAppId;
46
+ ownerAppCache.set(installationId, appId);
47
+ }
48
+ return this.authForApp(appId);
49
+ }
50
+ }
51
+ //# sourceMappingURL=GitHubAppRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubAppRegistry.js","sourceRoot":"","sources":["../../src/github/GitHubAppRegistry.ts"],"names":[],"mappings":"AAqDA,wEAAwE;AACxE,+EAA+E;AAC/E,4CAA4C;AAC5C,MAAM,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAA;AAE/C,MAAM,OAAO,iBAAiB;IACC,IAAI;IAAjC,YAA6B,IAAmC;oBAAnC,IAAI;IAAkC,CAAC;IAEpE,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAA;IAChC,CAAC;IAED,8EAA8E;IAC9E,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC/F,CAAC;IAED,0FAA0F;IAC1F,UAAU,CAAC,KAAgC;QACzC,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YAC1E,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAA;QAClC,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAA;IAC/B,CAAC;IAED,2EAA2E;IAC3E,KAAK,CAAC,iBAAiB,CAAC,cAAsB;QAC5C,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAA;IACjF,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,uBAAuB,CAAC,cAAsB;QAClD,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAA;IACvF,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,YAAgC;QAC7C,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,CAAA;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAA;IACnF,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,cAAsB;QAC5C,IAAI,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;QAC7C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAA;YACzF,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC,YAAY,CAAA;YAC1C,aAAa,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAA;QAC1C,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAC/B,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ import type { BlockRepository, CiStatusProvider, CiStatusReport, GitHubClient } from '@cat-factory/kernel';
2
+ import type { ResolveRepoTarget } from '../agents/ContainerAgentExecutor.js';
3
+ export interface GitHubCiStatusProviderDependencies {
4
+ githubClient: GitHubClient;
5
+ /** Resolves the repo (installation + owner/name) a block's work targets. */
6
+ resolveRepoTarget: ResolveRepoTarget;
7
+ /** Reads the block's recorded PR ref (head branch). */
8
+ blockRepository: BlockRepository;
9
+ }
10
+ /**
11
+ * Reads a block's CI status from GitHub for the `ci` gate: resolve the PR head
12
+ * branch → its head commit (latest commit on the branch) → the check runs for
13
+ * that commit. Returns `{ headSha: null, checks: [] }` when there is no resolvable
14
+ * PR branch yet (the engine treats that as "nothing to gate").
15
+ */
16
+ export declare class GitHubCiStatusProvider implements CiStatusProvider {
17
+ private readonly deps;
18
+ constructor(deps: GitHubCiStatusProviderDependencies);
19
+ getStatus(workspaceId: string, blockId: string): Promise<CiStatusReport>;
20
+ }
21
+ //# sourceMappingURL=GitHubCiStatusProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubCiStatusProvider.d.ts","sourceRoot":"","sources":["../../src/github/GitHubCiStatusProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,YAAY,EACb,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAE5E,MAAM,WAAW,kCAAkC;IACjD,YAAY,EAAE,YAAY,CAAA;IAC1B,4EAA4E;IAC5E,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,uDAAuD;IACvD,eAAe,EAAE,eAAe,CAAA;CACjC;AAED;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,gBAAgB;IACjD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,kCAAkC,EAAI;IAEnE,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyB7E;CACF"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Reads a block's CI status from GitHub for the `ci` gate: resolve the PR head
3
+ * branch → its head commit (latest commit on the branch) → the check runs for
4
+ * that commit. Returns `{ headSha: null, checks: [] }` when there is no resolvable
5
+ * PR branch yet (the engine treats that as "nothing to gate").
6
+ */
7
+ export class GitHubCiStatusProvider {
8
+ deps;
9
+ constructor(deps) {
10
+ this.deps = deps;
11
+ }
12
+ async getStatus(workspaceId, blockId) {
13
+ const block = await this.deps.blockRepository.get(workspaceId, blockId);
14
+ const branch = block?.pullRequest?.branch;
15
+ if (!branch)
16
+ return { headSha: null, checks: [] };
17
+ const target = await this.deps.resolveRepoTarget(workspaceId, blockId);
18
+ if (!target)
19
+ return { headSha: null, checks: [] };
20
+ const ref = { owner: target.owner, repo: target.name };
21
+ // The head commit of the PR branch is the latest commit listed on that ref.
22
+ const commits = await this.deps.githubClient.listCommits(target.installationId, ref, {
23
+ sha: branch,
24
+ });
25
+ const headSha = commits.items[0]?.sha ?? null;
26
+ if (!headSha)
27
+ return { headSha: null, checks: [] };
28
+ const checks = await this.deps.githubClient.listCheckRuns(target.installationId, ref, headSha);
29
+ return {
30
+ headSha,
31
+ checks: checks.items.map((c) => ({
32
+ name: c.name,
33
+ status: c.status,
34
+ conclusion: c.conclusion,
35
+ })),
36
+ };
37
+ }
38
+ }
39
+ //# sourceMappingURL=GitHubCiStatusProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubCiStatusProvider.js","sourceRoot":"","sources":["../../src/github/GitHubCiStatusProvider.ts"],"names":[],"mappings":"AAgBA;;;;;GAKG;AACH,MAAM,OAAO,sBAAsB;IACJ,IAAI;IAAjC,YAA6B,IAAwC;oBAAxC,IAAI;IAAuC,CAAC;IAEzE,KAAK,CAAC,SAAS,CAAC,WAAmB,EAAE,OAAe;QAClD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACvE,MAAM,MAAM,GAAG,KAAK,EAAE,WAAW,EAAE,MAAM,CAAA;QACzC,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;QAEjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACtE,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;QACjD,MAAM,GAAG,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAA;QAEtD,4EAA4E;QAC5E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,EAAE;YACnF,GAAG,EAAE,MAAM;SACZ,CAAC,CAAA;QACF,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,IAAI,CAAA;QAC7C,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;QAElD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;QAC9F,OAAO;YACL,OAAO;YACP,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC/B,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,UAAU,EAAE,CAAC,CAAC,UAAU;aACzB,CAAC,CAAC;SACJ,CAAA;IACH,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import type { BlockRepository, GitHubClient, MergeabilityReport, MergeabilityVerdict, PullRequestMergeabilityProvider } from '@cat-factory/kernel';
2
+ import type { ResolveRepoTarget } from '../agents/ContainerAgentExecutor.js';
3
+ export interface GitHubMergeabilityProviderDependencies {
4
+ githubClient: GitHubClient;
5
+ /** Resolves the repo (installation + owner/name) a block's work targets. */
6
+ resolveRepoTarget: ResolveRepoTarget;
7
+ /** Reads the block's recorded PR ref (number). */
8
+ blockRepository: BlockRepository;
9
+ }
10
+ /**
11
+ * Reads a block's PR mergeability from GitHub for the `conflicts` gate. Returns
12
+ * `{ headSha: null, verdict: 'unknown' }` when there is no resolvable PR (the engine
13
+ * treats that as "nothing to gate"). Maps GitHub's lazily-computed `mergeable` /
14
+ * `mergeable_state` to the engine's small verdict: only `mergeable_state === 'dirty'`
15
+ * is a real conflict; a null/`unknown` reading means GitHub is still computing it
16
+ * (poll again); everything else (clean / behind / blocked / unstable) has no
17
+ * conflict to resolve.
18
+ */
19
+ export declare class GitHubMergeabilityProvider implements PullRequestMergeabilityProvider {
20
+ private readonly deps;
21
+ constructor(deps: GitHubMergeabilityProviderDependencies);
22
+ getMergeability(workspaceId: string, blockId: string): Promise<MergeabilityReport>;
23
+ }
24
+ /** Map GitHub's `mergeable` / `mergeable_state` to the engine's mergeability verdict. */
25
+ export declare function classifyMergeability(mergeable: boolean | null, mergeableState: string): MergeabilityVerdict;
26
+ //# sourceMappingURL=GitHubMergeabilityProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubMergeabilityProvider.d.ts","sourceRoot":"","sources":["../../src/github/GitHubMergeabilityProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,+BAA+B,EAChC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAE5E,MAAM,WAAW,sCAAsC;IACrD,YAAY,EAAE,YAAY,CAAA;IAC1B,4EAA4E;IAC5E,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,kDAAkD;IAClD,eAAe,EAAE,eAAe,CAAA;CACjC;AAED;;;;;;;;GAQG;AACH,qBAAa,0BAA2B,YAAW,+BAA+B;IACpE,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,sCAAsC,EAAI;IAEvE,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAevF;CACF;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,OAAO,GAAG,IAAI,EACzB,cAAc,EAAE,MAAM,GACrB,mBAAmB,CAOrB"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Reads a block's PR mergeability from GitHub for the `conflicts` gate. Returns
3
+ * `{ headSha: null, verdict: 'unknown' }` when there is no resolvable PR (the engine
4
+ * treats that as "nothing to gate"). Maps GitHub's lazily-computed `mergeable` /
5
+ * `mergeable_state` to the engine's small verdict: only `mergeable_state === 'dirty'`
6
+ * is a real conflict; a null/`unknown` reading means GitHub is still computing it
7
+ * (poll again); everything else (clean / behind / blocked / unstable) has no
8
+ * conflict to resolve.
9
+ */
10
+ export class GitHubMergeabilityProvider {
11
+ deps;
12
+ constructor(deps) {
13
+ this.deps = deps;
14
+ }
15
+ async getMergeability(workspaceId, blockId) {
16
+ const block = await this.deps.blockRepository.get(workspaceId, blockId);
17
+ const number = block?.pullRequest?.number;
18
+ if (number === undefined)
19
+ return { headSha: null, verdict: 'unknown' };
20
+ const target = await this.deps.resolveRepoTarget(workspaceId, blockId);
21
+ if (!target)
22
+ return { headSha: null, verdict: 'unknown' };
23
+ const { mergeable, mergeableState, headSha } = await this.deps.githubClient.getPullRequestMergeability(target.installationId, { owner: target.owner, repo: target.name }, number);
24
+ return { headSha, verdict: classifyMergeability(mergeable, mergeableState) };
25
+ }
26
+ }
27
+ /** Map GitHub's `mergeable` / `mergeable_state` to the engine's mergeability verdict. */
28
+ export function classifyMergeability(mergeable, mergeableState) {
29
+ // 'dirty' is GitHub's signal that the PR conflicts with its base.
30
+ if (mergeableState === 'dirty')
31
+ return 'conflicted';
32
+ // Mergeability is computed asynchronously: null / 'unknown' means "not ready yet".
33
+ if (mergeable === null || mergeableState === 'unknown' || mergeableState === '')
34
+ return 'unknown';
35
+ // clean / behind / blocked / unstable / has_hooks: no merge conflict to resolve.
36
+ return 'mergeable';
37
+ }
38
+ //# sourceMappingURL=GitHubMergeabilityProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubMergeabilityProvider.js","sourceRoot":"","sources":["../../src/github/GitHubMergeabilityProvider.ts"],"names":[],"mappings":"AAiBA;;;;;;;;GAQG;AACH,MAAM,OAAO,0BAA0B;IACR,IAAI;IAAjC,YAA6B,IAA4C;oBAA5C,IAAI;IAA2C,CAAC;IAE7E,KAAK,CAAC,eAAe,CAAC,WAAmB,EAAE,OAAe;QACxD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACvE,MAAM,MAAM,GAAG,KAAK,EAAE,WAAW,EAAE,MAAM,CAAA;QACzC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAA;QAEtE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACtE,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAA;QAEzD,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,GAC1C,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,0BAA0B,CACrD,MAAM,CAAC,cAAc,EACrB,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAC1C,MAAM,CACP,CAAA;QACH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,oBAAoB,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,CAAA;IAC9E,CAAC;CACF;AAED,yFAAyF;AACzF,MAAM,UAAU,oBAAoB,CAClC,SAAyB,EACzB,cAAsB;IAEtB,kEAAkE;IAClE,IAAI,cAAc,KAAK,OAAO;QAAE,OAAO,YAAY,CAAA;IACnD,mFAAmF;IACnF,IAAI,SAAS,KAAK,IAAI,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK,EAAE;QAAE,OAAO,SAAS,CAAA;IACjG,iFAAiF;IACjF,OAAO,WAAW,CAAA;AACpB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { BlockRepository, GitHubClient, PullRequestMerger } from '@cat-factory/kernel';
2
+ import type { ResolveRepoTarget } from '../agents/ContainerAgentExecutor.js';
3
+ export interface GitHubPullRequestMergerDependencies {
4
+ githubClient: GitHubClient;
5
+ /** Resolves the repo (installation + owner/name) a block's work targets. */
6
+ resolveRepoTarget: ResolveRepoTarget;
7
+ /** Reads the block's recorded PR ref (number to merge). */
8
+ blockRepository: BlockRepository;
9
+ }
10
+ /**
11
+ * The single place a block's pull request is actually merged on GitHub. The
12
+ * execution engine calls this (via the {@link PullRequestMerger} port) before
13
+ * flipping a task to `done`, so `done` provably means "merged". Throws if the
14
+ * block has no PR number, the repo can't be resolved, or GitHub rejects the merge
15
+ * (failing required checks, conflicts) — the engine then leaves the block awaiting
16
+ * a manual merge / raises a review notification.
17
+ */
18
+ export declare class GitHubPullRequestMerger implements PullRequestMerger {
19
+ private readonly deps;
20
+ constructor(deps: GitHubPullRequestMergerDependencies);
21
+ mergeForBlock(workspaceId: string, blockId: string): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=GitHubPullRequestMerger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubPullRequestMerger.d.ts","sourceRoot":"","sources":["../../src/github/GitHubPullRequestMerger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAC3F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AAE5E,MAAM,WAAW,mCAAmC;IAClD,YAAY,EAAE,YAAY,CAAA;IAC1B,4EAA4E;IAC5E,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,2DAA2D;IAC3D,eAAe,EAAE,eAAe,CAAA;CACjC;AAED;;;;;;;GAOG;AACH,qBAAa,uBAAwB,YAAW,iBAAiB;IACnD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,mCAAmC,EAAI;IAEpE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BvE;CACF"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The single place a block's pull request is actually merged on GitHub. The
3
+ * execution engine calls this (via the {@link PullRequestMerger} port) before
4
+ * flipping a task to `done`, so `done` provably means "merged". Throws if the
5
+ * block has no PR number, the repo can't be resolved, or GitHub rejects the merge
6
+ * (failing required checks, conflicts) — the engine then leaves the block awaiting
7
+ * a manual merge / raises a review notification.
8
+ */
9
+ export class GitHubPullRequestMerger {
10
+ deps;
11
+ constructor(deps) {
12
+ this.deps = deps;
13
+ }
14
+ async mergeForBlock(workspaceId, blockId) {
15
+ const target = await this.deps.resolveRepoTarget(workspaceId, blockId);
16
+ if (!target) {
17
+ throw new Error(`No GitHub repository resolved for block '${blockId}'; cannot merge.`);
18
+ }
19
+ const block = await this.deps.blockRepository.get(workspaceId, blockId);
20
+ const number = block?.pullRequest?.number;
21
+ if (number === undefined) {
22
+ throw new Error(`Block '${blockId}' has no pull-request number to merge.`);
23
+ }
24
+ await this.deps.githubClient.mergePullRequest(target.installationId, { owner: target.owner, repo: target.name }, number);
25
+ // Tear down the work branch now that it is merged. The branch is deterministic
26
+ // per task (`cat-factory/<blockId>`), so leaving it behind would let a later
27
+ // re-run of this block RESUME on already-merged commits — which a squash/rebase
28
+ // merge would re-introduce wholesale (those commits are not ancestors of base).
29
+ // Best-effort: a failed delete must never undo or fail the completed merge.
30
+ const branch = block?.pullRequest?.branch;
31
+ if (branch) {
32
+ await this.deps.githubClient
33
+ .deleteBranch(target.installationId, { owner: target.owner, repo: target.name }, branch)
34
+ .catch(() => { });
35
+ }
36
+ }
37
+ }
38
+ //# sourceMappingURL=GitHubPullRequestMerger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitHubPullRequestMerger.js","sourceRoot":"","sources":["../../src/github/GitHubPullRequestMerger.ts"],"names":[],"mappings":"AAWA;;;;;;;GAOG;AACH,MAAM,OAAO,uBAAuB;IACL,IAAI;IAAjC,YAA6B,IAAyC;oBAAzC,IAAI;IAAwC,CAAC;IAE1E,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,OAAe;QACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACtE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,4CAA4C,OAAO,kBAAkB,CAAC,CAAA;QACxF,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QACvE,MAAM,MAAM,GAAG,KAAK,EAAE,WAAW,EAAE,MAAM,CAAA;QACzC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,UAAU,OAAO,wCAAwC,CAAC,CAAA;QAC5E,CAAC;QACD,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAC3C,MAAM,CAAC,cAAc,EACrB,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAC1C,MAAM,CACP,CAAA;QAED,+EAA+E;QAC/E,6EAA6E;QAC7E,gFAAgF;QAChF,gFAAgF;QAChF,4EAA4E;QAC5E,MAAM,MAAM,GAAG,KAAK,EAAE,WAAW,EAAE,MAAM,CAAA;QACzC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY;iBACzB,YAAY,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC;iBACvF,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,9 @@
1
+ import type { WebhookVerifier } from '@cat-factory/kernel';
2
+ export declare class WebCryptoWebhookVerifier implements WebhookVerifier {
3
+ private readonly secret;
4
+ private keyPromise?;
5
+ constructor(secret: string);
6
+ verify(rawBody: ArrayBuffer, signatureHeader: string | null): Promise<boolean>;
7
+ private importKey;
8
+ }
9
+ //# sourceMappingURL=WebCryptoWebhookVerifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebCryptoWebhookVerifier.d.ts","sourceRoot":"","sources":["../../src/github/WebCryptoWebhookVerifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAY1D,qBAAa,wBAAyB,YAAW,eAAe;IAGlD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,UAAU,CAAC,CAAoB;IAEvC,YAA6B,MAAM,EAAE,MAAM,EAAI;IAEzC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAQnF;IAED,OAAO,CAAC,SAAS;CAYlB"}
@@ -0,0 +1,40 @@
1
+ import { timingSafeEqual } from '../crypto/encoding.js';
2
+ // Verifies GitHub webhook deliveries: GitHub signs the raw body with HMAC-SHA-256
3
+ // using the App's webhook secret and sends `sha256=<hex>` in the
4
+ // `X-Hub-Signature-256` header. We recompute the digest with Web Crypto
5
+ // (`crypto.subtle`, a global on both workerd and Node 22+) and compare in constant
6
+ // time, on the *raw* body bytes (verification must precede any JSON parse). Promoted
7
+ // from the Worker infra so every facade verifies webhooks identically.
8
+ const PREFIX = 'sha256=';
9
+ export class WebCryptoWebhookVerifier {
10
+ secret;
11
+ keyPromise;
12
+ constructor(secret) {
13
+ this.secret = secret;
14
+ }
15
+ async verify(rawBody, signatureHeader) {
16
+ if (!signatureHeader || !signatureHeader.startsWith(PREFIX))
17
+ return false;
18
+ const provided = hexToBytes(signatureHeader.slice(PREFIX.length));
19
+ if (!provided)
20
+ return false;
21
+ const key = await this.importKey();
22
+ const computed = new Uint8Array(await crypto.subtle.sign('HMAC', key, rawBody));
23
+ return timingSafeEqual(provided, computed);
24
+ }
25
+ importKey() {
26
+ if (!this.keyPromise) {
27
+ this.keyPromise = crypto.subtle.importKey('raw', new TextEncoder().encode(this.secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
28
+ }
29
+ return this.keyPromise;
30
+ }
31
+ }
32
+ function hexToBytes(hex) {
33
+ if (hex.length === 0 || hex.length % 2 !== 0 || /[^0-9a-fA-F]/.test(hex))
34
+ return null;
35
+ const bytes = new Uint8Array(hex.length / 2);
36
+ for (let i = 0; i < bytes.length; i++)
37
+ bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
38
+ return bytes;
39
+ }
40
+ //# sourceMappingURL=WebCryptoWebhookVerifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebCryptoWebhookVerifier.js","sourceRoot":"","sources":["../../src/github/WebCryptoWebhookVerifier.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,kFAAkF;AAClF,iEAAiE;AACjE,wEAAwE;AACxE,mFAAmF;AACnF,qFAAqF;AACrF,uEAAuE;AAEvE,MAAM,MAAM,GAAG,SAAS,CAAA;AAExB,MAAM,OAAO,wBAAwB;IAGN,MAAM;IAF3B,UAAU,CAAqB;IAEvC,YAA6B,MAAc;sBAAd,MAAM;IAAW,CAAC;IAE/C,KAAK,CAAC,MAAM,CAAC,OAAoB,EAAE,eAA8B;QAC/D,IAAI,CAAC,eAAe,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAA;QACzE,MAAM,QAAQ,GAAG,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QACjE,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAA;QAE3B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAA;QAClC,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAA;QAC/E,OAAO,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAC5C,CAAC;IAEO,SAAS;QACf,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CACvC,KAAK,EACL,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EACrC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,EACjC,KAAK,EACL,CAAC,MAAM,CAAC,CACT,CAAA;QACH,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;CACF;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IACrF,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC3F,OAAO,KAAK,CAAA;AACd,CAAC"}
@@ -0,0 +1,26 @@
1
+ export interface EnsureWorkBranchInput {
2
+ /** GitHub REST base, e.g. `https://api.github.com` (GitHub Enterprise overrides it). */
3
+ apiBase?: string;
4
+ /** A short-lived installation token authorised for the repo. */
5
+ token: string;
6
+ owner: string;
7
+ name: string;
8
+ /** The branch the work branch forks from (the repo's base). */
9
+ baseBranch: string;
10
+ /** The work branch to ensure, e.g. `cat-factory/<blockId>`. */
11
+ branch: string;
12
+ /**
13
+ * Whether to CREATE the work branch from base when it does not yet exist. Writers pass
14
+ * `true` (they need the branch); read-only agents pass `false` to PROBE only — they
15
+ * never write, so a missing branch means "nothing to read, use base", and creating it
16
+ * would only orphan an empty ref. Defaults to `true`.
17
+ */
18
+ create?: boolean;
19
+ }
20
+ /**
21
+ * Ensure `branch` is present on the remote. Writers (`create !== false`) create it from
22
+ * `baseBranch`'s tip when absent; read-only callers (`create: false`) only report whether
23
+ * it already exists. Returns whether the work branch is present afterwards.
24
+ */
25
+ export declare function ensureWorkBranchViaRest(input: EnsureWorkBranchInput): Promise<boolean>;
26
+ //# sourceMappingURL=ensureWorkBranch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensureWorkBranch.d.ts","sourceRoot":"","sources":["../../src/github/ensureWorkBranch.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,qBAAqB;IACpC,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAA;IAClB,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAmBD;;;;GAIG;AACH,wBAAsB,uBAAuB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CA0D5F"}