@urateam/core 0.1.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 (620) hide show
  1. package/dist/__tests__/assembler.test.d.ts +2 -0
  2. package/dist/__tests__/assembler.test.d.ts.map +1 -0
  3. package/dist/__tests__/assembler.test.js +63 -0
  4. package/dist/__tests__/assembler.test.js.map +1 -0
  5. package/dist/__tests__/auth-check.test.d.ts +2 -0
  6. package/dist/__tests__/auth-check.test.d.ts.map +1 -0
  7. package/dist/__tests__/auth-check.test.js +88 -0
  8. package/dist/__tests__/auth-check.test.js.map +1 -0
  9. package/dist/__tests__/auto-merge.test.d.ts +15 -0
  10. package/dist/__tests__/auto-merge.test.d.ts.map +1 -0
  11. package/dist/__tests__/auto-merge.test.js +428 -0
  12. package/dist/__tests__/auto-merge.test.js.map +1 -0
  13. package/dist/__tests__/bec89-unified-schema.test.d.ts +2 -0
  14. package/dist/__tests__/bec89-unified-schema.test.d.ts.map +1 -0
  15. package/dist/__tests__/bec89-unified-schema.test.js +235 -0
  16. package/dist/__tests__/bec89-unified-schema.test.js.map +1 -0
  17. package/dist/__tests__/conflict-detector.test.d.ts +2 -0
  18. package/dist/__tests__/conflict-detector.test.d.ts.map +1 -0
  19. package/dist/__tests__/conflict-detector.test.js +206 -0
  20. package/dist/__tests__/conflict-detector.test.js.map +1 -0
  21. package/dist/__tests__/coordination.test.d.ts +2 -0
  22. package/dist/__tests__/coordination.test.d.ts.map +1 -0
  23. package/dist/__tests__/coordination.test.js +257 -0
  24. package/dist/__tests__/coordination.test.js.map +1 -0
  25. package/dist/__tests__/db-postgres.test.d.ts +14 -0
  26. package/dist/__tests__/db-postgres.test.d.ts.map +1 -0
  27. package/dist/__tests__/db-postgres.test.js +289 -0
  28. package/dist/__tests__/db-postgres.test.js.map +1 -0
  29. package/dist/__tests__/db.test.d.ts +2 -0
  30. package/dist/__tests__/db.test.d.ts.map +1 -0
  31. package/dist/__tests__/db.test.js +182 -0
  32. package/dist/__tests__/db.test.js.map +1 -0
  33. package/dist/__tests__/deep-review.test.d.ts +2 -0
  34. package/dist/__tests__/deep-review.test.d.ts.map +1 -0
  35. package/dist/__tests__/deep-review.test.js +322 -0
  36. package/dist/__tests__/deep-review.test.js.map +1 -0
  37. package/dist/__tests__/devcontainer.test.d.ts +2 -0
  38. package/dist/__tests__/devcontainer.test.d.ts.map +1 -0
  39. package/dist/__tests__/devcontainer.test.js +89 -0
  40. package/dist/__tests__/devcontainer.test.js.map +1 -0
  41. package/dist/__tests__/distributed-lock.test.d.ts +18 -0
  42. package/dist/__tests__/distributed-lock.test.d.ts.map +1 -0
  43. package/dist/__tests__/distributed-lock.test.js +237 -0
  44. package/dist/__tests__/distributed-lock.test.js.map +1 -0
  45. package/dist/__tests__/e2e-pipeline.test.d.ts +25 -0
  46. package/dist/__tests__/e2e-pipeline.test.d.ts.map +1 -0
  47. package/dist/__tests__/e2e-pipeline.test.js +517 -0
  48. package/dist/__tests__/e2e-pipeline.test.js.map +1 -0
  49. package/dist/__tests__/error-classifier.test.d.ts +2 -0
  50. package/dist/__tests__/error-classifier.test.d.ts.map +1 -0
  51. package/dist/__tests__/error-classifier.test.js +33 -0
  52. package/dist/__tests__/error-classifier.test.js.map +1 -0
  53. package/dist/__tests__/executor-integration.test.d.ts +11 -0
  54. package/dist/__tests__/executor-integration.test.d.ts.map +1 -0
  55. package/dist/__tests__/executor-integration.test.js +246 -0
  56. package/dist/__tests__/executor-integration.test.js.map +1 -0
  57. package/dist/__tests__/executor-issue-id.test.d.ts +13 -0
  58. package/dist/__tests__/executor-issue-id.test.d.ts.map +1 -0
  59. package/dist/__tests__/executor-issue-id.test.js +211 -0
  60. package/dist/__tests__/executor-issue-id.test.js.map +1 -0
  61. package/dist/__tests__/executor.test.d.ts +2 -0
  62. package/dist/__tests__/executor.test.d.ts.map +1 -0
  63. package/dist/__tests__/executor.test.js +164 -0
  64. package/dist/__tests__/executor.test.js.map +1 -0
  65. package/dist/__tests__/extract-handoff.test.d.ts +2 -0
  66. package/dist/__tests__/extract-handoff.test.d.ts.map +1 -0
  67. package/dist/__tests__/extract-handoff.test.js +131 -0
  68. package/dist/__tests__/extract-handoff.test.js.map +1 -0
  69. package/dist/__tests__/fail-on-auto-commit.test.d.ts +2 -0
  70. package/dist/__tests__/fail-on-auto-commit.test.d.ts.map +1 -0
  71. package/dist/__tests__/fail-on-auto-commit.test.js +156 -0
  72. package/dist/__tests__/fail-on-auto-commit.test.js.map +1 -0
  73. package/dist/__tests__/fixtures/webhook-comment.json +5 -0
  74. package/dist/__tests__/fixtures/webhook-state-change.json +15 -0
  75. package/dist/__tests__/force-push-agent-branches.test.d.ts +12 -0
  76. package/dist/__tests__/force-push-agent-branches.test.d.ts.map +1 -0
  77. package/dist/__tests__/force-push-agent-branches.test.js +348 -0
  78. package/dist/__tests__/force-push-agent-branches.test.js.map +1 -0
  79. package/dist/__tests__/github-webhook.test.d.ts +2 -0
  80. package/dist/__tests__/github-webhook.test.d.ts.map +1 -0
  81. package/dist/__tests__/github-webhook.test.js +370 -0
  82. package/dist/__tests__/github-webhook.test.js.map +1 -0
  83. package/dist/__tests__/gitlab.test.d.ts +28 -0
  84. package/dist/__tests__/gitlab.test.d.ts.map +1 -0
  85. package/dist/__tests__/gitlab.test.js +241 -0
  86. package/dist/__tests__/gitlab.test.js.map +1 -0
  87. package/dist/__tests__/integration/auto-commit.test.d.ts +2 -0
  88. package/dist/__tests__/integration/auto-commit.test.d.ts.map +1 -0
  89. package/dist/__tests__/integration/auto-commit.test.js +207 -0
  90. package/dist/__tests__/integration/auto-commit.test.js.map +1 -0
  91. package/dist/__tests__/integration/bec99-cross-worktree-guard.test.d.ts +10 -0
  92. package/dist/__tests__/integration/bec99-cross-worktree-guard.test.d.ts.map +1 -0
  93. package/dist/__tests__/integration/bec99-cross-worktree-guard.test.js +183 -0
  94. package/dist/__tests__/integration/bec99-cross-worktree-guard.test.js.map +1 -0
  95. package/dist/__tests__/integration/reproduce-bec99.test.d.ts +32 -0
  96. package/dist/__tests__/integration/reproduce-bec99.test.d.ts.map +1 -0
  97. package/dist/__tests__/integration/reproduce-bec99.test.js +243 -0
  98. package/dist/__tests__/integration/reproduce-bec99.test.js.map +1 -0
  99. package/dist/__tests__/integration/vitest-changed.test.d.ts +10 -0
  100. package/dist/__tests__/integration/vitest-changed.test.d.ts.map +1 -0
  101. package/dist/__tests__/integration/vitest-changed.test.js +128 -0
  102. package/dist/__tests__/integration/vitest-changed.test.js.map +1 -0
  103. package/dist/__tests__/license.test.d.ts +2 -0
  104. package/dist/__tests__/license.test.d.ts.map +1 -0
  105. package/dist/__tests__/license.test.js +53 -0
  106. package/dist/__tests__/license.test.js.map +1 -0
  107. package/dist/__tests__/mcp-resolver.test.d.ts +2 -0
  108. package/dist/__tests__/mcp-resolver.test.d.ts.map +1 -0
  109. package/dist/__tests__/mcp-resolver.test.js +65 -0
  110. package/dist/__tests__/mcp-resolver.test.js.map +1 -0
  111. package/dist/__tests__/migrator.test.d.ts +2 -0
  112. package/dist/__tests__/migrator.test.d.ts.map +1 -0
  113. package/dist/__tests__/migrator.test.js +300 -0
  114. package/dist/__tests__/migrator.test.js.map +1 -0
  115. package/dist/__tests__/notifier-discord.test.d.ts +2 -0
  116. package/dist/__tests__/notifier-discord.test.d.ts.map +1 -0
  117. package/dist/__tests__/notifier-discord.test.js +166 -0
  118. package/dist/__tests__/notifier-discord.test.js.map +1 -0
  119. package/dist/__tests__/notifier-slack.test.d.ts +2 -0
  120. package/dist/__tests__/notifier-slack.test.d.ts.map +1 -0
  121. package/dist/__tests__/notifier-slack.test.js +157 -0
  122. package/dist/__tests__/notifier-slack.test.js.map +1 -0
  123. package/dist/__tests__/notifier.test.d.ts +2 -0
  124. package/dist/__tests__/notifier.test.d.ts.map +1 -0
  125. package/dist/__tests__/notifier.test.js +207 -0
  126. package/dist/__tests__/notifier.test.js.map +1 -0
  127. package/dist/__tests__/pipeline-config.test.d.ts +2 -0
  128. package/dist/__tests__/pipeline-config.test.d.ts.map +1 -0
  129. package/dist/__tests__/pipeline-config.test.js +143 -0
  130. package/dist/__tests__/pipeline-config.test.js.map +1 -0
  131. package/dist/__tests__/pipeline-runner.test.d.ts +2 -0
  132. package/dist/__tests__/pipeline-runner.test.d.ts.map +1 -0
  133. package/dist/__tests__/pipeline-runner.test.js +359 -0
  134. package/dist/__tests__/pipeline-runner.test.js.map +1 -0
  135. package/dist/__tests__/pm-approvals-n1.repro.test.d.ts +9 -0
  136. package/dist/__tests__/pm-approvals-n1.repro.test.d.ts.map +1 -0
  137. package/dist/__tests__/pm-approvals-n1.repro.test.js +175 -0
  138. package/dist/__tests__/pm-approvals-n1.repro.test.js.map +1 -0
  139. package/dist/__tests__/pm-approvals.test.d.ts +2 -0
  140. package/dist/__tests__/pm-approvals.test.d.ts.map +1 -0
  141. package/dist/__tests__/pm-approvals.test.js +162 -0
  142. package/dist/__tests__/pm-approvals.test.js.map +1 -0
  143. package/dist/__tests__/pm-budget.test.d.ts +2 -0
  144. package/dist/__tests__/pm-budget.test.d.ts.map +1 -0
  145. package/dist/__tests__/pm-budget.test.js +65 -0
  146. package/dist/__tests__/pm-budget.test.js.map +1 -0
  147. package/dist/__tests__/pm-conflict.test.d.ts +2 -0
  148. package/dist/__tests__/pm-conflict.test.d.ts.map +1 -0
  149. package/dist/__tests__/pm-conflict.test.js +87 -0
  150. package/dist/__tests__/pm-conflict.test.js.map +1 -0
  151. package/dist/__tests__/pm-promote.test.d.ts +2 -0
  152. package/dist/__tests__/pm-promote.test.d.ts.map +1 -0
  153. package/dist/__tests__/pm-promote.test.js +82 -0
  154. package/dist/__tests__/pm-promote.test.js.map +1 -0
  155. package/dist/__tests__/pm-recover.test.d.ts +2 -0
  156. package/dist/__tests__/pm-recover.test.d.ts.map +1 -0
  157. package/dist/__tests__/pm-recover.test.js +100 -0
  158. package/dist/__tests__/pm-recover.test.js.map +1 -0
  159. package/dist/__tests__/pm-scheduler.test.d.ts +2 -0
  160. package/dist/__tests__/pm-scheduler.test.d.ts.map +1 -0
  161. package/dist/__tests__/pm-scheduler.test.js +112 -0
  162. package/dist/__tests__/pm-scheduler.test.js.map +1 -0
  163. package/dist/__tests__/pm-slack-interface.test.d.ts +2 -0
  164. package/dist/__tests__/pm-slack-interface.test.d.ts.map +1 -0
  165. package/dist/__tests__/pm-slack-interface.test.js +372 -0
  166. package/dist/__tests__/pm-slack-interface.test.js.map +1 -0
  167. package/dist/__tests__/pm-slack.test.d.ts +2 -0
  168. package/dist/__tests__/pm-slack.test.d.ts.map +1 -0
  169. package/dist/__tests__/pm-slack.test.js +83 -0
  170. package/dist/__tests__/pm-slack.test.js.map +1 -0
  171. package/dist/__tests__/pm-triage.test.d.ts +2 -0
  172. package/dist/__tests__/pm-triage.test.d.ts.map +1 -0
  173. package/dist/__tests__/pm-triage.test.js +198 -0
  174. package/dist/__tests__/pm-triage.test.js.map +1 -0
  175. package/dist/__tests__/pm-types.test.d.ts +2 -0
  176. package/dist/__tests__/pm-types.test.d.ts.map +1 -0
  177. package/dist/__tests__/pm-types.test.js +76 -0
  178. package/dist/__tests__/pm-types.test.js.map +1 -0
  179. package/dist/__tests__/pr-automerge.test.d.ts +18 -0
  180. package/dist/__tests__/pr-automerge.test.d.ts.map +1 -0
  181. package/dist/__tests__/pr-automerge.test.js +645 -0
  182. package/dist/__tests__/pr-automerge.test.js.map +1 -0
  183. package/dist/__tests__/pr-description.test.d.ts +2 -0
  184. package/dist/__tests__/pr-description.test.d.ts.map +1 -0
  185. package/dist/__tests__/pr-description.test.js +728 -0
  186. package/dist/__tests__/pr-description.test.js.map +1 -0
  187. package/dist/__tests__/prompt-injection.test.d.ts +2 -0
  188. package/dist/__tests__/prompt-injection.test.d.ts.map +1 -0
  189. package/dist/__tests__/prompt-injection.test.js +446 -0
  190. package/dist/__tests__/prompt-injection.test.js.map +1 -0
  191. package/dist/__tests__/ralph-gate.test.d.ts +19 -0
  192. package/dist/__tests__/ralph-gate.test.d.ts.map +1 -0
  193. package/dist/__tests__/ralph-gate.test.js +593 -0
  194. package/dist/__tests__/ralph-gate.test.js.map +1 -0
  195. package/dist/__tests__/ralph-review-fix-regression.test.d.ts +18 -0
  196. package/dist/__tests__/ralph-review-fix-regression.test.d.ts.map +1 -0
  197. package/dist/__tests__/ralph-review-fix-regression.test.js +306 -0
  198. package/dist/__tests__/ralph-review-fix-regression.test.js.map +1 -0
  199. package/dist/__tests__/ralph.test.d.ts +2 -0
  200. package/dist/__tests__/ralph.test.d.ts.map +1 -0
  201. package/dist/__tests__/ralph.test.js +96 -0
  202. package/dist/__tests__/ralph.test.js.map +1 -0
  203. package/dist/__tests__/recover-stuck.test.d.ts +8 -0
  204. package/dist/__tests__/recover-stuck.test.d.ts.map +1 -0
  205. package/dist/__tests__/recover-stuck.test.js +399 -0
  206. package/dist/__tests__/recover-stuck.test.js.map +1 -0
  207. package/dist/__tests__/repo.test.d.ts +2 -0
  208. package/dist/__tests__/repo.test.d.ts.map +1 -0
  209. package/dist/__tests__/repo.test.js +295 -0
  210. package/dist/__tests__/repo.test.js.map +1 -0
  211. package/dist/__tests__/repro-bec58-n-plus-one.test.d.ts +2 -0
  212. package/dist/__tests__/repro-bec58-n-plus-one.test.d.ts.map +1 -0
  213. package/dist/__tests__/repro-bec58-n-plus-one.test.js +187 -0
  214. package/dist/__tests__/repro-bec58-n-plus-one.test.js.map +1 -0
  215. package/dist/__tests__/reproduce-bec113-pagination-warning.test.d.ts +16 -0
  216. package/dist/__tests__/reproduce-bec113-pagination-warning.test.d.ts.map +1 -0
  217. package/dist/__tests__/reproduce-bec113-pagination-warning.test.js +226 -0
  218. package/dist/__tests__/reproduce-bec113-pagination-warning.test.js.map +1 -0
  219. package/dist/__tests__/reproduce-bec43-updatedat.test.d.ts +2 -0
  220. package/dist/__tests__/reproduce-bec43-updatedat.test.d.ts.map +1 -0
  221. package/dist/__tests__/reproduce-bec43-updatedat.test.js +76 -0
  222. package/dist/__tests__/reproduce-bec43-updatedat.test.js.map +1 -0
  223. package/dist/__tests__/reproduce-bec48-distributed-race.test.d.ts +18 -0
  224. package/dist/__tests__/reproduce-bec48-distributed-race.test.d.ts.map +1 -0
  225. package/dist/__tests__/reproduce-bec48-distributed-race.test.js +178 -0
  226. package/dist/__tests__/reproduce-bec48-distributed-race.test.js.map +1 -0
  227. package/dist/__tests__/reproduce-bec62.test.d.ts +2 -0
  228. package/dist/__tests__/reproduce-bec62.test.d.ts.map +1 -0
  229. package/dist/__tests__/reproduce-bec62.test.js +86 -0
  230. package/dist/__tests__/reproduce-bec62.test.js.map +1 -0
  231. package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.d.ts +13 -0
  232. package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.d.ts.map +1 -0
  233. package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js +220 -0
  234. package/dist/__tests__/reproduce-bec91-stuck-in-progress.test.js.map +1 -0
  235. package/dist/__tests__/review-feedback.test.d.ts +2 -0
  236. package/dist/__tests__/review-feedback.test.d.ts.map +1 -0
  237. package/dist/__tests__/review-feedback.test.js +383 -0
  238. package/dist/__tests__/review-feedback.test.js.map +1 -0
  239. package/dist/__tests__/sanitizer.test.d.ts +2 -0
  240. package/dist/__tests__/sanitizer.test.d.ts.map +1 -0
  241. package/dist/__tests__/sanitizer.test.js +162 -0
  242. package/dist/__tests__/sanitizer.test.js.map +1 -0
  243. package/dist/__tests__/security.test.d.ts +2 -0
  244. package/dist/__tests__/security.test.d.ts.map +1 -0
  245. package/dist/__tests__/security.test.js +52 -0
  246. package/dist/__tests__/security.test.js.map +1 -0
  247. package/dist/__tests__/server.test.d.ts +2 -0
  248. package/dist/__tests__/server.test.d.ts.map +1 -0
  249. package/dist/__tests__/server.test.js +61 -0
  250. package/dist/__tests__/server.test.js.map +1 -0
  251. package/dist/__tests__/slack-alerts.test.d.ts +2 -0
  252. package/dist/__tests__/slack-alerts.test.d.ts.map +1 -0
  253. package/dist/__tests__/slack-alerts.test.js +214 -0
  254. package/dist/__tests__/slack-alerts.test.js.map +1 -0
  255. package/dist/__tests__/stage-models.test.d.ts +14 -0
  256. package/dist/__tests__/stage-models.test.d.ts.map +1 -0
  257. package/dist/__tests__/stage-models.test.js +244 -0
  258. package/dist/__tests__/stage-models.test.js.map +1 -0
  259. package/dist/__tests__/start-todo.test.d.ts +2 -0
  260. package/dist/__tests__/start-todo.test.d.ts.map +1 -0
  261. package/dist/__tests__/start-todo.test.js +175 -0
  262. package/dist/__tests__/start-todo.test.js.map +1 -0
  263. package/dist/__tests__/tech-stack.test.d.ts +2 -0
  264. package/dist/__tests__/tech-stack.test.d.ts.map +1 -0
  265. package/dist/__tests__/tech-stack.test.js +75 -0
  266. package/dist/__tests__/tech-stack.test.js.map +1 -0
  267. package/dist/__tests__/templates.test.d.ts +2 -0
  268. package/dist/__tests__/templates.test.d.ts.map +1 -0
  269. package/dist/__tests__/templates.test.js +161 -0
  270. package/dist/__tests__/templates.test.js.map +1 -0
  271. package/dist/__tests__/test-quality.test.d.ts +2 -0
  272. package/dist/__tests__/test-quality.test.d.ts.map +1 -0
  273. package/dist/__tests__/test-quality.test.js +329 -0
  274. package/dist/__tests__/test-quality.test.js.map +1 -0
  275. package/dist/__tests__/token-budget.test.d.ts +2 -0
  276. package/dist/__tests__/token-budget.test.d.ts.map +1 -0
  277. package/dist/__tests__/token-budget.test.js +198 -0
  278. package/dist/__tests__/token-budget.test.js.map +1 -0
  279. package/dist/__tests__/types.test.d.ts +2 -0
  280. package/dist/__tests__/types.test.d.ts.map +1 -0
  281. package/dist/__tests__/types.test.js +156 -0
  282. package/dist/__tests__/types.test.js.map +1 -0
  283. package/dist/__tests__/validate.test.d.ts +2 -0
  284. package/dist/__tests__/validate.test.d.ts.map +1 -0
  285. package/dist/__tests__/validate.test.js +128 -0
  286. package/dist/__tests__/validate.test.js.map +1 -0
  287. package/dist/__tests__/webhook-handler.test.d.ts +2 -0
  288. package/dist/__tests__/webhook-handler.test.d.ts.map +1 -0
  289. package/dist/__tests__/webhook-handler.test.js +286 -0
  290. package/dist/__tests__/webhook-handler.test.js.map +1 -0
  291. package/dist/__tests__/webhook.test.d.ts +2 -0
  292. package/dist/__tests__/webhook.test.d.ts.map +1 -0
  293. package/dist/__tests__/webhook.test.js +58 -0
  294. package/dist/__tests__/webhook.test.js.map +1 -0
  295. package/dist/db/client.d.ts +56 -0
  296. package/dist/db/client.d.ts.map +1 -0
  297. package/dist/db/client.js +201 -0
  298. package/dist/db/client.js.map +1 -0
  299. package/dist/db/index.d.ts +4 -0
  300. package/dist/db/index.d.ts.map +1 -0
  301. package/dist/db/index.js +4 -0
  302. package/dist/db/index.js.map +1 -0
  303. package/dist/db/migrations/postgres/001_initial_schema.sql +78 -0
  304. package/dist/db/migrations/postgres/002_pg_timestamps.sql +78 -0
  305. package/dist/db/migrations/postgres/003_retry_count.sql +10 -0
  306. package/dist/db/migrations/postgres/004_review_feedback.sql +20 -0
  307. package/dist/db/migrations/postgres/005_auto_merge.sql +15 -0
  308. package/dist/db/migrations/sqlite/001_initial_schema.sql +78 -0
  309. package/dist/db/migrations/sqlite/002_retry_count.sql +5 -0
  310. package/dist/db/migrations/sqlite/003_review_feedback.sql +7 -0
  311. package/dist/db/migrations/sqlite/004_auto_merge.sql +6 -0
  312. package/dist/db/migrator.d.ts +51 -0
  313. package/dist/db/migrator.d.ts.map +1 -0
  314. package/dist/db/migrator.js +188 -0
  315. package/dist/db/migrator.js.map +1 -0
  316. package/dist/db/schema.d.ts +1114 -0
  317. package/dist/db/schema.d.ts.map +1 -0
  318. package/dist/db/schema.js +129 -0
  319. package/dist/db/schema.js.map +1 -0
  320. package/dist/entrypoint.d.ts +2 -0
  321. package/dist/entrypoint.d.ts.map +1 -0
  322. package/dist/entrypoint.js +113 -0
  323. package/dist/entrypoint.js.map +1 -0
  324. package/dist/executor/agent-config.d.ts +10 -0
  325. package/dist/executor/agent-config.d.ts.map +1 -0
  326. package/dist/executor/agent-config.js +81 -0
  327. package/dist/executor/agent-config.js.map +1 -0
  328. package/dist/executor/agent-stream.d.ts +65 -0
  329. package/dist/executor/agent-stream.d.ts.map +1 -0
  330. package/dist/executor/agent-stream.js +101 -0
  331. package/dist/executor/agent-stream.js.map +1 -0
  332. package/dist/executor/auth-check.d.ts +10 -0
  333. package/dist/executor/auth-check.d.ts.map +1 -0
  334. package/dist/executor/auth-check.js +52 -0
  335. package/dist/executor/auth-check.js.map +1 -0
  336. package/dist/executor/deep-review.d.ts +61 -0
  337. package/dist/executor/deep-review.d.ts.map +1 -0
  338. package/dist/executor/deep-review.js +308 -0
  339. package/dist/executor/deep-review.js.map +1 -0
  340. package/dist/executor/executor.d.ts +27 -0
  341. package/dist/executor/executor.d.ts.map +1 -0
  342. package/dist/executor/executor.js +168 -0
  343. package/dist/executor/executor.js.map +1 -0
  344. package/dist/executor/extract-handoff.d.ts +14 -0
  345. package/dist/executor/extract-handoff.d.ts.map +1 -0
  346. package/dist/executor/extract-handoff.js +80 -0
  347. package/dist/executor/extract-handoff.js.map +1 -0
  348. package/dist/executor/handoff.d.ts +24 -0
  349. package/dist/executor/handoff.d.ts.map +1 -0
  350. package/dist/executor/handoff.js +63 -0
  351. package/dist/executor/handoff.js.map +1 -0
  352. package/dist/executor/index.d.ts +8 -0
  353. package/dist/executor/index.d.ts.map +1 -0
  354. package/dist/executor/index.js +8 -0
  355. package/dist/executor/index.js.map +1 -0
  356. package/dist/executor/mcp-resolver.d.ts +29 -0
  357. package/dist/executor/mcp-resolver.d.ts.map +1 -0
  358. package/dist/executor/mcp-resolver.js +80 -0
  359. package/dist/executor/mcp-resolver.js.map +1 -0
  360. package/dist/executor/permissions.d.ts +11 -0
  361. package/dist/executor/permissions.d.ts.map +1 -0
  362. package/dist/executor/permissions.js +32 -0
  363. package/dist/executor/permissions.js.map +1 -0
  364. package/dist/executor/profiles.d.ts +5 -0
  365. package/dist/executor/profiles.d.ts.map +1 -0
  366. package/dist/executor/profiles.js +35 -0
  367. package/dist/executor/profiles.js.map +1 -0
  368. package/dist/executor/prompt/assembler.d.ts +10 -0
  369. package/dist/executor/prompt/assembler.d.ts.map +1 -0
  370. package/dist/executor/prompt/assembler.js +28 -0
  371. package/dist/executor/prompt/assembler.js.map +1 -0
  372. package/dist/executor/prompt/index.d.ts +5 -0
  373. package/dist/executor/prompt/index.d.ts.map +1 -0
  374. package/dist/executor/prompt/index.js +5 -0
  375. package/dist/executor/prompt/index.js.map +1 -0
  376. package/dist/executor/prompt/sanitizer.d.ts +25 -0
  377. package/dist/executor/prompt/sanitizer.d.ts.map +1 -0
  378. package/dist/executor/prompt/sanitizer.js +81 -0
  379. package/dist/executor/prompt/sanitizer.js.map +1 -0
  380. package/dist/executor/prompt/schema-mapper.d.ts +7 -0
  381. package/dist/executor/prompt/schema-mapper.d.ts.map +1 -0
  382. package/dist/executor/prompt/schema-mapper.js +59 -0
  383. package/dist/executor/prompt/schema-mapper.js.map +1 -0
  384. package/dist/executor/prompt/templates.d.ts +31 -0
  385. package/dist/executor/prompt/templates.d.ts.map +1 -0
  386. package/dist/executor/prompt/templates.js +283 -0
  387. package/dist/executor/prompt/templates.js.map +1 -0
  388. package/dist/executor/ralph.d.ts +19 -0
  389. package/dist/executor/ralph.d.ts.map +1 -0
  390. package/dist/executor/ralph.js +112 -0
  391. package/dist/executor/ralph.js.map +1 -0
  392. package/dist/executor/test-quality.d.ts +117 -0
  393. package/dist/executor/test-quality.d.ts.map +1 -0
  394. package/dist/executor/test-quality.js +261 -0
  395. package/dist/executor/test-quality.js.map +1 -0
  396. package/dist/executor/validate.d.ts +15 -0
  397. package/dist/executor/validate.d.ts.map +1 -0
  398. package/dist/executor/validate.js +124 -0
  399. package/dist/executor/validate.js.map +1 -0
  400. package/dist/index.d.ts +29 -0
  401. package/dist/index.d.ts.map +1 -0
  402. package/dist/index.js +26 -0
  403. package/dist/index.js.map +1 -0
  404. package/dist/license.d.ts +18 -0
  405. package/dist/license.d.ts.map +1 -0
  406. package/dist/license.js +44 -0
  407. package/dist/license.js.map +1 -0
  408. package/dist/logger.d.ts +43 -0
  409. package/dist/logger.d.ts.map +1 -0
  410. package/dist/logger.js +91 -0
  411. package/dist/logger.js.map +1 -0
  412. package/dist/notifier/composite.d.ts +13 -0
  413. package/dist/notifier/composite.d.ts.map +1 -0
  414. package/dist/notifier/composite.js +28 -0
  415. package/dist/notifier/composite.js.map +1 -0
  416. package/dist/notifier/discord.d.ts +14 -0
  417. package/dist/notifier/discord.d.ts.map +1 -0
  418. package/dist/notifier/discord.js +105 -0
  419. package/dist/notifier/discord.js.map +1 -0
  420. package/dist/notifier/index.d.ts +6 -0
  421. package/dist/notifier/index.d.ts.map +1 -0
  422. package/dist/notifier/index.js +6 -0
  423. package/dist/notifier/index.js.map +1 -0
  424. package/dist/notifier/linear.d.ts +28 -0
  425. package/dist/notifier/linear.d.ts.map +1 -0
  426. package/dist/notifier/linear.js +138 -0
  427. package/dist/notifier/linear.js.map +1 -0
  428. package/dist/notifier/slack-alerts.d.ts +62 -0
  429. package/dist/notifier/slack-alerts.d.ts.map +1 -0
  430. package/dist/notifier/slack-alerts.js +184 -0
  431. package/dist/notifier/slack-alerts.js.map +1 -0
  432. package/dist/notifier/slack.d.ts +14 -0
  433. package/dist/notifier/slack.d.ts.map +1 -0
  434. package/dist/notifier/slack.js +146 -0
  435. package/dist/notifier/slack.js.map +1 -0
  436. package/dist/pipeline/automerge.d.ts +44 -0
  437. package/dist/pipeline/automerge.d.ts.map +1 -0
  438. package/dist/pipeline/automerge.js +135 -0
  439. package/dist/pipeline/automerge.js.map +1 -0
  440. package/dist/pipeline/config.d.ts +5 -0
  441. package/dist/pipeline/config.d.ts.map +1 -0
  442. package/dist/pipeline/config.js +68 -0
  443. package/dist/pipeline/config.js.map +1 -0
  444. package/dist/pipeline/distributed-lock.d.ts +50 -0
  445. package/dist/pipeline/distributed-lock.d.ts.map +1 -0
  446. package/dist/pipeline/distributed-lock.js +114 -0
  447. package/dist/pipeline/distributed-lock.js.map +1 -0
  448. package/dist/pipeline/error-classifier.d.ts +9 -0
  449. package/dist/pipeline/error-classifier.d.ts.map +1 -0
  450. package/dist/pipeline/error-classifier.js +25 -0
  451. package/dist/pipeline/error-classifier.js.map +1 -0
  452. package/dist/pipeline/index.d.ts +9 -0
  453. package/dist/pipeline/index.d.ts.map +1 -0
  454. package/dist/pipeline/index.js +9 -0
  455. package/dist/pipeline/index.js.map +1 -0
  456. package/dist/pipeline/pr-description.d.ts +35 -0
  457. package/dist/pipeline/pr-description.d.ts.map +1 -0
  458. package/dist/pipeline/pr-description.js +52 -0
  459. package/dist/pipeline/pr-description.js.map +1 -0
  460. package/dist/pipeline/queue.d.ts +7 -0
  461. package/dist/pipeline/queue.d.ts.map +1 -0
  462. package/dist/pipeline/queue.js +39 -0
  463. package/dist/pipeline/queue.js.map +1 -0
  464. package/dist/pipeline/router.d.ts +6 -0
  465. package/dist/pipeline/router.d.ts.map +1 -0
  466. package/dist/pipeline/router.js +19 -0
  467. package/dist/pipeline/router.js.map +1 -0
  468. package/dist/pipeline/runner.d.ts +142 -0
  469. package/dist/pipeline/runner.d.ts.map +1 -0
  470. package/dist/pipeline/runner.js +1848 -0
  471. package/dist/pipeline/runner.js.map +1 -0
  472. package/dist/pm/actions/approval-helpers.d.ts +11 -0
  473. package/dist/pm/actions/approval-helpers.d.ts.map +1 -0
  474. package/dist/pm/actions/approval-helpers.js +34 -0
  475. package/dist/pm/actions/approval-helpers.js.map +1 -0
  476. package/dist/pm/actions/cancel.d.ts +11 -0
  477. package/dist/pm/actions/cancel.d.ts.map +1 -0
  478. package/dist/pm/actions/cancel.js +68 -0
  479. package/dist/pm/actions/cancel.js.map +1 -0
  480. package/dist/pm/actions/deprioritize.d.ts +12 -0
  481. package/dist/pm/actions/deprioritize.d.ts.map +1 -0
  482. package/dist/pm/actions/deprioritize.js +55 -0
  483. package/dist/pm/actions/deprioritize.js.map +1 -0
  484. package/dist/pm/actions/promote.d.ts +11 -0
  485. package/dist/pm/actions/promote.d.ts.map +1 -0
  486. package/dist/pm/actions/promote.js +78 -0
  487. package/dist/pm/actions/promote.js.map +1 -0
  488. package/dist/pm/actions/recover-stuck.d.ts +42 -0
  489. package/dist/pm/actions/recover-stuck.d.ts.map +1 -0
  490. package/dist/pm/actions/recover-stuck.js +143 -0
  491. package/dist/pm/actions/recover-stuck.js.map +1 -0
  492. package/dist/pm/actions/recover.d.ts +18 -0
  493. package/dist/pm/actions/recover.d.ts.map +1 -0
  494. package/dist/pm/actions/recover.js +56 -0
  495. package/dist/pm/actions/recover.js.map +1 -0
  496. package/dist/pm/actions/resolve-approvals.d.ts +17 -0
  497. package/dist/pm/actions/resolve-approvals.d.ts.map +1 -0
  498. package/dist/pm/actions/resolve-approvals.js +92 -0
  499. package/dist/pm/actions/resolve-approvals.js.map +1 -0
  500. package/dist/pm/actions/start-todo.d.ts +28 -0
  501. package/dist/pm/actions/start-todo.d.ts.map +1 -0
  502. package/dist/pm/actions/start-todo.js +117 -0
  503. package/dist/pm/actions/start-todo.js.map +1 -0
  504. package/dist/pm/actions/triage.d.ts +13 -0
  505. package/dist/pm/actions/triage.d.ts.map +1 -0
  506. package/dist/pm/actions/triage.js +109 -0
  507. package/dist/pm/actions/triage.js.map +1 -0
  508. package/dist/pm/budget.d.ts +9 -0
  509. package/dist/pm/budget.d.ts.map +1 -0
  510. package/dist/pm/budget.js +62 -0
  511. package/dist/pm/budget.js.map +1 -0
  512. package/dist/pm/call-claude.d.ts +3 -0
  513. package/dist/pm/call-claude.d.ts.map +1 -0
  514. package/dist/pm/call-claude.js +37 -0
  515. package/dist/pm/call-claude.js.map +1 -0
  516. package/dist/pm/conflict-detector.d.ts +42 -0
  517. package/dist/pm/conflict-detector.d.ts.map +1 -0
  518. package/dist/pm/conflict-detector.js +116 -0
  519. package/dist/pm/conflict-detector.js.map +1 -0
  520. package/dist/pm/conflict.d.ts +20 -0
  521. package/dist/pm/conflict.d.ts.map +1 -0
  522. package/dist/pm/conflict.js +63 -0
  523. package/dist/pm/conflict.js.map +1 -0
  524. package/dist/pm/coordination.d.ts +50 -0
  525. package/dist/pm/coordination.d.ts.map +1 -0
  526. package/dist/pm/coordination.js +163 -0
  527. package/dist/pm/coordination.js.map +1 -0
  528. package/dist/pm/linear-helpers.d.ts +2 -0
  529. package/dist/pm/linear-helpers.d.ts.map +1 -0
  530. package/dist/pm/linear-helpers.js +16 -0
  531. package/dist/pm/linear-helpers.js.map +1 -0
  532. package/dist/pm/scheduler.d.ts +47 -0
  533. package/dist/pm/scheduler.d.ts.map +1 -0
  534. package/dist/pm/scheduler.js +346 -0
  535. package/dist/pm/scheduler.js.map +1 -0
  536. package/dist/pm/slack-helpers.d.ts +2 -0
  537. package/dist/pm/slack-helpers.d.ts.map +1 -0
  538. package/dist/pm/slack-helpers.js +24 -0
  539. package/dist/pm/slack-helpers.js.map +1 -0
  540. package/dist/pm/slack-interface.d.ts +133 -0
  541. package/dist/pm/slack-interface.d.ts.map +1 -0
  542. package/dist/pm/slack-interface.js +641 -0
  543. package/dist/pm/slack-interface.js.map +1 -0
  544. package/dist/pm/slack.d.ts +18 -0
  545. package/dist/pm/slack.d.ts.map +1 -0
  546. package/dist/pm/slack.js +144 -0
  547. package/dist/pm/slack.js.map +1 -0
  548. package/dist/pm/types.d.ts +99 -0
  549. package/dist/pm/types.d.ts.map +1 -0
  550. package/dist/pm/types.js +17 -0
  551. package/dist/pm/types.js.map +1 -0
  552. package/dist/repo/config.d.ts +35 -0
  553. package/dist/repo/config.d.ts.map +1 -0
  554. package/dist/repo/config.js +72 -0
  555. package/dist/repo/config.js.map +1 -0
  556. package/dist/repo/devcontainer.d.ts +33 -0
  557. package/dist/repo/devcontainer.d.ts.map +1 -0
  558. package/dist/repo/devcontainer.js +90 -0
  559. package/dist/repo/devcontainer.js.map +1 -0
  560. package/dist/repo/git.d.ts +185 -0
  561. package/dist/repo/git.d.ts.map +1 -0
  562. package/dist/repo/git.js +586 -0
  563. package/dist/repo/git.js.map +1 -0
  564. package/dist/repo/github.d.ts +56 -0
  565. package/dist/repo/github.d.ts.map +1 -0
  566. package/dist/repo/github.js +164 -0
  567. package/dist/repo/github.js.map +1 -0
  568. package/dist/repo/gitlab.d.ts +47 -0
  569. package/dist/repo/gitlab.d.ts.map +1 -0
  570. package/dist/repo/gitlab.js +91 -0
  571. package/dist/repo/gitlab.js.map +1 -0
  572. package/dist/repo/index.d.ts +7 -0
  573. package/dist/repo/index.d.ts.map +1 -0
  574. package/dist/repo/index.js +5 -0
  575. package/dist/repo/index.js.map +1 -0
  576. package/dist/repo/tech-stack.d.ts +13 -0
  577. package/dist/repo/tech-stack.d.ts.map +1 -0
  578. package/dist/repo/tech-stack.js +112 -0
  579. package/dist/repo/tech-stack.js.map +1 -0
  580. package/dist/security/index.d.ts +3 -0
  581. package/dist/security/index.d.ts.map +1 -0
  582. package/dist/security/index.js +3 -0
  583. package/dist/security/index.js.map +1 -0
  584. package/dist/security/review-checklist.d.ts +9 -0
  585. package/dist/security/review-checklist.d.ts.map +1 -0
  586. package/dist/security/review-checklist.js +46 -0
  587. package/dist/security/review-checklist.js.map +1 -0
  588. package/dist/security/sandbox.d.ts +7 -0
  589. package/dist/security/sandbox.d.ts.map +1 -0
  590. package/dist/security/sandbox.js +31 -0
  591. package/dist/security/sandbox.js.map +1 -0
  592. package/dist/server.d.ts +48 -0
  593. package/dist/server.d.ts.map +1 -0
  594. package/dist/server.js +90 -0
  595. package/dist/server.js.map +1 -0
  596. package/dist/types.d.ts +1230 -0
  597. package/dist/types.d.ts.map +1 -0
  598. package/dist/types.js +225 -0
  599. package/dist/types.js.map +1 -0
  600. package/dist/webhook/github-handler.d.ts +39 -0
  601. package/dist/webhook/github-handler.d.ts.map +1 -0
  602. package/dist/webhook/github-handler.js +439 -0
  603. package/dist/webhook/github-handler.js.map +1 -0
  604. package/dist/webhook/handler.d.ts +16 -0
  605. package/dist/webhook/handler.d.ts.map +1 -0
  606. package/dist/webhook/handler.js +171 -0
  607. package/dist/webhook/handler.js.map +1 -0
  608. package/dist/webhook/index.d.ts +5 -0
  609. package/dist/webhook/index.d.ts.map +1 -0
  610. package/dist/webhook/index.js +5 -0
  611. package/dist/webhook/index.js.map +1 -0
  612. package/dist/webhook/parser.d.ts +18 -0
  613. package/dist/webhook/parser.d.ts.map +1 -0
  614. package/dist/webhook/parser.js +30 -0
  615. package/dist/webhook/parser.js.map +1 -0
  616. package/dist/webhook/signature.d.ts +2 -0
  617. package/dist/webhook/signature.d.ts.map +1 -0
  618. package/dist/webhook/signature.js +14 -0
  619. package/dist/webhook/signature.js.map +1 -0
  620. package/package.json +40 -0
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=assembler.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assembler.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/assembler.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { assemblePrompt } from "../executor/prompt/assembler.js";
3
+ const issue = {
4
+ id: "ENG-99",
5
+ slug: "add-feature",
6
+ title: "Add feature",
7
+ description: "Add a new feature.",
8
+ acceptanceCriteria: ["Feature works"],
9
+ labels: ["feature"],
10
+ priority: 2,
11
+ };
12
+ const repo = {
13
+ url: "https://github.com/acme/app",
14
+ defaultBranch: "main",
15
+ testCommand: "npm test",
16
+ buildCommand: "npm run build",
17
+ };
18
+ const handoff = {
19
+ runId: "run-2",
20
+ issueId: "ENG-99",
21
+ stage: "reproduce",
22
+ timestamp: "2026-01-02T00:00:00Z",
23
+ summary: "Reproduced successfully",
24
+ filesChanged: ["src/feature.ts"],
25
+ approach: "Add new module",
26
+ context: {
27
+ issueIntent: "New feature",
28
+ constraints: [],
29
+ assumptions: [],
30
+ },
31
+ tokenBudget: {
32
+ contextTokensUsed: 300,
33
+ recommendedMaxTurns: 5,
34
+ },
35
+ };
36
+ describe("assemblePrompt", () => {
37
+ it("assembles triage prompt", () => {
38
+ const result = assemblePrompt("triage", issue, repo);
39
+ expect(result).toContain("triage agent");
40
+ expect(result).toContain("<issue-data>");
41
+ expect(result).toContain("<repo-context>");
42
+ });
43
+ it("assembles implement prompt with handoff", () => {
44
+ const result = assemblePrompt("implement", issue, repo, handoff);
45
+ expect(result).toContain("<previous-stage-context>");
46
+ expect(result).toContain("Reproduced successfully");
47
+ });
48
+ it("assembles review prompt with security checklist", () => {
49
+ const result = assemblePrompt("review", issue, repo);
50
+ expect(result).toContain("INJECTION");
51
+ expect(result).toContain("AUTHENTICATION");
52
+ });
53
+ it("throws for await-approval", () => {
54
+ expect(() => assemblePrompt("await-approval", issue, repo)).toThrow("await-approval is not an agent stage — no prompt needed");
55
+ });
56
+ it("all 5 agent stages assemble without error", () => {
57
+ const stages = ["triage", "reproduce", "implement", "test", "review"];
58
+ for (const stage of stages) {
59
+ expect(() => assemblePrompt(stage, issue, repo)).not.toThrow();
60
+ }
61
+ });
62
+ });
63
+ //# sourceMappingURL=assembler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assembler.test.js","sourceRoot":"","sources":["../../src/__tests__/assembler.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auth-check.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-check.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/auth-check.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,88 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { isClaudeAuthValid, resetAuthCheckCache } from "../executor/auth-check.js";
3
+ // Mock child_process.execFile
4
+ vi.mock("node:child_process", () => ({
5
+ execFile: vi.fn(),
6
+ }));
7
+ import { execFile } from "node:child_process";
8
+ const mockExecFile = vi.mocked(execFile);
9
+ function simulateSuccess() {
10
+ mockExecFile.mockImplementation((_cmd, _args, _opts, cb) => {
11
+ cb(null);
12
+ return {};
13
+ });
14
+ }
15
+ function simulateFailure() {
16
+ mockExecFile.mockImplementation((_cmd, _args, _opts, cb) => {
17
+ cb(new Error("auth failed"));
18
+ return {};
19
+ });
20
+ }
21
+ describe("isClaudeAuthValid", () => {
22
+ beforeEach(() => {
23
+ resetAuthCheckCache();
24
+ mockExecFile.mockReset();
25
+ });
26
+ afterEach(() => {
27
+ vi.useRealTimers();
28
+ });
29
+ it("returns true when claude auth status succeeds", async () => {
30
+ simulateSuccess();
31
+ const result = await isClaudeAuthValid();
32
+ expect(result).toBe(true);
33
+ expect(mockExecFile).toHaveBeenCalledTimes(1);
34
+ expect(mockExecFile).toHaveBeenCalledWith("claude", ["auth", "status"], { timeout: 10_000 }, expect.any(Function));
35
+ });
36
+ it("returns false when claude auth status fails", async () => {
37
+ simulateFailure();
38
+ const result = await isClaudeAuthValid();
39
+ expect(result).toBe(false);
40
+ expect(mockExecFile).toHaveBeenCalledTimes(1);
41
+ });
42
+ it("caches result within 5 minute TTL", async () => {
43
+ simulateSuccess();
44
+ await isClaudeAuthValid();
45
+ await isClaudeAuthValid();
46
+ await isClaudeAuthValid();
47
+ expect(mockExecFile).toHaveBeenCalledTimes(1);
48
+ });
49
+ it("re-checks after TTL expires", async () => {
50
+ vi.useFakeTimers();
51
+ simulateSuccess();
52
+ await isClaudeAuthValid();
53
+ expect(mockExecFile).toHaveBeenCalledTimes(1);
54
+ // Advance past 5 minute TTL
55
+ vi.advanceTimersByTime(5 * 60 * 1000 + 1);
56
+ await isClaudeAuthValid();
57
+ expect(mockExecFile).toHaveBeenCalledTimes(2);
58
+ });
59
+ it("concurrent callers share a single subprocess (single-flight)", async () => {
60
+ let resolveCb = null;
61
+ mockExecFile.mockImplementation((_cmd, _args, _opts, cb) => {
62
+ // Delay the callback so concurrent callers overlap
63
+ resolveCb = () => cb(null);
64
+ return {};
65
+ });
66
+ resetAuthCheckCache();
67
+ const p1 = isClaudeAuthValid();
68
+ const p2 = isClaudeAuthValid();
69
+ const p3 = isClaudeAuthValid();
70
+ // Only one execFile call should have been made
71
+ expect(mockExecFile).toHaveBeenCalledTimes(1);
72
+ // Resolve the single subprocess
73
+ resolveCb();
74
+ const [r1, r2, r3] = await Promise.all([p1, p2, p3]);
75
+ expect(r1).toBe(true);
76
+ expect(r2).toBe(true);
77
+ expect(r3).toBe(true);
78
+ });
79
+ it("resetAuthCheckCache sets result to false (unknown)", async () => {
80
+ simulateSuccess();
81
+ await isClaudeAuthValid();
82
+ expect(await isClaudeAuthValid()).toBe(true);
83
+ resetAuthCheckCache();
84
+ simulateFailure();
85
+ expect(await isClaudeAuthValid()).toBe(false);
86
+ });
87
+ });
88
+ //# sourceMappingURL=auth-check.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-check.test.js","sourceRoot":"","sources":["../../src/__tests__/auth-check.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Auto-merge decision logic tests — BEC-49
3
+ *
4
+ * Tests the four auto-merge outcomes in the pipeline runner:
5
+ * 1. autoMerge: true, small diff, no blocking findings → mergePRViaCli called
6
+ * 2. autoMerge: true, diff exceeds autoMergeMaxLines → merge skipped
7
+ * 3. autoMerge: true, blocking findings → merge skipped
8
+ * 4. autoMerge: false or not set → merge not attempted
9
+ *
10
+ * Uses the same mock strategy as e2e-pipeline.test.ts: mocks git operations
11
+ * and executor at the module level, then drives the pipeline through the
12
+ * webhook handler to exercise the full runner code path.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=auto-merge.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-merge.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/auto-merge.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,428 @@
1
+ /**
2
+ * Auto-merge decision logic tests — BEC-49
3
+ *
4
+ * Tests the four auto-merge outcomes in the pipeline runner:
5
+ * 1. autoMerge: true, small diff, no blocking findings → mergePRViaCli called
6
+ * 2. autoMerge: true, diff exceeds autoMergeMaxLines → merge skipped
7
+ * 3. autoMerge: true, blocking findings → merge skipped
8
+ * 4. autoMerge: false or not set → merge not attempted
9
+ *
10
+ * Uses the same mock strategy as e2e-pipeline.test.ts: mocks git operations
11
+ * and executor at the module level, then drives the pipeline through the
12
+ * webhook handler to exercise the full runner code path.
13
+ */
14
+ import { describe, it, expect, vi, beforeEach } from "vitest";
15
+ import { createHmac } from "node:crypto";
16
+ import { Hono } from "hono";
17
+ import { createDb } from "../db/client.js";
18
+ import { PipelineRunner, matchesAnyPattern } from "../pipeline/runner.js";
19
+ import { createWebhookHandler } from "../webhook/handler.js";
20
+ import { pipelineRuns } from "../db/schema.js";
21
+ import { eq } from "drizzle-orm";
22
+ // ---------------------------------------------------------------------------
23
+ // Module mocks
24
+ // ---------------------------------------------------------------------------
25
+ // vi.hoisted ensures these are available when vi.mock factories run (which
26
+ // are hoisted above all other code by Vitest).
27
+ const { mockMergePRViaCli, mockGetDiffLineCount, mockGetChangedFiles } = vi.hoisted(() => ({
28
+ mockMergePRViaCli: vi.fn().mockResolvedValue(true),
29
+ mockGetDiffLineCount: vi.fn().mockResolvedValue(50),
30
+ mockGetChangedFiles: vi.fn().mockResolvedValue(["src/feature.ts"]),
31
+ }));
32
+ let mockReviewFindings;
33
+ function makeHandoffArtifact(runId, issueId, stage, reviewFindings) {
34
+ return {
35
+ runId,
36
+ issueId,
37
+ stage,
38
+ timestamp: new Date().toISOString(),
39
+ summary: `Completed ${stage} stage successfully`,
40
+ filesChanged: ["src/feature.ts"],
41
+ approach: `Standard ${stage} approach`,
42
+ context: {
43
+ issueIntent: "Add user search functionality",
44
+ constraints: ["Must not break existing tests"],
45
+ assumptions: ["Input is sanitised upstream"],
46
+ ...(reviewFindings ? { reviewFindings } : {}),
47
+ },
48
+ tokenBudget: { contextTokensUsed: 150, recommendedMaxTurns: 5 },
49
+ };
50
+ }
51
+ vi.mock("../executor/executor.js", () => ({
52
+ executeStage: vi.fn().mockImplementation(async ({ runId, issueId, stage, db }) => {
53
+ const { nanoid } = await import("nanoid");
54
+ const { stageRuns: stageRunsTable } = await import("../db/schema.js");
55
+ const { eq: drizzleEq } = await import("drizzle-orm");
56
+ const stageRunId = nanoid();
57
+ await db.insert(stageRunsTable).values({
58
+ id: stageRunId,
59
+ pipelineRunId: runId,
60
+ stage,
61
+ status: "running",
62
+ });
63
+ await db
64
+ .update(stageRunsTable)
65
+ .set({
66
+ status: "completed",
67
+ completedAt: new Date(),
68
+ inputTokens: 200,
69
+ outputTokens: 100,
70
+ turns: 2,
71
+ handoffArtifact: JSON.stringify(makeHandoffArtifact(runId, issueId, stage, mockReviewFindings)),
72
+ })
73
+ .where(drizzleEq(stageRunsTable.id, stageRunId));
74
+ return {
75
+ status: "completed",
76
+ inputTokens: 200,
77
+ outputTokens: 100,
78
+ turns: 2,
79
+ handoffArtifact: makeHandoffArtifact(runId, issueId, stage, mockReviewFindings),
80
+ handoffIsStructured: true,
81
+ };
82
+ }),
83
+ }));
84
+ vi.mock("../repo/git.js", () => ({
85
+ cloneRepo: vi.fn().mockResolvedValue(undefined),
86
+ createWorktree: vi.fn().mockResolvedValue("/tmp/auto-merge-test-worktree"),
87
+ createWorktreeFromRemote: vi.fn().mockResolvedValue("/tmp/auto-merge-test-worktree"),
88
+ deleteWorktree: vi.fn().mockResolvedValue(undefined),
89
+ pushBranch: vi.fn().mockResolvedValue(undefined),
90
+ pushBranchForce: vi.fn().mockResolvedValue(undefined),
91
+ // Pure function — provide real implementation so push-strategy logic works correctly
92
+ choosePushStrategy: (branch, rebaseConflict) => {
93
+ if (rebaseConflict || branch.startsWith("agent/"))
94
+ return "force-with-lease";
95
+ return "standard";
96
+ },
97
+ rebaseBranch: vi.fn().mockResolvedValue({ success: true, hasConflicts: false }),
98
+ abortRebase: vi.fn().mockResolvedValue(undefined),
99
+ autoCommitChanges: vi.fn().mockResolvedValue(false),
100
+ getAgentCommits: vi.fn().mockResolvedValue([]),
101
+ createPRViaCli: vi
102
+ .fn()
103
+ .mockResolvedValue("https://github.com/test/repo/pull/42"),
104
+ mergePRViaCli: mockMergePRViaCli,
105
+ getDiffLineCount: mockGetDiffLineCount,
106
+ getChangedFiles: mockGetChangedFiles,
107
+ checkDuplicateBranch: vi.fn().mockResolvedValue(null),
108
+ cleanupWorktrees: vi.fn().mockResolvedValue([]),
109
+ branchName: vi
110
+ .fn()
111
+ .mockImplementation((identifier, slug) => `agent/${identifier}-${slug}`),
112
+ gitExecSafe: vi.fn().mockResolvedValue(""),
113
+ gitExecRaw: vi.fn().mockResolvedValue(""),
114
+ gitExec: vi.fn().mockResolvedValue(""),
115
+ }));
116
+ vi.mock("../repo/tech-stack.js", () => ({
117
+ detectTechStack: vi.fn().mockResolvedValue({
118
+ languages: ["typescript"],
119
+ frameworks: [],
120
+ buildSystems: ["pnpm"],
121
+ }),
122
+ }));
123
+ vi.mock("../repo/devcontainer.js", () => ({
124
+ shouldUseDevcontainer: vi.fn().mockResolvedValue(false),
125
+ devcontainerUp: vi.fn().mockResolvedValue(undefined),
126
+ devcontainerDown: vi.fn().mockResolvedValue(undefined),
127
+ }));
128
+ vi.mock("../pm/coordination.js", () => ({
129
+ upsertActiveWork: vi.fn().mockResolvedValue(undefined),
130
+ removeActiveWork: vi.fn().mockResolvedValue(undefined),
131
+ checkFileOverlap: vi.fn().mockResolvedValue({ hasOverlap: false, overlappingFiles: [], conflictingRunIds: [] }),
132
+ getModifiedFiles: vi.fn().mockResolvedValue([]),
133
+ }));
134
+ // ---------------------------------------------------------------------------
135
+ // Test helpers
136
+ // ---------------------------------------------------------------------------
137
+ const WEBHOOK_SECRET = "test-auto-merge-secret";
138
+ function signPayload(body) {
139
+ return createHmac("sha256", WEBHOOK_SECRET).update(body).digest("hex");
140
+ }
141
+ let issueCounter = 0;
142
+ function buildPayload(identifier) {
143
+ const id = identifier ?? `AM-${++issueCounter}`;
144
+ return JSON.stringify({
145
+ action: "update",
146
+ type: "Issue",
147
+ data: {
148
+ id: `issue-uuid-${id}`,
149
+ identifier: id,
150
+ title: "Auto-merge test issue",
151
+ description: "Test auto-merge logic",
152
+ priority: 2,
153
+ state: { id: "state-todo-uuid", name: "Todo" },
154
+ teamId: "team-am",
155
+ labels: [{ name: "auto-implement" }],
156
+ },
157
+ updatedFrom: { stateId: "state-backlog-uuid" },
158
+ });
159
+ }
160
+ async function postWebhook(app, body) {
161
+ const sig = signPayload(body);
162
+ const res = await app.fetch(new Request("http://localhost/webhooks/linear", {
163
+ method: "POST",
164
+ headers: {
165
+ "Content-Type": "application/json",
166
+ "Linear-Signature": sig,
167
+ },
168
+ body,
169
+ }));
170
+ return { status: res.status, json: (await res.json()) };
171
+ }
172
+ async function waitForPipeline(db, issueId, timeoutMs = 8_000) {
173
+ const deadline = Date.now() + timeoutMs;
174
+ while (Date.now() < deadline) {
175
+ const rows = await db
176
+ .select()
177
+ .from(pipelineRuns)
178
+ .where(eq(pipelineRuns.issueId, issueId));
179
+ if (rows.length > 0) {
180
+ const run = rows[0];
181
+ if (run.status === "completed" || run.status === "failed" || run.status === "aborted") {
182
+ return run;
183
+ }
184
+ }
185
+ await new Promise((r) => setTimeout(r, 50));
186
+ }
187
+ throw new Error(`Pipeline for issue ${issueId} did not complete within ${timeoutMs}ms`);
188
+ }
189
+ // ---------------------------------------------------------------------------
190
+ // Test configs
191
+ // ---------------------------------------------------------------------------
192
+ const REPO_CONFIG = {
193
+ url: "https://github.com/test/test-repo.git",
194
+ defaultBranch: "main",
195
+ testCommand: "pnpm test",
196
+ buildCommand: "pnpm build",
197
+ };
198
+ function makePipelineConfig(overrides = {}) {
199
+ return {
200
+ name: "Auto Implement",
201
+ stages: ["triage", "implement"],
202
+ retry: { maxAttempts: 0, strategy: "fail-fast" },
203
+ review: { requiredApprovals: 0 },
204
+ prStrategy: "ready",
205
+ validateHandoffs: false,
206
+ ralphIterations: 0,
207
+ reviewFixIterations: 0,
208
+ ...overrides,
209
+ };
210
+ }
211
+ // ---------------------------------------------------------------------------
212
+ // Tests
213
+ // ---------------------------------------------------------------------------
214
+ describe("Auto-merge decision logic", () => {
215
+ let db;
216
+ let notifier;
217
+ let humanReviewCalls;
218
+ beforeEach(async () => {
219
+ mockMergePRViaCli.mockClear().mockResolvedValue(true);
220
+ mockGetDiffLineCount.mockClear().mockResolvedValue(50);
221
+ mockGetChangedFiles.mockClear().mockResolvedValue(["src/feature.ts"]);
222
+ mockReviewFindings = undefined;
223
+ humanReviewCalls = [];
224
+ db = await createDb({ driver: "sqlite", connectionString: ":memory:" });
225
+ notifier = {
226
+ onPipelineStart: vi.fn(async () => { }),
227
+ onStageComplete: vi.fn(async () => { }),
228
+ onPipelineComplete: vi.fn(async () => { }),
229
+ onPipelineFailed: vi.fn(async () => { }),
230
+ onHumanReviewNeeded: vi.fn(async (run, prUrl, reason) => {
231
+ humanReviewCalls.push({ run, prUrl, reason });
232
+ }),
233
+ };
234
+ });
235
+ function buildApp(pipelineConfig) {
236
+ const runner = new PipelineRunner({
237
+ db,
238
+ notifier,
239
+ concurrency: 2,
240
+ agentRunDir: "/tmp/auto-merge-agent-runs",
241
+ repoCloneDir: "/tmp/auto-merge-repos",
242
+ });
243
+ const app = new Hono();
244
+ const webhookApp = createWebhookHandler({
245
+ webhookSecret: WEBHOOK_SECRET,
246
+ runner,
247
+ pipelineConfigs: { "auto-implement": pipelineConfig },
248
+ repoConfigs: { "team-am": REPO_CONFIG },
249
+ });
250
+ app.route("/", webhookApp);
251
+ return app;
252
+ }
253
+ // 1. autoMerge: true, small diff, no blocking findings -> merge called
254
+ it("auto-merges when enabled, diff is small, and no blocking findings", async () => {
255
+ const config = makePipelineConfig({ autoMerge: true, autoMergeMaxLines: 200 });
256
+ const app = buildApp(config);
257
+ const issueId = `AM-${++issueCounter}`;
258
+ const body = buildPayload(issueId);
259
+ await postWebhook(app, body);
260
+ const run = await waitForPipeline(db, issueId);
261
+ expect(run.status).toBe("completed");
262
+ expect(mockMergePRViaCli).toHaveBeenCalled();
263
+ expect(humanReviewCalls).toHaveLength(0);
264
+ });
265
+ // 2. autoMerge: true, diff exceeds autoMergeMaxLines -> merge skipped
266
+ it("skips auto-merge when diff exceeds autoMergeMaxLines", async () => {
267
+ mockGetDiffLineCount.mockResolvedValue(500);
268
+ const config = makePipelineConfig({ autoMerge: true, autoMergeMaxLines: 200 });
269
+ const app = buildApp(config);
270
+ const issueId = `AM-${++issueCounter}`;
271
+ const body = buildPayload(issueId);
272
+ await postWebhook(app, body);
273
+ const run = await waitForPipeline(db, issueId);
274
+ expect(run.status).toBe("completed");
275
+ expect(mockMergePRViaCli).not.toHaveBeenCalled();
276
+ expect(humanReviewCalls).toHaveLength(1);
277
+ expect(humanReviewCalls[0].reason).toMatch(/Diff too large/);
278
+ });
279
+ // 3. autoMerge: true, blocking findings -> merge skipped
280
+ it("skips auto-merge when blocking review findings exist", async () => {
281
+ mockReviewFindings = [
282
+ {
283
+ severity: "blocking",
284
+ file: "src/feature.ts",
285
+ line: 10,
286
+ category: "security",
287
+ description: "SQL injection vulnerability",
288
+ fix: "Use parameterized queries",
289
+ },
290
+ ];
291
+ const config = makePipelineConfig({ autoMerge: true, autoMergeMaxLines: 200 });
292
+ const app = buildApp(config);
293
+ const issueId = `AM-${++issueCounter}`;
294
+ const body = buildPayload(issueId);
295
+ await postWebhook(app, body);
296
+ const run = await waitForPipeline(db, issueId);
297
+ expect(run.status).toBe("completed");
298
+ expect(mockMergePRViaCli).not.toHaveBeenCalled();
299
+ expect(humanReviewCalls).toHaveLength(1);
300
+ expect(humanReviewCalls[0].reason).toMatch(/blocking finding/);
301
+ });
302
+ // 4. autoMerge: false -> merge not attempted
303
+ it("does not attempt merge when autoMerge is false", async () => {
304
+ const config = makePipelineConfig({ autoMerge: false });
305
+ const app = buildApp(config);
306
+ const issueId = `AM-${++issueCounter}`;
307
+ const body = buildPayload(issueId);
308
+ await postWebhook(app, body);
309
+ const run = await waitForPipeline(db, issueId);
310
+ expect(run.status).toBe("completed");
311
+ expect(mockMergePRViaCli).not.toHaveBeenCalled();
312
+ expect(mockGetDiffLineCount).not.toHaveBeenCalled();
313
+ });
314
+ // 4b. autoMerge not set -> merge not attempted
315
+ it("does not attempt merge when autoMerge is not set", async () => {
316
+ const config = makePipelineConfig(); // no autoMerge property
317
+ const app = buildApp(config);
318
+ const issueId = `AM-${++issueCounter}`;
319
+ const body = buildPayload(issueId);
320
+ await postWebhook(app, body);
321
+ const run = await waitForPipeline(db, issueId);
322
+ expect(run.status).toBe("completed");
323
+ expect(mockMergePRViaCli).not.toHaveBeenCalled();
324
+ expect(mockGetDiffLineCount).not.toHaveBeenCalled();
325
+ });
326
+ // Edge case: uses default autoMergeMaxLines of 200
327
+ it("uses default autoMergeMaxLines of 200 when not specified", async () => {
328
+ mockGetDiffLineCount.mockResolvedValue(199);
329
+ const config = makePipelineConfig({ autoMerge: true }); // no autoMergeMaxLines
330
+ const app = buildApp(config);
331
+ const issueId = `AM-${++issueCounter}`;
332
+ const body = buildPayload(issueId);
333
+ await postWebhook(app, body);
334
+ const run = await waitForPipeline(db, issueId);
335
+ expect(run.status).toBe("completed");
336
+ expect(mockMergePRViaCli).toHaveBeenCalled();
337
+ });
338
+ // 5. autoMergeExcludePatterns: changed file matches pattern -> merge skipped
339
+ it("skips auto-merge when a changed file matches an exclusion pattern", async () => {
340
+ mockGetChangedFiles.mockResolvedValue(["db/migrations/0001_initial.sql", "src/feature.ts"]);
341
+ const config = makePipelineConfig({
342
+ autoMerge: true,
343
+ autoMergeExcludePatterns: ["**/migrations/**"],
344
+ });
345
+ const app = buildApp(config);
346
+ const issueId = `AM-${++issueCounter}`;
347
+ const body = buildPayload(issueId);
348
+ await postWebhook(app, body);
349
+ const run = await waitForPipeline(db, issueId);
350
+ expect(run.status).toBe("completed");
351
+ expect(mockMergePRViaCli).not.toHaveBeenCalled();
352
+ expect(humanReviewCalls).toHaveLength(1);
353
+ expect(humanReviewCalls[0].reason).toMatch(/exclusion pattern/);
354
+ expect(run.autoMerged).toBeFalsy();
355
+ expect(run.autoMergeReason).toMatch(/exclusion pattern/);
356
+ });
357
+ // 6. autoMergeExcludePatterns: no changed file matches -> merge proceeds
358
+ it("merges when changed files do not match exclusion patterns", async () => {
359
+ mockGetChangedFiles.mockResolvedValue(["src/feature.ts", "src/utils.ts"]);
360
+ const config = makePipelineConfig({
361
+ autoMerge: true,
362
+ autoMergeExcludePatterns: ["**/migrations/**", "infra/**"],
363
+ });
364
+ const app = buildApp(config);
365
+ const issueId = `AM-${++issueCounter}`;
366
+ const body = buildPayload(issueId);
367
+ await postWebhook(app, body);
368
+ const run = await waitForPipeline(db, issueId);
369
+ expect(run.status).toBe("completed");
370
+ expect(mockMergePRViaCli).toHaveBeenCalled();
371
+ expect(humanReviewCalls).toHaveLength(0);
372
+ });
373
+ // 7. Audit log: autoMerged and autoMergeReason are persisted to DB
374
+ it("persists autoMerged=true and reason to DB on successful auto-merge", async () => {
375
+ const config = makePipelineConfig({ autoMerge: true });
376
+ const app = buildApp(config);
377
+ const issueId = `AM-${++issueCounter}`;
378
+ const body = buildPayload(issueId);
379
+ await postWebhook(app, body);
380
+ const run = await waitForPipeline(db, issueId);
381
+ expect(run.status).toBe("completed");
382
+ expect(mockMergePRViaCli).toHaveBeenCalled();
383
+ expect(run.autoMerged).toBeTruthy();
384
+ expect(run.autoMergeReason).toMatch(/auto-merged successfully/);
385
+ });
386
+ // 8. Audit log: autoMerged=false and reason stored when merge is skipped
387
+ it("persists autoMerged=false and skip reason to DB when diff is too large", async () => {
388
+ mockGetDiffLineCount.mockResolvedValue(500);
389
+ const config = makePipelineConfig({ autoMerge: true, autoMergeMaxLines: 200 });
390
+ const app = buildApp(config);
391
+ const issueId = `AM-${++issueCounter}`;
392
+ const body = buildPayload(issueId);
393
+ await postWebhook(app, body);
394
+ const run = await waitForPipeline(db, issueId);
395
+ expect(run.status).toBe("completed");
396
+ expect(mockMergePRViaCli).not.toHaveBeenCalled();
397
+ expect(run.autoMerged).toBeFalsy();
398
+ expect(run.autoMergeReason).toMatch(/Diff too large/);
399
+ });
400
+ });
401
+ // ---------------------------------------------------------------------------
402
+ // Unit tests for matchesAnyPattern helper
403
+ // ---------------------------------------------------------------------------
404
+ describe("matchesAnyPattern", () => {
405
+ it("matches simple filename pattern", () => {
406
+ expect(matchesAnyPattern("src/foo.ts", ["**/*.ts"])).toBe(true);
407
+ expect(matchesAnyPattern("src/foo.js", ["**/*.ts"])).toBe(false);
408
+ });
409
+ it("matches ** glob across multiple path segments", () => {
410
+ expect(matchesAnyPattern("db/migrations/0001_init.sql", ["**/migrations/**"])).toBe(true);
411
+ expect(matchesAnyPattern("src/feature.ts", ["**/migrations/**"])).toBe(false);
412
+ });
413
+ it("matches prefix wildcard", () => {
414
+ expect(matchesAnyPattern("infra/terraform/main.tf", ["infra/**"])).toBe(true);
415
+ expect(matchesAnyPattern("src/infra.ts", ["infra/**"])).toBe(false);
416
+ });
417
+ it("returns false for empty patterns array", () => {
418
+ expect(matchesAnyPattern("src/anything.ts", [])).toBe(false);
419
+ });
420
+ it("matches any pattern in the list", () => {
421
+ expect(matchesAnyPattern("src/db/schema.sql", ["**/migrations/**", "**/*.sql", "infra/**"])).toBe(true);
422
+ });
423
+ it("handles ? single-character wildcard", () => {
424
+ expect(matchesAnyPattern("src/foo.ts", ["src/f?o.ts"])).toBe(true);
425
+ expect(matchesAnyPattern("src/fooo.ts", ["src/f?o.ts"])).toBe(false);
426
+ });
427
+ });
428
+ //# sourceMappingURL=auto-merge.test.js.map