reviewflow 3.26.0 → 3.27.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 (306) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/config/projectConfig.d.ts +1 -0
  3. package/dist/config/projectConfig.d.ts.map +1 -1
  4. package/dist/config/projectConfig.js +17 -0
  5. package/dist/config/projectConfig.js.map +1 -1
  6. package/dist/dashboard/index.html +77 -2
  7. package/dist/dashboard/modules/headerCapacityBadge.d.ts +33 -0
  8. package/dist/dashboard/modules/headerCapacityBadge.d.ts.map +1 -0
  9. package/dist/dashboard/modules/headerCapacityBadge.js +53 -0
  10. package/dist/dashboard/modules/headerCapacityBadge.js.map +1 -0
  11. package/dist/dashboard/modules/i18n.d.ts.map +1 -1
  12. package/dist/dashboard/modules/i18n.js +4 -0
  13. package/dist/dashboard/modules/i18n.js.map +1 -1
  14. package/dist/dashboard/modules/settingsModal.d.ts +17 -0
  15. package/dist/dashboard/modules/settingsModal.d.ts.map +1 -1
  16. package/dist/dashboard/modules/settingsModal.js +38 -0
  17. package/dist/dashboard/modules/settingsModal.js.map +1 -1
  18. package/dist/dashboard/modules/worktreePanel.d.ts +40 -0
  19. package/dist/dashboard/modules/worktreePanel.d.ts.map +1 -1
  20. package/dist/dashboard/modules/worktreePanel.js +98 -1
  21. package/dist/dashboard/modules/worktreePanel.js.map +1 -1
  22. package/dist/dashboard/styles.css +125 -1
  23. package/dist/frameworks/claude/claudeInvoker.d.ts.map +1 -1
  24. package/dist/frameworks/claude/claudeInvoker.js +5 -10
  25. package/dist/frameworks/claude/claudeInvoker.js.map +1 -1
  26. package/dist/frameworks/config/configLoader.d.ts +1 -0
  27. package/dist/frameworks/config/configLoader.d.ts.map +1 -1
  28. package/dist/frameworks/config/configLoader.js +11 -0
  29. package/dist/frameworks/config/configLoader.js.map +1 -1
  30. package/dist/frameworks/queue/pQueueAdapter.d.ts +17 -0
  31. package/dist/frameworks/queue/pQueueAdapter.d.ts.map +1 -1
  32. package/dist/frameworks/queue/pQueueAdapter.js +103 -40
  33. package/dist/frameworks/queue/pQueueAdapter.js.map +1 -1
  34. package/dist/frameworks/queue/projectSemaphore.d.ts +26 -0
  35. package/dist/frameworks/queue/projectSemaphore.d.ts.map +1 -0
  36. package/dist/frameworks/queue/projectSemaphore.js +79 -0
  37. package/dist/frameworks/queue/projectSemaphore.js.map +1 -0
  38. package/dist/frameworks/settings/runtimeSettings.d.ts +3 -0
  39. package/dist/frameworks/settings/runtimeSettings.d.ts.map +1 -1
  40. package/dist/frameworks/settings/runtimeSettings.js +14 -0
  41. package/dist/frameworks/settings/runtimeSettings.js.map +1 -1
  42. package/dist/main/dependencies.d.ts +4 -0
  43. package/dist/main/dependencies.d.ts.map +1 -1
  44. package/dist/main/dependencies.js +8 -0
  45. package/dist/main/dependencies.js.map +1 -1
  46. package/dist/main/routes.d.ts.map +1 -1
  47. package/dist/main/routes.js +32 -3
  48. package/dist/main/routes.js.map +1 -1
  49. package/dist/main/server.d.ts.map +1 -1
  50. package/dist/main/server.js +69 -1
  51. package/dist/main/server.js.map +1 -1
  52. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.d.ts +2 -0
  53. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.d.ts.map +1 -0
  54. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.js +4 -0
  55. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.js.map +1 -0
  56. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.schema.d.ts +7 -0
  57. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.schema.d.ts.map +1 -0
  58. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.schema.js +10 -0
  59. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.schema.js.map +1 -0
  60. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.d.ts +18 -0
  61. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.d.ts.map +1 -0
  62. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.js +28 -0
  63. package/dist/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.js.map +1 -0
  64. package/dist/modules/cli-configuration/entities/repositoriesList/repositoriesList.gateway.d.ts +9 -0
  65. package/dist/modules/cli-configuration/entities/repositoriesList/repositoriesList.gateway.d.ts.map +1 -0
  66. package/dist/modules/cli-configuration/entities/repositoriesList/repositoriesList.gateway.js +2 -0
  67. package/dist/modules/cli-configuration/entities/repositoriesList/repositoriesList.gateway.js.map +1 -0
  68. package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.d.ts +1 -0
  69. package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.d.ts.map +1 -1
  70. package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js +26 -0
  71. package/dist/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js.map +1 -1
  72. package/dist/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.d.ts +8 -0
  73. package/dist/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.d.ts.map +1 -0
  74. package/dist/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.js +14 -0
  75. package/dist/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.js.map +1 -0
  76. package/dist/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.d.ts +26 -0
  77. package/dist/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.d.ts.map +1 -0
  78. package/dist/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.js +24 -0
  79. package/dist/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.js.map +1 -0
  80. package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.d.ts +2 -1
  81. package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.d.ts.map +1 -1
  82. package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.js +29 -5
  83. package/dist/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.js.map +1 -1
  84. package/dist/modules/review-execution/entities/job/jobHistory.gateway.d.ts +10 -0
  85. package/dist/modules/review-execution/entities/job/jobHistory.gateway.d.ts.map +1 -0
  86. package/dist/modules/review-execution/entities/job/jobHistory.gateway.js +2 -0
  87. package/dist/modules/review-execution/entities/job/jobHistory.gateway.js.map +1 -0
  88. package/dist/modules/review-execution/entities/job/jobRecord.guard.d.ts +13 -0
  89. package/dist/modules/review-execution/entities/job/jobRecord.guard.d.ts.map +1 -0
  90. package/dist/modules/review-execution/entities/job/jobRecord.guard.js +4 -0
  91. package/dist/modules/review-execution/entities/job/jobRecord.guard.js.map +1 -0
  92. package/dist/modules/review-execution/entities/job/jobRecord.schema.d.ts +33 -0
  93. package/dist/modules/review-execution/entities/job/jobRecord.schema.d.ts.map +1 -0
  94. package/dist/modules/review-execution/entities/job/jobRecord.schema.js +15 -0
  95. package/dist/modules/review-execution/entities/job/jobRecord.schema.js.map +1 -0
  96. package/dist/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.d.ts +19 -0
  97. package/dist/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.d.ts.map +1 -0
  98. package/dist/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.js +120 -0
  99. package/dist/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.js.map +1 -0
  100. package/dist/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.d.ts +17 -0
  101. package/dist/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.d.ts.map +1 -0
  102. package/dist/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.js +11 -0
  103. package/dist/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.js.map +1 -0
  104. package/dist/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.d.ts +18 -0
  105. package/dist/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.d.ts.map +1 -0
  106. package/dist/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.js +58 -0
  107. package/dist/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.js.map +1 -0
  108. package/dist/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.d.ts +16 -0
  109. package/dist/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.d.ts.map +1 -0
  110. package/dist/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.js +12 -0
  111. package/dist/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.js.map +1 -0
  112. package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.d.ts +4 -0
  113. package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.d.ts.map +1 -1
  114. package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.js +2 -0
  115. package/dist/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.js.map +1 -1
  116. package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.d.ts +12 -0
  117. package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.d.ts.map +1 -1
  118. package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.js +8 -0
  119. package/dist/modules/statistics-insights/interface-adapters/presenters/overview.presenter.js.map +1 -1
  120. package/dist/modules/statistics-insights/services/fetchDiffStatsSafely.d.ts +5 -0
  121. package/dist/modules/statistics-insights/services/fetchDiffStatsSafely.d.ts.map +1 -0
  122. package/dist/modules/statistics-insights/services/fetchDiffStatsSafely.js +10 -0
  123. package/dist/modules/statistics-insights/services/fetchDiffStatsSafely.js.map +1 -0
  124. package/dist/modules/statistics-insights/services/statsService.d.ts +5 -0
  125. package/dist/modules/statistics-insights/services/statsService.d.ts.map +1 -1
  126. package/dist/modules/statistics-insights/services/statsService.js +5 -0
  127. package/dist/modules/statistics-insights/services/statsService.js.map +1 -1
  128. package/dist/modules/worktree-management/entities/gitCommand/gitCommand.gateway.d.ts +1 -1
  129. package/dist/modules/worktree-management/entities/gitCommand/gitCommand.gateway.d.ts.map +1 -1
  130. package/dist/modules/worktree-management/entities/worktree/worktree.gateway.d.ts +1 -0
  131. package/dist/modules/worktree-management/entities/worktree/worktree.gateway.d.ts.map +1 -1
  132. package/dist/modules/worktree-management/entities/worktree/worktreeHealth.schema.d.ts +44 -0
  133. package/dist/modules/worktree-management/entities/worktree/worktreeHealth.schema.d.ts.map +1 -0
  134. package/dist/modules/worktree-management/entities/worktree/worktreeHealth.schema.js +31 -0
  135. package/dist/modules/worktree-management/entities/worktree/worktreeHealth.schema.js.map +1 -0
  136. package/dist/modules/worktree-management/entities/worktree/worktreeHealthProbe.gateway.d.ts +20 -0
  137. package/dist/modules/worktree-management/entities/worktree/worktreeHealthProbe.gateway.d.ts.map +1 -0
  138. package/dist/modules/worktree-management/entities/worktree/worktreeHealthProbe.gateway.js +2 -0
  139. package/dist/modules/worktree-management/entities/worktree/worktreeHealthProbe.gateway.js.map +1 -0
  140. package/dist/modules/worktree-management/interface-adapters/controllers/http/worktreeOverview.routes.d.ts +6 -0
  141. package/dist/modules/worktree-management/interface-adapters/controllers/http/worktreeOverview.routes.d.ts.map +1 -1
  142. package/dist/modules/worktree-management/interface-adapters/controllers/http/worktreeOverview.routes.js +52 -1
  143. package/dist/modules/worktree-management/interface-adapters/controllers/http/worktreeOverview.routes.js.map +1 -1
  144. package/dist/modules/worktree-management/interface-adapters/gateways/worktree.fileSystem.gateway.d.ts.map +1 -1
  145. package/dist/modules/worktree-management/interface-adapters/gateways/worktree.fileSystem.gateway.js +5 -1
  146. package/dist/modules/worktree-management/interface-adapters/gateways/worktree.fileSystem.gateway.js.map +1 -1
  147. package/dist/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.d.ts +14 -0
  148. package/dist/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.d.ts.map +1 -0
  149. package/dist/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.js +97 -0
  150. package/dist/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.js.map +1 -0
  151. package/dist/modules/worktree-management/interface-adapters/presenters/worktreePanel.presenter.d.ts +20 -0
  152. package/dist/modules/worktree-management/interface-adapters/presenters/worktreePanel.presenter.d.ts.map +1 -1
  153. package/dist/modules/worktree-management/interface-adapters/presenters/worktreePanel.presenter.js +58 -0
  154. package/dist/modules/worktree-management/interface-adapters/presenters/worktreePanel.presenter.js.map +1 -1
  155. package/dist/modules/worktree-management/services/forceCleanupLock.d.ts +10 -0
  156. package/dist/modules/worktree-management/services/forceCleanupLock.d.ts.map +1 -0
  157. package/dist/modules/worktree-management/services/forceCleanupLock.js +14 -0
  158. package/dist/modules/worktree-management/services/forceCleanupLock.js.map +1 -0
  159. package/dist/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.d.ts +13 -0
  160. package/dist/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.d.ts.map +1 -0
  161. package/dist/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.js +35 -0
  162. package/dist/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.js.map +1 -0
  163. package/dist/modules/worktree-management/usecases/removeWorktree.usecase.d.ts +1 -0
  164. package/dist/modules/worktree-management/usecases/removeWorktree.usecase.d.ts.map +1 -1
  165. package/dist/modules/worktree-management/usecases/removeWorktree.usecase.js +2 -1
  166. package/dist/modules/worktree-management/usecases/removeWorktree.usecase.js.map +1 -1
  167. package/dist/tests/acceptance/175-worktree-failure-visibility.acceptance.test.d.ts +12 -0
  168. package/dist/tests/acceptance/175-worktree-failure-visibility.acceptance.test.d.ts.map +1 -0
  169. package/dist/tests/acceptance/175-worktree-failure-visibility.acceptance.test.js +293 -0
  170. package/dist/tests/acceptance/175-worktree-failure-visibility.acceptance.test.js.map +1 -0
  171. package/dist/tests/acceptance/176-job-history-persistence.acceptance.test.d.ts +13 -0
  172. package/dist/tests/acceptance/176-job-history-persistence.acceptance.test.d.ts.map +1 -0
  173. package/dist/tests/acceptance/176-job-history-persistence.acceptance.test.js +261 -0
  174. package/dist/tests/acceptance/176-job-history-persistence.acceptance.test.js.map +1 -0
  175. package/dist/tests/acceptance/186-per-project-concurrency-cap.acceptance.test.d.ts +16 -0
  176. package/dist/tests/acceptance/186-per-project-concurrency-cap.acceptance.test.d.ts.map +1 -0
  177. package/dist/tests/acceptance/186-per-project-concurrency-cap.acceptance.test.js +391 -0
  178. package/dist/tests/acceptance/186-per-project-concurrency-cap.acceptance.test.js.map +1 -0
  179. package/dist/tests/acceptance/47-capture-git-diff-stats.acceptance.test.d.ts +18 -0
  180. package/dist/tests/acceptance/47-capture-git-diff-stats.acceptance.test.d.ts.map +1 -0
  181. package/dist/tests/acceptance/47-capture-git-diff-stats.acceptance.test.js +221 -0
  182. package/dist/tests/acceptance/47-capture-git-diff-stats.acceptance.test.js.map +1 -0
  183. package/dist/tests/factories/config.factory.d.ts.map +1 -1
  184. package/dist/tests/factories/config.factory.js +1 -0
  185. package/dist/tests/factories/config.factory.js.map +1 -1
  186. package/dist/tests/factories/jobRecord.factory.d.ts +5 -0
  187. package/dist/tests/factories/jobRecord.factory.d.ts.map +1 -0
  188. package/dist/tests/factories/jobRecord.factory.js +18 -0
  189. package/dist/tests/factories/jobRecord.factory.js.map +1 -0
  190. package/dist/tests/factories/projectConcurrencyCap.factory.d.ts +5 -0
  191. package/dist/tests/factories/projectConcurrencyCap.factory.d.ts.map +1 -0
  192. package/dist/tests/factories/projectConcurrencyCap.factory.js +8 -0
  193. package/dist/tests/factories/projectConcurrencyCap.factory.js.map +1 -0
  194. package/dist/tests/factories/worktreeHealth.factory.d.ts +22 -0
  195. package/dist/tests/factories/worktreeHealth.factory.d.ts.map +1 -0
  196. package/dist/tests/factories/worktreeHealth.factory.js +53 -0
  197. package/dist/tests/factories/worktreeHealth.factory.js.map +1 -0
  198. package/dist/tests/stubs/jobHistory.stub.d.ts +13 -0
  199. package/dist/tests/stubs/jobHistory.stub.d.ts.map +1 -0
  200. package/dist/tests/stubs/jobHistory.stub.js +63 -0
  201. package/dist/tests/stubs/jobHistory.stub.js.map +1 -0
  202. package/dist/tests/stubs/queueCapacityPort.stub.d.ts +8 -0
  203. package/dist/tests/stubs/queueCapacityPort.stub.d.ts.map +1 -0
  204. package/dist/tests/stubs/queueCapacityPort.stub.js +11 -0
  205. package/dist/tests/stubs/queueCapacityPort.stub.js.map +1 -0
  206. package/dist/tests/stubs/repositoriesListGateway.stub.d.ts +7 -0
  207. package/dist/tests/stubs/repositoriesListGateway.stub.d.ts.map +1 -0
  208. package/dist/tests/stubs/repositoriesListGateway.stub.js +10 -0
  209. package/dist/tests/stubs/repositoriesListGateway.stub.js.map +1 -0
  210. package/dist/tests/stubs/worktreeHealthProbe.stub.d.ts +11 -0
  211. package/dist/tests/stubs/worktreeHealthProbe.stub.d.ts.map +1 -0
  212. package/dist/tests/stubs/worktreeHealthProbe.stub.js +26 -0
  213. package/dist/tests/stubs/worktreeHealthProbe.stub.js.map +1 -0
  214. package/dist/tests/units/cli/cli.integration.test.js +6 -4
  215. package/dist/tests/units/cli/cli.integration.test.js.map +1 -1
  216. package/dist/tests/units/dashboard/modules/headerCapacityBadge.test.d.ts +2 -0
  217. package/dist/tests/units/dashboard/modules/headerCapacityBadge.test.d.ts.map +1 -0
  218. package/dist/tests/units/dashboard/modules/headerCapacityBadge.test.js +55 -0
  219. package/dist/tests/units/dashboard/modules/headerCapacityBadge.test.js.map +1 -0
  220. package/dist/tests/units/dashboard/modules/notifications.test.js +17 -0
  221. package/dist/tests/units/dashboard/modules/notifications.test.js.map +1 -1
  222. package/dist/tests/units/dashboard/modules/settingsModal.test.js +7 -0
  223. package/dist/tests/units/dashboard/modules/settingsModal.test.js.map +1 -1
  224. package/dist/tests/units/dashboard/modules/worktreePanel.test.js +123 -1
  225. package/dist/tests/units/dashboard/modules/worktreePanel.test.js.map +1 -1
  226. package/dist/tests/units/frameworks/config/configLoader.test.js +28 -0
  227. package/dist/tests/units/frameworks/config/configLoader.test.js.map +1 -1
  228. package/dist/tests/units/frameworks/queue/pQueueAdapter.test.js +125 -0
  229. package/dist/tests/units/frameworks/queue/pQueueAdapter.test.js.map +1 -1
  230. package/dist/tests/units/frameworks/queue/projectSemaphore.test.d.ts +2 -0
  231. package/dist/tests/units/frameworks/queue/projectSemaphore.test.d.ts.map +1 -0
  232. package/dist/tests/units/frameworks/queue/projectSemaphore.test.js +92 -0
  233. package/dist/tests/units/frameworks/queue/projectSemaphore.test.js.map +1 -0
  234. package/dist/tests/units/frameworks/settings/runtimeSettings.test.js +34 -2
  235. package/dist/tests/units/frameworks/settings/runtimeSettings.test.js.map +1 -1
  236. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.test.d.ts +2 -0
  237. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.test.d.ts.map +1 -0
  238. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.test.js +22 -0
  239. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.guard.test.js.map +1 -0
  240. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.test.d.ts +2 -0
  241. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.test.d.ts.map +1 -0
  242. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.test.js +85 -0
  243. package/dist/tests/units/modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.test.js.map +1 -0
  244. package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.test.js +91 -0
  245. package/dist/tests/units/modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.test.js.map +1 -1
  246. package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.test.d.ts +2 -0
  247. package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.test.d.ts.map +1 -0
  248. package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.test.js +29 -0
  249. package/dist/tests/units/modules/cli-configuration/interface-adapters/gateways/repositoriesList.runtimeConfig.gateway.test.js.map +1 -0
  250. package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.test.d.ts +2 -0
  251. package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.test.d.ts.map +1 -0
  252. package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.test.js +126 -0
  253. package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.test.js.map +1 -0
  254. package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.test.js +78 -0
  255. package/dist/tests/units/modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.test.js.map +1 -1
  256. package/dist/tests/units/modules/review-execution/entities/job/jobRecord.guard.test.d.ts +2 -0
  257. package/dist/tests/units/modules/review-execution/entities/job/jobRecord.guard.test.d.ts.map +1 -0
  258. package/dist/tests/units/modules/review-execution/entities/job/jobRecord.guard.test.js +48 -0
  259. package/dist/tests/units/modules/review-execution/entities/job/jobRecord.guard.test.js.map +1 -0
  260. package/dist/tests/units/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.test.d.ts +2 -0
  261. package/dist/tests/units/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.test.d.ts.map +1 -0
  262. package/dist/tests/units/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.test.js +134 -0
  263. package/dist/tests/units/modules/review-execution/interface-adapters/gateways/fileSystem/jobHistory.fileSystem.gateway.test.js.map +1 -0
  264. package/dist/tests/units/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.test.d.ts +2 -0
  265. package/dist/tests/units/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.test.d.ts.map +1 -0
  266. package/dist/tests/units/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.test.js +38 -0
  267. package/dist/tests/units/modules/review-execution/usecases/jobHistory/loadRecentJobHistory.usecase.test.js.map +1 -0
  268. package/dist/tests/units/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.test.d.ts +2 -0
  269. package/dist/tests/units/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.test.d.ts.map +1 -0
  270. package/dist/tests/units/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.test.js +126 -0
  271. package/dist/tests/units/modules/review-execution/usecases/jobHistory/persistJobRecord.usecase.test.js.map +1 -0
  272. package/dist/tests/units/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.test.d.ts +2 -0
  273. package/dist/tests/units/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.test.d.ts.map +1 -0
  274. package/dist/tests/units/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.test.js +42 -0
  275. package/dist/tests/units/modules/review-execution/usecases/jobHistory/pruneJobHistory.usecase.test.js.map +1 -0
  276. package/dist/tests/units/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.test.js +28 -0
  277. package/dist/tests/units/modules/statistics-insights/interface-adapters/controllers/http/overview.routes.test.js.map +1 -1
  278. package/dist/tests/units/modules/statistics-insights/interface-adapters/presenters/overview.presenter.test.js +39 -0
  279. package/dist/tests/units/modules/statistics-insights/interface-adapters/presenters/overview.presenter.test.js.map +1 -1
  280. package/dist/tests/units/modules/worktree-management/entities/worktree/worktreeHealth.schema.test.d.ts +2 -0
  281. package/dist/tests/units/modules/worktree-management/entities/worktree/worktreeHealth.schema.test.d.ts.map +1 -0
  282. package/dist/tests/units/modules/worktree-management/entities/worktree/worktreeHealth.schema.test.js +50 -0
  283. package/dist/tests/units/modules/worktree-management/entities/worktree/worktreeHealth.schema.test.js.map +1 -0
  284. package/dist/tests/units/modules/worktree-management/interface-adapters/controllers/http/worktreeOverview.routes.test.js +106 -0
  285. package/dist/tests/units/modules/worktree-management/interface-adapters/controllers/http/worktreeOverview.routes.test.js.map +1 -1
  286. package/dist/tests/units/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.test.d.ts +2 -0
  287. package/dist/tests/units/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.test.d.ts.map +1 -0
  288. package/dist/tests/units/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.test.js +114 -0
  289. package/dist/tests/units/modules/worktree-management/interface-adapters/gateways/worktreeHealthProbe.fileSystem.gateway.test.js.map +1 -0
  290. package/dist/tests/units/modules/worktree-management/interface-adapters/presenters/worktreePanel.presenter.test.js +140 -0
  291. package/dist/tests/units/modules/worktree-management/interface-adapters/presenters/worktreePanel.presenter.test.js.map +1 -1
  292. package/dist/tests/units/modules/worktree-management/services/forceCleanupLock.test.d.ts +2 -0
  293. package/dist/tests/units/modules/worktree-management/services/forceCleanupLock.test.d.ts.map +1 -0
  294. package/dist/tests/units/modules/worktree-management/services/forceCleanupLock.test.js +29 -0
  295. package/dist/tests/units/modules/worktree-management/services/forceCleanupLock.test.js.map +1 -0
  296. package/dist/tests/units/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.test.d.ts +2 -0
  297. package/dist/tests/units/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.test.d.ts.map +1 -0
  298. package/dist/tests/units/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.test.js +124 -0
  299. package/dist/tests/units/modules/worktree-management/usecases/detectDegradedWorktrees.usecase.test.js.map +1 -0
  300. package/dist/tests/units/modules/worktree-management/usecases/removeWorktree.usecase.test.js +27 -0
  301. package/dist/tests/units/modules/worktree-management/usecases/removeWorktree.usecase.test.js.map +1 -1
  302. package/dist/tests/units/services/statsService.summary.test.d.ts +2 -0
  303. package/dist/tests/units/services/statsService.summary.test.d.ts.map +1 -0
  304. package/dist/tests/units/services/statsService.summary.test.js +43 -0
  305. package/dist/tests/units/services/statsService.summary.test.js.map +1 -0
  306. package/package.json +1 -1
@@ -0,0 +1,391 @@
1
+ /**
2
+ * SPEC-186 — Per-project concurrency cap for reviews.
3
+ *
4
+ * Outer-loop acceptance test (SDD). Stays RED while the inside-out
5
+ * implementation is in progress, flips GREEN once all layers are wired.
6
+ *
7
+ * Source of truth: docs/specs/186-per-project-concurrency-cap.md (17 DSL scenarios).
8
+ *
9
+ * The scenarios are grouped by Rule:
10
+ * - Cap validation (range + integer + empty) → 7 scenarios.
11
+ * - Missing key fallback → 1 scenario.
12
+ * - Runtime enforcement (held / running / lower / raise) → 4 scenarios.
13
+ * - Dashboard header arithmetic (sum / running / saturation / add / remove) → 5 scenarios.
14
+ */
15
+ import Fastify from 'fastify';
16
+ import { describe, expect, it } from 'vitest';
17
+ import { projectConfigRoutes } from '../../modules/cli-configuration/interface-adapters/controllers/http/projectConfig.routes.js';
18
+ import { UpdateProjectConfigUseCase } from '../../modules/cli-configuration/usecases/projectConfig/updateProjectConfig.usecase.js';
19
+ import { StubProjectConfigGateway } from '../../tests/stubs/projectConfigGateway.stub.js';
20
+ import { StubRepositoriesListGateway } from '../../tests/stubs/repositoriesListGateway.stub.js';
21
+ import { StubQueueCapacityPort } from '../../tests/stubs/queueCapacityPort.stub.js';
22
+ import { RecomputeGlobalConcurrencyUseCase } from '../../modules/cli-configuration/usecases/projectConfig/recomputeGlobalConcurrency.usecase.js';
23
+ import { ProjectSemaphore } from '../../frameworks/queue/projectSemaphore.js';
24
+ import { effectiveProjectConcurrencyCap, DEFAULT_PROJECT_CONCURRENCY_CAP, PROJECT_CAP_OUT_OF_RANGE_MESSAGE, PROJECT_CAP_NOT_INTEGER_MESSAGE, PROJECT_CAP_REQUIRED_MESSAGE, } from '../../modules/cli-configuration/entities/projectConcurrencyCap/projectConcurrencyCap.valueObject.js';
25
+ import { OverviewPresenter } from '../../modules/statistics-insights/interface-adapters/presenters/overview.presenter.js';
26
+ import { RepositoryConfigFactory } from '../../tests/factories/repositoryConfig.factory.js';
27
+ import { validateMaxConcurrentReviews, buildSettingsViewModel, renderSettingsModalHtml, } from '../../dashboard/modules/settingsModal.js';
28
+ import { buildHeaderCapacityViewModel } from '../../dashboard/modules/headerCapacityBadge.js';
29
+ function baseProjectConfig(overrides = {}) {
30
+ return {
31
+ github: false,
32
+ gitlab: true,
33
+ defaultModel: 'sonnet',
34
+ reviewSkill: 'review-front',
35
+ reviewFollowupSkill: 'review-followup',
36
+ language: 'fr',
37
+ retentionDays: 14,
38
+ ...overrides,
39
+ };
40
+ }
41
+ async function buildPatchApp(gateway) {
42
+ const app = Fastify();
43
+ const updateProjectConfig = new UpdateProjectConfigUseCase(gateway);
44
+ await app.register(projectConfigRoutes, { updateProjectConfig });
45
+ return app;
46
+ }
47
+ describe('Acceptance — SPEC-186: Per-project concurrency cap', () => {
48
+ describe('Rule: cap validation (range 1-10, integer, required) — server PATCH', () => {
49
+ it('valid update {maxConcurrentReviews: 4} → 200 + persisted "4"', async () => {
50
+ const gateway = new StubProjectConfigGateway();
51
+ gateway.set('/home/user/proj', baseProjectConfig());
52
+ const app = await buildPatchApp(gateway);
53
+ const response = await app.inject({
54
+ method: 'PATCH',
55
+ url: '/api/project-config?path=' + encodeURIComponent('/home/user/proj'),
56
+ payload: { maxConcurrentReviews: 4 },
57
+ });
58
+ expect(response.statusCode).toBe(200);
59
+ expect(gateway.get('/home/user/proj')?.maxConcurrentReviews).toBe(4);
60
+ await app.close();
61
+ });
62
+ it('value too low {maxConcurrentReviews: 0} → rejects "La valeur doit être comprise entre 1 et 10"', async () => {
63
+ const gateway = new StubProjectConfigGateway();
64
+ gateway.set('/home/user/proj', baseProjectConfig());
65
+ const app = await buildPatchApp(gateway);
66
+ const response = await app.inject({
67
+ method: 'PATCH',
68
+ url: '/api/project-config?path=' + encodeURIComponent('/home/user/proj'),
69
+ payload: { maxConcurrentReviews: 0 },
70
+ });
71
+ expect(response.statusCode).toBe(400);
72
+ expect(response.json().error).toBe(PROJECT_CAP_OUT_OF_RANGE_MESSAGE);
73
+ await app.close();
74
+ });
75
+ it('value too high {maxConcurrentReviews: 11} → rejects "La valeur doit être comprise entre 1 et 10"', async () => {
76
+ const gateway = new StubProjectConfigGateway();
77
+ gateway.set('/home/user/proj', baseProjectConfig());
78
+ const app = await buildPatchApp(gateway);
79
+ const response = await app.inject({
80
+ method: 'PATCH',
81
+ url: '/api/project-config?path=' + encodeURIComponent('/home/user/proj'),
82
+ payload: { maxConcurrentReviews: 11 },
83
+ });
84
+ expect(response.statusCode).toBe(400);
85
+ expect(response.json().error).toBe(PROJECT_CAP_OUT_OF_RANGE_MESSAGE);
86
+ await app.close();
87
+ });
88
+ it('value negative {maxConcurrentReviews: -1} → rejects "La valeur doit être comprise entre 1 et 10"', async () => {
89
+ const gateway = new StubProjectConfigGateway();
90
+ gateway.set('/home/user/proj', baseProjectConfig());
91
+ const app = await buildPatchApp(gateway);
92
+ const response = await app.inject({
93
+ method: 'PATCH',
94
+ url: '/api/project-config?path=' + encodeURIComponent('/home/user/proj'),
95
+ payload: { maxConcurrentReviews: -1 },
96
+ });
97
+ expect(response.statusCode).toBe(400);
98
+ expect(response.json().error).toBe(PROJECT_CAP_OUT_OF_RANGE_MESSAGE);
99
+ await app.close();
100
+ });
101
+ it('value non integer {maxConcurrentReviews: 2.5} → rejects "La valeur doit être un nombre entier"', async () => {
102
+ const gateway = new StubProjectConfigGateway();
103
+ gateway.set('/home/user/proj', baseProjectConfig());
104
+ const app = await buildPatchApp(gateway);
105
+ const response = await app.inject({
106
+ method: 'PATCH',
107
+ url: '/api/project-config?path=' + encodeURIComponent('/home/user/proj'),
108
+ payload: { maxConcurrentReviews: 2.5 },
109
+ });
110
+ expect(response.statusCode).toBe(400);
111
+ expect(response.json().error).toBe(PROJECT_CAP_NOT_INTEGER_MESSAGE);
112
+ await app.close();
113
+ });
114
+ it('value not a number {maxConcurrentReviews: "abc"} → rejects "La valeur doit être un nombre entier"', async () => {
115
+ const gateway = new StubProjectConfigGateway();
116
+ gateway.set('/home/user/proj', baseProjectConfig());
117
+ const app = await buildPatchApp(gateway);
118
+ const response = await app.inject({
119
+ method: 'PATCH',
120
+ url: '/api/project-config?path=' + encodeURIComponent('/home/user/proj'),
121
+ payload: { maxConcurrentReviews: 'abc' },
122
+ });
123
+ expect(response.statusCode).toBe(400);
124
+ expect(response.json().error).toBe(PROJECT_CAP_NOT_INTEGER_MESSAGE);
125
+ await app.close();
126
+ });
127
+ it('value empty {maxConcurrentReviews: ""} → rejects "La valeur est obligatoire"', async () => {
128
+ const gateway = new StubProjectConfigGateway();
129
+ gateway.set('/home/user/proj', baseProjectConfig());
130
+ const app = await buildPatchApp(gateway);
131
+ const response = await app.inject({
132
+ method: 'PATCH',
133
+ url: '/api/project-config?path=' + encodeURIComponent('/home/user/proj'),
134
+ payload: { maxConcurrentReviews: '' },
135
+ });
136
+ expect(response.statusCode).toBe(400);
137
+ expect(response.json().error).toBe(PROJECT_CAP_REQUIRED_MESSAGE);
138
+ await app.close();
139
+ });
140
+ });
141
+ describe('Rule: missing key falls back to default 2', () => {
142
+ it('config without maxConcurrentReviews → effective cap "2"', () => {
143
+ const cap = effectiveProjectConcurrencyCap({});
144
+ expect(cap).toBe(DEFAULT_PROJECT_CONCURRENCY_CAP);
145
+ expect(cap).toBe(2);
146
+ });
147
+ });
148
+ describe('Rule: runtime enforcement of per-project cap (ProjectSemaphore)', () => {
149
+ it('enforce cap at runtime {cap: 2, running: 2, new: 1} → "queued"', async () => {
150
+ const semaphore = new ProjectSemaphore();
151
+ semaphore.setCapacity('/proj/A', 2);
152
+ const firstAcquired = await semaphore.acquire('/proj/A');
153
+ const secondAcquired = await semaphore.acquire('/proj/A');
154
+ expect(firstAcquired).toBe(true);
155
+ expect(secondAcquired).toBe(true);
156
+ expect(semaphore.runningCount('/proj/A')).toBe(2);
157
+ let thirdResolved = false;
158
+ const thirdPromise = semaphore.acquire('/proj/A').then(() => {
159
+ thirdResolved = true;
160
+ });
161
+ await Promise.resolve();
162
+ await Promise.resolve();
163
+ expect(thirdResolved).toBe(false);
164
+ expect(semaphore.pendingCount('/proj/A')).toBe(1);
165
+ semaphore.release('/proj/A');
166
+ await thirdPromise;
167
+ expect(thirdResolved).toBe(true);
168
+ });
169
+ it('below cap accepts new review {cap: 3, running: 2, new: 1} → "running"', async () => {
170
+ const semaphore = new ProjectSemaphore();
171
+ semaphore.setCapacity('/proj/A', 3);
172
+ await semaphore.acquire('/proj/A');
173
+ await semaphore.acquire('/proj/A');
174
+ const third = await semaphore.acquire('/proj/A');
175
+ expect(third).toBe(true);
176
+ expect(semaphore.runningCount('/proj/A')).toBe(3);
177
+ expect(semaphore.pendingCount('/proj/A')).toBe(0);
178
+ });
179
+ it('lower cap with running reviews {cap: 4, running: 4, lowerTo: 2} → running unchanged + next "queued"', async () => {
180
+ const semaphore = new ProjectSemaphore();
181
+ semaphore.setCapacity('/proj/A', 4);
182
+ await semaphore.acquire('/proj/A');
183
+ await semaphore.acquire('/proj/A');
184
+ await semaphore.acquire('/proj/A');
185
+ await semaphore.acquire('/proj/A');
186
+ semaphore.setCapacity('/proj/A', 2);
187
+ expect(semaphore.runningCount('/proj/A')).toBe(4);
188
+ let queuedResolved = false;
189
+ const queuedPromise = semaphore.acquire('/proj/A').then(() => {
190
+ queuedResolved = true;
191
+ });
192
+ await Promise.resolve();
193
+ await Promise.resolve();
194
+ expect(queuedResolved).toBe(false);
195
+ semaphore.release('/proj/A');
196
+ semaphore.release('/proj/A');
197
+ await Promise.resolve();
198
+ expect(queuedResolved).toBe(false);
199
+ semaphore.release('/proj/A');
200
+ await queuedPromise;
201
+ expect(queuedResolved).toBe(true);
202
+ });
203
+ it('raise cap releases queued {cap: 2, running: 2, queued: 3, raiseTo: 4} → 2 released, 1 still queued', async () => {
204
+ const semaphore = new ProjectSemaphore();
205
+ semaphore.setCapacity('/proj/A', 2);
206
+ await semaphore.acquire('/proj/A');
207
+ await semaphore.acquire('/proj/A');
208
+ const releasedCounter = { count: 0 };
209
+ const queuedPromises = [
210
+ semaphore.acquire('/proj/A').then(() => { releasedCounter.count += 1; }),
211
+ semaphore.acquire('/proj/A').then(() => { releasedCounter.count += 1; }),
212
+ semaphore.acquire('/proj/A').then(() => { releasedCounter.count += 1; }),
213
+ ];
214
+ await Promise.resolve();
215
+ expect(releasedCounter.count).toBe(0);
216
+ expect(semaphore.pendingCount('/proj/A')).toBe(3);
217
+ semaphore.setCapacity('/proj/A', 4);
218
+ await Promise.resolve();
219
+ await Promise.resolve();
220
+ await Promise.resolve();
221
+ expect(releasedCounter.count).toBe(2);
222
+ expect(semaphore.pendingCount('/proj/A')).toBe(1);
223
+ semaphore.release('/proj/A');
224
+ await Promise.resolve();
225
+ expect(releasedCounter.count).toBe(3);
226
+ expect(semaphore.pendingCount('/proj/A')).toBe(0);
227
+ await Promise.all(queuedPromises);
228
+ });
229
+ });
230
+ describe('Rule: total capacity equals sum across declared projects', () => {
231
+ it('total capacity equals sum {projects: [{cap:2},{cap:3},{cap:1}]} → header max "6"', async () => {
232
+ const repositoriesList = new StubRepositoriesListGateway();
233
+ repositoriesList.set([
234
+ { name: 'A', localPath: '/repos/A', enabled: true },
235
+ { name: 'B', localPath: '/repos/B', enabled: true },
236
+ { name: 'C', localPath: '/repos/C', enabled: true },
237
+ ]);
238
+ const projectConfig = new StubProjectConfigGateway();
239
+ projectConfig.set('/repos/A', baseProjectConfig({ maxConcurrentReviews: 2 }));
240
+ projectConfig.set('/repos/B', baseProjectConfig({ maxConcurrentReviews: 3 }));
241
+ projectConfig.set('/repos/C', baseProjectConfig({ maxConcurrentReviews: 1 }));
242
+ const queueCapacityPort = new StubQueueCapacityPort();
243
+ const recompute = new RecomputeGlobalConcurrencyUseCase({
244
+ repositoriesListGateway: repositoriesList,
245
+ projectConfigGateway: projectConfig,
246
+ queueCapacityPort,
247
+ });
248
+ const result = recompute.execute({});
249
+ expect(result.totalCapacity).toBe(6);
250
+ expect(queueCapacityPort.globalConcurrency).toBe(6);
251
+ });
252
+ it('new project adds to total {existingTotal: 5, added: {cap: 3}} → max "8"', () => {
253
+ const repositoriesList = new StubRepositoriesListGateway();
254
+ repositoriesList.set([
255
+ { name: 'A', localPath: '/repos/A', enabled: true },
256
+ { name: 'B', localPath: '/repos/B', enabled: true },
257
+ ]);
258
+ const projectConfig = new StubProjectConfigGateway();
259
+ projectConfig.set('/repos/A', baseProjectConfig({ maxConcurrentReviews: 2 }));
260
+ projectConfig.set('/repos/B', baseProjectConfig({ maxConcurrentReviews: 3 }));
261
+ const queueCapacityPort = new StubQueueCapacityPort();
262
+ const recompute = new RecomputeGlobalConcurrencyUseCase({
263
+ repositoriesListGateway: repositoriesList,
264
+ projectConfigGateway: projectConfig,
265
+ queueCapacityPort,
266
+ });
267
+ const before = recompute.execute({});
268
+ expect(before.totalCapacity).toBe(5);
269
+ repositoriesList.set([
270
+ { name: 'A', localPath: '/repos/A', enabled: true },
271
+ { name: 'B', localPath: '/repos/B', enabled: true },
272
+ { name: 'C', localPath: '/repos/C', enabled: true },
273
+ ]);
274
+ projectConfig.set('/repos/C', baseProjectConfig({ maxConcurrentReviews: 3 }));
275
+ const after = recompute.execute({});
276
+ expect(after.totalCapacity).toBe(8);
277
+ });
278
+ it('project removed shrinks total {existingTotal: 8, removed: {cap: 3}} → max "5"', () => {
279
+ const repositoriesList = new StubRepositoriesListGateway();
280
+ repositoriesList.set([
281
+ { name: 'A', localPath: '/repos/A', enabled: true },
282
+ { name: 'B', localPath: '/repos/B', enabled: true },
283
+ { name: 'C', localPath: '/repos/C', enabled: true },
284
+ ]);
285
+ const projectConfig = new StubProjectConfigGateway();
286
+ projectConfig.set('/repos/A', baseProjectConfig({ maxConcurrentReviews: 2 }));
287
+ projectConfig.set('/repos/B', baseProjectConfig({ maxConcurrentReviews: 3 }));
288
+ projectConfig.set('/repos/C', baseProjectConfig({ maxConcurrentReviews: 3 }));
289
+ const queueCapacityPort = new StubQueueCapacityPort();
290
+ const recompute = new RecomputeGlobalConcurrencyUseCase({
291
+ repositoriesListGateway: repositoriesList,
292
+ projectConfigGateway: projectConfig,
293
+ queueCapacityPort,
294
+ });
295
+ expect(recompute.execute({}).totalCapacity).toBe(8);
296
+ repositoriesList.set([
297
+ { name: 'A', localPath: '/repos/A', enabled: true },
298
+ { name: 'B', localPath: '/repos/B', enabled: true },
299
+ ]);
300
+ expect(recompute.execute({}).totalCapacity).toBe(5);
301
+ });
302
+ });
303
+ describe('Rule: header reflects running / total + saturation', () => {
304
+ it('header reflects running count {projects: [{running:1,cap:2},{running:2,cap:3}]} → "3 / 5"', () => {
305
+ const presenter = new OverviewPresenter();
306
+ const viewModel = presenter.present({
307
+ repositories: [RepositoryConfigFactory.create({ name: 'A', localPath: '/repos/A' })],
308
+ activeJobs: [],
309
+ projectStats: [],
310
+ recentReviews: [],
311
+ capacity: { running: 3, max: 5 },
312
+ });
313
+ expect(viewModel.headerCapacity.label).toBe('3 / 5');
314
+ expect(viewModel.headerCapacity.isSaturated).toBe(false);
315
+ });
316
+ it('saturated header at full load {projects: [{running:2,cap:2},{running:3,cap:3}]} → "5 / 5" + saturated', () => {
317
+ const presenter = new OverviewPresenter();
318
+ const viewModel = presenter.present({
319
+ repositories: [RepositoryConfigFactory.create({ name: 'A', localPath: '/repos/A' })],
320
+ activeJobs: [],
321
+ projectStats: [],
322
+ recentReviews: [],
323
+ capacity: { running: 5, max: 5 },
324
+ });
325
+ expect(viewModel.headerCapacity.label).toBe('5 / 5');
326
+ expect(viewModel.headerCapacity.isSaturated).toBe(true);
327
+ });
328
+ });
329
+ describe('Frontend humble module — validateMaxConcurrentReviews (mirrors server)', () => {
330
+ it('accepts integer values 1 through 10', () => {
331
+ for (const value of ['1', '2', '5', '7', '10']) {
332
+ expect(validateMaxConcurrentReviews(value)).toEqual({ ok: true });
333
+ }
334
+ });
335
+ it('rejects empty with the French required message', () => {
336
+ expect(validateMaxConcurrentReviews('')).toEqual({
337
+ ok: false,
338
+ message: PROJECT_CAP_REQUIRED_MESSAGE,
339
+ });
340
+ });
341
+ it('rejects 0 with the range message', () => {
342
+ expect(validateMaxConcurrentReviews('0')).toEqual({
343
+ ok: false,
344
+ message: PROJECT_CAP_OUT_OF_RANGE_MESSAGE,
345
+ });
346
+ });
347
+ it('rejects 11 with the range message', () => {
348
+ expect(validateMaxConcurrentReviews('11')).toEqual({
349
+ ok: false,
350
+ message: PROJECT_CAP_OUT_OF_RANGE_MESSAGE,
351
+ });
352
+ });
353
+ it('rejects 2.5 with the integer message', () => {
354
+ expect(validateMaxConcurrentReviews('2.5')).toEqual({
355
+ ok: false,
356
+ message: PROJECT_CAP_NOT_INTEGER_MESSAGE,
357
+ });
358
+ });
359
+ it('rejects "abc" with the integer message', () => {
360
+ expect(validateMaxConcurrentReviews('abc')).toEqual({
361
+ ok: false,
362
+ message: PROJECT_CAP_NOT_INTEGER_MESSAGE,
363
+ });
364
+ });
365
+ });
366
+ describe('Frontend humble module — settings modal exposes maxConcurrentReviews input', () => {
367
+ it('settings modal HTML contains an input for maxConcurrentReviews bounded to 1-10', () => {
368
+ const html = renderSettingsModalHtml(buildSettingsViewModel({
369
+ config: baseProjectConfig({ maxConcurrentReviews: 4 }),
370
+ projectName: 'frontend',
371
+ }));
372
+ expect(html).toMatch(/<input[^>]+name="maxConcurrentReviews"[^>]+type="number"/);
373
+ expect(html).toMatch(/<input[^>]+name="maxConcurrentReviews"[^>]+min="1"/);
374
+ expect(html).toMatch(/<input[^>]+name="maxConcurrentReviews"[^>]+max="10"/);
375
+ expect(html).toMatch(/<input[^>]+name="maxConcurrentReviews"[^>]+value="4"/);
376
+ });
377
+ });
378
+ describe('Frontend humble module — header capacity badge', () => {
379
+ it('builds a viewmodel with "N / M" label and isSaturated false when under load', () => {
380
+ const viewModel = buildHeaderCapacityViewModel({ running: 3, max: 5 });
381
+ expect(viewModel.label).toBe('3 / 5');
382
+ expect(viewModel.isSaturated).toBe(false);
383
+ });
384
+ it('marks the viewmodel saturated when running equals max', () => {
385
+ const viewModel = buildHeaderCapacityViewModel({ running: 5, max: 5 });
386
+ expect(viewModel.label).toBe('5 / 5');
387
+ expect(viewModel.isSaturated).toBe(true);
388
+ });
389
+ });
390
+ });
391
+ //# sourceMappingURL=186-per-project-concurrency-cap.acceptance.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"186-per-project-concurrency-cap.acceptance.test.js","sourceRoot":"","sources":["../../../src/tests/acceptance/186-per-project-concurrency-cap.acceptance.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * SPEC-47 — Capture Git Diff Stats (Commits, Additions, Deletions)
3
+ *
4
+ * Outer-loop acceptance test (SDD): exercises the production
5
+ * fetchDiffStatsSafely helper + the stats service + the tracking use case.
6
+ * The wiring inside claudeInvoker.ts is exercised by its own unit tests.
7
+ *
8
+ * Scenarios from docs/specs/47-capture-git-diff-stats.md:
9
+ * 1. Successful diff stats capture on GitHub review (nominal)
10
+ * 2. Successful diff stats capture on GitLab review (nominal)
11
+ * 3. Diff stats fetch failure does not block the review
12
+ * 4. Backward compatibility — old reviews without diff stats
13
+ * 5. Aggregated diff stats in project stats
14
+ * 6. Followup reviews also capture diff stats
15
+ * 7. Zero-diff merge request
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=47-capture-git-diff-stats.acceptance.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"47-capture-git-diff-stats.acceptance.test.d.ts","sourceRoot":"","sources":["../../../src/tests/acceptance/47-capture-git-diff-stats.acceptance.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}