reviewflow 3.0.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 (914) hide show
  1. package/CHANGELOG.md +271 -0
  2. package/LICENSE +21 -0
  3. package/README.md +209 -0
  4. package/dist/claude/invoker.d.ts +3 -0
  5. package/dist/claude/invoker.d.ts.map +1 -0
  6. package/dist/claude/invoker.js +4 -0
  7. package/dist/claude/invoker.js.map +1 -0
  8. package/dist/claude/progressParser.d.ts +3 -0
  9. package/dist/claude/progressParser.d.ts.map +1 -0
  10. package/dist/claude/progressParser.js +4 -0
  11. package/dist/claude/progressParser.js.map +1 -0
  12. package/dist/cli/parseCliArgs.d.ts +6 -0
  13. package/dist/cli/parseCliArgs.d.ts.map +1 -0
  14. package/dist/cli/parseCliArgs.js +13 -0
  15. package/dist/cli/parseCliArgs.js.map +1 -0
  16. package/dist/config/loader.d.ts +3 -0
  17. package/dist/config/loader.d.ts.map +1 -0
  18. package/dist/config/loader.js +4 -0
  19. package/dist/config/loader.js.map +1 -0
  20. package/dist/config/projectConfig.d.ts +30 -0
  21. package/dist/config/projectConfig.d.ts.map +1 -0
  22. package/dist/config/projectConfig.js +89 -0
  23. package/dist/config/projectConfig.js.map +1 -0
  24. package/dist/entities/diffMetadata/diffMetadata.gateway.d.ts +5 -0
  25. package/dist/entities/diffMetadata/diffMetadata.gateway.d.ts.map +1 -0
  26. package/dist/entities/diffMetadata/diffMetadata.gateway.js +2 -0
  27. package/dist/entities/diffMetadata/diffMetadata.gateway.js.map +1 -0
  28. package/dist/entities/github/githubPullRequestEvent.guard.d.ts +199 -0
  29. package/dist/entities/github/githubPullRequestEvent.guard.d.ts.map +1 -0
  30. package/dist/entities/github/githubPullRequestEvent.guard.js +28 -0
  31. package/dist/entities/github/githubPullRequestEvent.guard.js.map +1 -0
  32. package/dist/entities/gitlab/gitlabMergeRequestEvent.guard.d.ts +231 -0
  33. package/dist/entities/gitlab/gitlabMergeRequestEvent.guard.d.ts.map +1 -0
  34. package/dist/entities/gitlab/gitlabMergeRequestEvent.guard.js +52 -0
  35. package/dist/entities/gitlab/gitlabMergeRequestEvent.guard.js.map +1 -0
  36. package/dist/entities/job/jobContext.gateway.d.ts +10 -0
  37. package/dist/entities/job/jobContext.gateway.d.ts.map +1 -0
  38. package/dist/entities/job/jobContext.gateway.js +2 -0
  39. package/dist/entities/job/jobContext.gateway.js.map +1 -0
  40. package/dist/entities/progress/agentDefinition.type.d.ts +7 -0
  41. package/dist/entities/progress/agentDefinition.type.d.ts.map +1 -0
  42. package/dist/entities/progress/agentDefinition.type.js +18 -0
  43. package/dist/entities/progress/agentDefinition.type.js.map +1 -0
  44. package/dist/entities/progress/progress.calculator.d.ts +3 -0
  45. package/dist/entities/progress/progress.calculator.d.ts.map +1 -0
  46. package/dist/entities/progress/progress.calculator.js +17 -0
  47. package/dist/entities/progress/progress.calculator.js.map +1 -0
  48. package/dist/entities/progress/progress.factory.d.ts +4 -0
  49. package/dist/entities/progress/progress.factory.d.ts.map +1 -0
  50. package/dist/entities/progress/progress.factory.js +15 -0
  51. package/dist/entities/progress/progress.factory.js.map +1 -0
  52. package/dist/entities/progress/progress.gateway.d.ts +12 -0
  53. package/dist/entities/progress/progress.gateway.d.ts.map +1 -0
  54. package/dist/entities/progress/progress.gateway.js +2 -0
  55. package/dist/entities/progress/progress.gateway.js.map +1 -0
  56. package/dist/entities/progress/progress.type.d.ts +28 -0
  57. package/dist/entities/progress/progress.type.d.ts.map +1 -0
  58. package/dist/entities/progress/progress.type.js +2 -0
  59. package/dist/entities/progress/progress.type.js.map +1 -0
  60. package/dist/entities/review/reviewScore.valueObject.d.ts +25 -0
  61. package/dist/entities/review/reviewScore.valueObject.d.ts.map +1 -0
  62. package/dist/entities/review/reviewScore.valueObject.js +60 -0
  63. package/dist/entities/review/reviewScore.valueObject.js.map +1 -0
  64. package/dist/entities/reviewAction/reviewAction.d.ts +12 -0
  65. package/dist/entities/reviewAction/reviewAction.d.ts.map +1 -0
  66. package/dist/entities/reviewAction/reviewAction.gateway.d.ts +19 -0
  67. package/dist/entities/reviewAction/reviewAction.gateway.d.ts.map +1 -0
  68. package/dist/entities/reviewAction/reviewAction.gateway.js +2 -0
  69. package/dist/entities/reviewAction/reviewAction.gateway.js.map +1 -0
  70. package/dist/entities/reviewAction/reviewAction.guard.d.ts +27 -0
  71. package/dist/entities/reviewAction/reviewAction.guard.d.ts.map +1 -0
  72. package/dist/entities/reviewAction/reviewAction.guard.js +8 -0
  73. package/dist/entities/reviewAction/reviewAction.guard.js.map +1 -0
  74. package/dist/entities/reviewAction/reviewAction.js +2 -0
  75. package/dist/entities/reviewAction/reviewAction.js.map +1 -0
  76. package/dist/entities/reviewAction/reviewAction.schema.d.ts +51 -0
  77. package/dist/entities/reviewAction/reviewAction.schema.d.ts.map +1 -0
  78. package/dist/entities/reviewAction/reviewAction.schema.js +37 -0
  79. package/dist/entities/reviewAction/reviewAction.schema.js.map +1 -0
  80. package/dist/entities/reviewContext/reviewContext.d.ts +62 -0
  81. package/dist/entities/reviewContext/reviewContext.d.ts.map +1 -0
  82. package/dist/entities/reviewContext/reviewContext.gateway.d.ts +16 -0
  83. package/dist/entities/reviewContext/reviewContext.gateway.d.ts.map +1 -0
  84. package/dist/entities/reviewContext/reviewContext.gateway.js +2 -0
  85. package/dist/entities/reviewContext/reviewContext.gateway.js.map +1 -0
  86. package/dist/entities/reviewContext/reviewContext.js +2 -0
  87. package/dist/entities/reviewContext/reviewContext.js.map +1 -0
  88. package/dist/entities/reviewContext/reviewContext.schema.d.ts +122 -0
  89. package/dist/entities/reviewContext/reviewContext.schema.d.ts.map +1 -0
  90. package/dist/entities/reviewContext/reviewContext.schema.js +42 -0
  91. package/dist/entities/reviewContext/reviewContext.schema.js.map +1 -0
  92. package/dist/entities/reviewContext/reviewContextAction.guard.d.ts +247 -0
  93. package/dist/entities/reviewContext/reviewContextAction.guard.d.ts.map +1 -0
  94. package/dist/entities/reviewContext/reviewContextAction.guard.js +28 -0
  95. package/dist/entities/reviewContext/reviewContextAction.guard.js.map +1 -0
  96. package/dist/entities/reviewContext/reviewContextAction.schema.d.ts +16 -0
  97. package/dist/entities/reviewContext/reviewContextAction.schema.d.ts.map +1 -0
  98. package/dist/entities/reviewContext/reviewContextAction.schema.js +13 -0
  99. package/dist/entities/reviewContext/reviewContextAction.schema.js.map +1 -0
  100. package/dist/entities/reviewRequest/reviewRequest.entity.d.ts +37 -0
  101. package/dist/entities/reviewRequest/reviewRequest.entity.d.ts.map +1 -0
  102. package/dist/entities/reviewRequest/reviewRequest.entity.js +24 -0
  103. package/dist/entities/reviewRequest/reviewRequest.entity.js.map +1 -0
  104. package/dist/entities/reviewRequest/reviewRequest.guard.d.ts +20 -0
  105. package/dist/entities/reviewRequest/reviewRequest.guard.d.ts.map +1 -0
  106. package/dist/entities/reviewRequest/reviewRequest.guard.js +11 -0
  107. package/dist/entities/reviewRequest/reviewRequest.guard.js.map +1 -0
  108. package/dist/entities/reviewRequest/reviewRequestState.valueObject.d.ts +26 -0
  109. package/dist/entities/reviewRequest/reviewRequestState.valueObject.d.ts.map +1 -0
  110. package/dist/entities/reviewRequest/reviewRequestState.valueObject.js +61 -0
  111. package/dist/entities/reviewRequest/reviewRequestState.valueObject.js.map +1 -0
  112. package/dist/entities/shared/duration.valueObject.d.ts +21 -0
  113. package/dist/entities/shared/duration.valueObject.d.ts.map +1 -0
  114. package/dist/entities/shared/duration.valueObject.js +60 -0
  115. package/dist/entities/shared/duration.valueObject.js.map +1 -0
  116. package/dist/entities/threadFetch/threadFetch.gateway.d.ts +5 -0
  117. package/dist/entities/threadFetch/threadFetch.gateway.d.ts.map +1 -0
  118. package/dist/entities/threadFetch/threadFetch.gateway.js +2 -0
  119. package/dist/entities/threadFetch/threadFetch.gateway.js.map +1 -0
  120. package/dist/entities/tracking/assignmentInfo.d.ts +6 -0
  121. package/dist/entities/tracking/assignmentInfo.d.ts.map +1 -0
  122. package/dist/entities/tracking/assignmentInfo.js +2 -0
  123. package/dist/entities/tracking/assignmentInfo.js.map +1 -0
  124. package/dist/entities/tracking/mrTrackingData.d.ts +19 -0
  125. package/dist/entities/tracking/mrTrackingData.d.ts.map +1 -0
  126. package/dist/entities/tracking/mrTrackingData.js +11 -0
  127. package/dist/entities/tracking/mrTrackingData.js.map +1 -0
  128. package/dist/entities/tracking/reviewEvent.d.ts +12 -0
  129. package/dist/entities/tracking/reviewEvent.d.ts.map +1 -0
  130. package/dist/entities/tracking/reviewEvent.js +2 -0
  131. package/dist/entities/tracking/reviewEvent.js.map +1 -0
  132. package/dist/entities/tracking/trackedMr.d.ts +33 -0
  133. package/dist/entities/tracking/trackedMr.d.ts.map +1 -0
  134. package/dist/entities/tracking/trackedMr.js +4 -0
  135. package/dist/entities/tracking/trackedMr.js.map +1 -0
  136. package/dist/frameworks/claude/claudeInvoker.d.ts +30 -0
  137. package/dist/frameworks/claude/claudeInvoker.d.ts.map +1 -0
  138. package/dist/frameworks/claude/claudeInvoker.js +500 -0
  139. package/dist/frameworks/claude/claudeInvoker.js.map +1 -0
  140. package/dist/frameworks/claude/progressParser.d.ts +70 -0
  141. package/dist/frameworks/claude/progressParser.d.ts.map +1 -0
  142. package/dist/frameworks/claude/progressParser.js +196 -0
  143. package/dist/frameworks/claude/progressParser.js.map +1 -0
  144. package/dist/frameworks/config/configLoader.d.ts +34 -0
  145. package/dist/frameworks/config/configLoader.d.ts.map +1 -0
  146. package/dist/frameworks/config/configLoader.js +182 -0
  147. package/dist/frameworks/config/configLoader.js.map +1 -0
  148. package/dist/frameworks/logging/logBuffer.d.ts +38 -0
  149. package/dist/frameworks/logging/logBuffer.d.ts.map +1 -0
  150. package/dist/frameworks/logging/logBuffer.js +72 -0
  151. package/dist/frameworks/logging/logBuffer.js.map +1 -0
  152. package/dist/frameworks/queue/pQueueAdapter.d.ts +127 -0
  153. package/dist/frameworks/queue/pQueueAdapter.d.ts.map +1 -0
  154. package/dist/frameworks/queue/pQueueAdapter.js +276 -0
  155. package/dist/frameworks/queue/pQueueAdapter.js.map +1 -0
  156. package/dist/frameworks/settings/runtimeSettings.d.ts +12 -0
  157. package/dist/frameworks/settings/runtimeSettings.d.ts.map +1 -0
  158. package/dist/frameworks/settings/runtimeSettings.js +19 -0
  159. package/dist/frameworks/settings/runtimeSettings.js.map +1 -0
  160. package/dist/interface-adapters/adapters/githubPullRequest.adapter.d.ts +6 -0
  161. package/dist/interface-adapters/adapters/githubPullRequest.adapter.d.ts.map +1 -0
  162. package/dist/interface-adapters/adapters/githubPullRequest.adapter.js +27 -0
  163. package/dist/interface-adapters/adapters/githubPullRequest.adapter.js.map +1 -0
  164. package/dist/interface-adapters/adapters/gitlabMergeRequest.adapter.d.ts +6 -0
  165. package/dist/interface-adapters/adapters/gitlabMergeRequest.adapter.d.ts.map +1 -0
  166. package/dist/interface-adapters/adapters/gitlabMergeRequest.adapter.js +35 -0
  167. package/dist/interface-adapters/adapters/gitlabMergeRequest.adapter.js.map +1 -0
  168. package/dist/interface-adapters/adapters/platformAdapter.d.ts +9 -0
  169. package/dist/interface-adapters/adapters/platformAdapter.d.ts.map +1 -0
  170. package/dist/interface-adapters/adapters/platformAdapter.js +16 -0
  171. package/dist/interface-adapters/adapters/platformAdapter.js.map +1 -0
  172. package/dist/interface-adapters/controllers/http/cliStatus.routes.d.ts +3 -0
  173. package/dist/interface-adapters/controllers/http/cliStatus.routes.d.ts.map +1 -0
  174. package/dist/interface-adapters/controllers/http/cliStatus.routes.js +173 -0
  175. package/dist/interface-adapters/controllers/http/cliStatus.routes.js.map +1 -0
  176. package/dist/interface-adapters/controllers/http/health.routes.d.ts +9 -0
  177. package/dist/interface-adapters/controllers/http/health.routes.d.ts.map +1 -0
  178. package/dist/interface-adapters/controllers/http/health.routes.js +23 -0
  179. package/dist/interface-adapters/controllers/http/health.routes.js.map +1 -0
  180. package/dist/interface-adapters/controllers/http/index.d.ts +6 -0
  181. package/dist/interface-adapters/controllers/http/index.d.ts.map +1 -0
  182. package/dist/interface-adapters/controllers/http/index.js +6 -0
  183. package/dist/interface-adapters/controllers/http/index.js.map +1 -0
  184. package/dist/interface-adapters/controllers/http/logs.routes.d.ts +3 -0
  185. package/dist/interface-adapters/controllers/http/logs.routes.d.ts.map +1 -0
  186. package/dist/interface-adapters/controllers/http/logs.routes.js +12 -0
  187. package/dist/interface-adapters/controllers/http/logs.routes.js.map +1 -0
  188. package/dist/interface-adapters/controllers/http/mrTracking.routes.d.ts +8 -0
  189. package/dist/interface-adapters/controllers/http/mrTracking.routes.d.ts.map +1 -0
  190. package/dist/interface-adapters/controllers/http/mrTracking.routes.js +63 -0
  191. package/dist/interface-adapters/controllers/http/mrTracking.routes.js.map +1 -0
  192. package/dist/interface-adapters/controllers/http/mrTrackingAdvanced.routes.d.ts +12 -0
  193. package/dist/interface-adapters/controllers/http/mrTrackingAdvanced.routes.d.ts.map +1 -0
  194. package/dist/interface-adapters/controllers/http/mrTrackingAdvanced.routes.js +265 -0
  195. package/dist/interface-adapters/controllers/http/mrTrackingAdvanced.routes.js.map +1 -0
  196. package/dist/interface-adapters/controllers/http/projectConfig.routes.d.ts +3 -0
  197. package/dist/interface-adapters/controllers/http/projectConfig.routes.d.ts.map +1 -0
  198. package/dist/interface-adapters/controllers/http/projectConfig.routes.js +75 -0
  199. package/dist/interface-adapters/controllers/http/projectConfig.routes.js.map +1 -0
  200. package/dist/interface-adapters/controllers/http/reviews.routes.d.ts +18 -0
  201. package/dist/interface-adapters/controllers/http/reviews.routes.d.ts.map +1 -0
  202. package/dist/interface-adapters/controllers/http/reviews.routes.js +96 -0
  203. package/dist/interface-adapters/controllers/http/reviews.routes.js.map +1 -0
  204. package/dist/interface-adapters/controllers/http/settings.routes.d.ts +3 -0
  205. package/dist/interface-adapters/controllers/http/settings.routes.d.ts.map +1 -0
  206. package/dist/interface-adapters/controllers/http/settings.routes.js +21 -0
  207. package/dist/interface-adapters/controllers/http/settings.routes.js.map +1 -0
  208. package/dist/interface-adapters/controllers/http/stats.routes.d.ts +13 -0
  209. package/dist/interface-adapters/controllers/http/stats.routes.d.ts.map +1 -0
  210. package/dist/interface-adapters/controllers/http/stats.routes.js +37 -0
  211. package/dist/interface-adapters/controllers/http/stats.routes.js.map +1 -0
  212. package/dist/interface-adapters/controllers/mcp/addAction.handler.d.ts +4 -0
  213. package/dist/interface-adapters/controllers/mcp/addAction.handler.d.ts.map +1 -0
  214. package/dist/interface-adapters/controllers/mcp/addAction.handler.js +87 -0
  215. package/dist/interface-adapters/controllers/mcp/addAction.handler.js.map +1 -0
  216. package/dist/interface-adapters/controllers/mcp/completeAgent.handler.d.ts +4 -0
  217. package/dist/interface-adapters/controllers/mcp/completeAgent.handler.d.ts.map +1 -0
  218. package/dist/interface-adapters/controllers/mcp/completeAgent.handler.js +62 -0
  219. package/dist/interface-adapters/controllers/mcp/completeAgent.handler.js.map +1 -0
  220. package/dist/interface-adapters/controllers/mcp/getThreads.handler.d.ts +4 -0
  221. package/dist/interface-adapters/controllers/mcp/getThreads.handler.d.ts.map +1 -0
  222. package/dist/interface-adapters/controllers/mcp/getThreads.handler.js +32 -0
  223. package/dist/interface-adapters/controllers/mcp/getThreads.handler.js.map +1 -0
  224. package/dist/interface-adapters/controllers/mcp/getWorkflow.handler.d.ts +4 -0
  225. package/dist/interface-adapters/controllers/mcp/getWorkflow.handler.d.ts.map +1 -0
  226. package/dist/interface-adapters/controllers/mcp/getWorkflow.handler.js +28 -0
  227. package/dist/interface-adapters/controllers/mcp/getWorkflow.handler.js.map +1 -0
  228. package/dist/interface-adapters/controllers/mcp/setPhase.handler.d.ts +4 -0
  229. package/dist/interface-adapters/controllers/mcp/setPhase.handler.d.ts.map +1 -0
  230. package/dist/interface-adapters/controllers/mcp/setPhase.handler.js +60 -0
  231. package/dist/interface-adapters/controllers/mcp/setPhase.handler.js.map +1 -0
  232. package/dist/interface-adapters/controllers/mcp/startAgent.handler.d.ts +4 -0
  233. package/dist/interface-adapters/controllers/mcp/startAgent.handler.d.ts.map +1 -0
  234. package/dist/interface-adapters/controllers/mcp/startAgent.handler.js +40 -0
  235. package/dist/interface-adapters/controllers/mcp/startAgent.handler.js.map +1 -0
  236. package/dist/interface-adapters/controllers/webhook/eventFilter.d.ts +71 -0
  237. package/dist/interface-adapters/controllers/webhook/eventFilter.d.ts.map +1 -0
  238. package/dist/interface-adapters/controllers/webhook/eventFilter.js +252 -0
  239. package/dist/interface-adapters/controllers/webhook/eventFilter.js.map +1 -0
  240. package/dist/interface-adapters/controllers/webhook/github.controller.d.ts +5 -0
  241. package/dist/interface-adapters/controllers/webhook/github.controller.d.ts.map +1 -0
  242. package/dist/interface-adapters/controllers/webhook/github.controller.js +266 -0
  243. package/dist/interface-adapters/controllers/webhook/github.controller.js.map +1 -0
  244. package/dist/interface-adapters/controllers/webhook/gitlab.controller.d.ts +5 -0
  245. package/dist/interface-adapters/controllers/webhook/gitlab.controller.d.ts.map +1 -0
  246. package/dist/interface-adapters/controllers/webhook/gitlab.controller.js +461 -0
  247. package/dist/interface-adapters/controllers/webhook/gitlab.controller.js.map +1 -0
  248. package/dist/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.d.ts +7 -0
  249. package/dist/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.d.ts.map +1 -0
  250. package/dist/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.js +71 -0
  251. package/dist/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.js.map +1 -0
  252. package/dist/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.d.ts +7 -0
  253. package/dist/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.d.ts.map +1 -0
  254. package/dist/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.js +58 -0
  255. package/dist/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.js.map +1 -0
  256. package/dist/interface-adapters/gateways/diffMetadataFetch.github.gateway.d.ts +9 -0
  257. package/dist/interface-adapters/gateways/diffMetadataFetch.github.gateway.d.ts.map +1 -0
  258. package/dist/interface-adapters/gateways/diffMetadataFetch.github.gateway.js +16 -0
  259. package/dist/interface-adapters/gateways/diffMetadataFetch.github.gateway.js.map +1 -0
  260. package/dist/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.d.ts +9 -0
  261. package/dist/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.d.ts.map +1 -0
  262. package/dist/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.js +18 -0
  263. package/dist/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.js.map +1 -0
  264. package/dist/interface-adapters/gateways/fileSystem/reviewFile.fileSystem.d.ts +10 -0
  265. package/dist/interface-adapters/gateways/fileSystem/reviewFile.fileSystem.d.ts.map +1 -0
  266. package/dist/interface-adapters/gateways/fileSystem/reviewFile.fileSystem.js +81 -0
  267. package/dist/interface-adapters/gateways/fileSystem/reviewFile.fileSystem.js.map +1 -0
  268. package/dist/interface-adapters/gateways/fileSystem/reviewRequestTracking.fileSystem.d.ts +22 -0
  269. package/dist/interface-adapters/gateways/fileSystem/reviewRequestTracking.fileSystem.d.ts.map +1 -0
  270. package/dist/interface-adapters/gateways/fileSystem/reviewRequestTracking.fileSystem.js +142 -0
  271. package/dist/interface-adapters/gateways/fileSystem/reviewRequestTracking.fileSystem.js.map +1 -0
  272. package/dist/interface-adapters/gateways/fileSystem/stats.fileSystem.d.ts +8 -0
  273. package/dist/interface-adapters/gateways/fileSystem/stats.fileSystem.d.ts.map +1 -0
  274. package/dist/interface-adapters/gateways/fileSystem/stats.fileSystem.js +37 -0
  275. package/dist/interface-adapters/gateways/fileSystem/stats.fileSystem.js.map +1 -0
  276. package/dist/interface-adapters/gateways/jobContext.memory.gateway.d.ts +8 -0
  277. package/dist/interface-adapters/gateways/jobContext.memory.gateway.d.ts.map +1 -0
  278. package/dist/interface-adapters/gateways/jobContext.memory.gateway.js +13 -0
  279. package/dist/interface-adapters/gateways/jobContext.memory.gateway.js.map +1 -0
  280. package/dist/interface-adapters/gateways/reviewContext.fileSystem.gateway.d.ts +14 -0
  281. package/dist/interface-adapters/gateways/reviewContext.fileSystem.gateway.d.ts.map +1 -0
  282. package/dist/interface-adapters/gateways/reviewContext.fileSystem.gateway.js +87 -0
  283. package/dist/interface-adapters/gateways/reviewContext.fileSystem.gateway.js.map +1 -0
  284. package/dist/interface-adapters/gateways/reviewFile.gateway.d.ts +18 -0
  285. package/dist/interface-adapters/gateways/reviewFile.gateway.d.ts.map +1 -0
  286. package/dist/interface-adapters/gateways/reviewFile.gateway.js +2 -0
  287. package/dist/interface-adapters/gateways/reviewFile.gateway.js.map +1 -0
  288. package/dist/interface-adapters/gateways/reviewProgress.memory.gateway.d.ts +13 -0
  289. package/dist/interface-adapters/gateways/reviewProgress.memory.gateway.d.ts.map +1 -0
  290. package/dist/interface-adapters/gateways/reviewProgress.memory.gateway.js +73 -0
  291. package/dist/interface-adapters/gateways/reviewProgress.memory.gateway.js.map +1 -0
  292. package/dist/interface-adapters/gateways/reviewRequestTracking.gateway.d.ts +19 -0
  293. package/dist/interface-adapters/gateways/reviewRequestTracking.gateway.d.ts.map +1 -0
  294. package/dist/interface-adapters/gateways/reviewRequestTracking.gateway.js +2 -0
  295. package/dist/interface-adapters/gateways/reviewRequestTracking.gateway.js.map +1 -0
  296. package/dist/interface-adapters/gateways/stats.gateway.d.ts +7 -0
  297. package/dist/interface-adapters/gateways/stats.gateway.d.ts.map +1 -0
  298. package/dist/interface-adapters/gateways/stats.gateway.js +2 -0
  299. package/dist/interface-adapters/gateways/stats.gateway.js.map +1 -0
  300. package/dist/interface-adapters/gateways/threadFetch.github.gateway.d.ts +10 -0
  301. package/dist/interface-adapters/gateways/threadFetch.github.gateway.d.ts.map +1 -0
  302. package/dist/interface-adapters/gateways/threadFetch.github.gateway.js +33 -0
  303. package/dist/interface-adapters/gateways/threadFetch.github.gateway.js.map +1 -0
  304. package/dist/interface-adapters/gateways/threadFetch.gitlab.gateway.d.ts +10 -0
  305. package/dist/interface-adapters/gateways/threadFetch.gitlab.gateway.d.ts.map +1 -0
  306. package/dist/interface-adapters/gateways/threadFetch.gitlab.gateway.js +30 -0
  307. package/dist/interface-adapters/gateways/threadFetch.gitlab.gateway.js.map +1 -0
  308. package/dist/interface-adapters/presenters/jobStatus.presenter.d.ts +29 -0
  309. package/dist/interface-adapters/presenters/jobStatus.presenter.d.ts.map +1 -0
  310. package/dist/interface-adapters/presenters/jobStatus.presenter.js +57 -0
  311. package/dist/interface-adapters/presenters/jobStatus.presenter.js.map +1 -0
  312. package/dist/interface-adapters/presenters/reviewContextProgress.presenter.d.ts +8 -0
  313. package/dist/interface-adapters/presenters/reviewContextProgress.presenter.d.ts.map +1 -0
  314. package/dist/interface-adapters/presenters/reviewContextProgress.presenter.js +45 -0
  315. package/dist/interface-adapters/presenters/reviewContextProgress.presenter.js.map +1 -0
  316. package/dist/interface-adapters/presenters/reviewList.presenter.d.ts +22 -0
  317. package/dist/interface-adapters/presenters/reviewList.presenter.d.ts.map +1 -0
  318. package/dist/interface-adapters/presenters/reviewList.presenter.js +32 -0
  319. package/dist/interface-adapters/presenters/reviewList.presenter.js.map +1 -0
  320. package/dist/interface-adapters/services/projectStats.calculator.d.ts +8 -0
  321. package/dist/interface-adapters/services/projectStats.calculator.d.ts.map +1 -0
  322. package/dist/interface-adapters/services/projectStats.calculator.js +52 -0
  323. package/dist/interface-adapters/services/projectStats.calculator.js.map +1 -0
  324. package/dist/interface-adapters/views/dashboard/index.html +1537 -0
  325. package/dist/interface-adapters/views/dashboard/styles.css +1127 -0
  326. package/dist/main/cli.d.ts +12 -0
  327. package/dist/main/cli.d.ts.map +1 -0
  328. package/dist/main/cli.js +67 -0
  329. package/dist/main/cli.js.map +1 -0
  330. package/dist/main/dependencies.d.ts +20 -0
  331. package/dist/main/dependencies.d.ts.map +1 -0
  332. package/dist/main/dependencies.js +28 -0
  333. package/dist/main/dependencies.js.map +1 -0
  334. package/dist/main/mcpDependencies.d.ts +16 -0
  335. package/dist/main/mcpDependencies.d.ts.map +1 -0
  336. package/dist/main/mcpDependencies.js +35 -0
  337. package/dist/main/mcpDependencies.js.map +1 -0
  338. package/dist/main/routes.d.ts +4 -0
  339. package/dist/main/routes.d.ts.map +1 -0
  340. package/dist/main/routes.js +74 -0
  341. package/dist/main/routes.js.map +1 -0
  342. package/dist/main/server.d.ts +8 -0
  343. package/dist/main/server.d.ts.map +1 -0
  344. package/dist/main/server.js +54 -0
  345. package/dist/main/server.js.map +1 -0
  346. package/dist/main/websocket.d.ts +10 -0
  347. package/dist/main/websocket.d.ts.map +1 -0
  348. package/dist/main/websocket.js +109 -0
  349. package/dist/main/websocket.js.map +1 -0
  350. package/dist/mcp/mcpLogger.d.ts +9 -0
  351. package/dist/mcp/mcpLogger.d.ts.map +1 -0
  352. package/dist/mcp/mcpLogger.js +49 -0
  353. package/dist/mcp/mcpLogger.js.map +1 -0
  354. package/dist/mcp/mcpServerStdio.d.ts +13 -0
  355. package/dist/mcp/mcpServerStdio.d.ts.map +1 -0
  356. package/dist/mcp/mcpServerStdio.js +239 -0
  357. package/dist/mcp/mcpServerStdio.js.map +1 -0
  358. package/dist/mcp/server.d.ts +8 -0
  359. package/dist/mcp/server.d.ts.map +1 -0
  360. package/dist/mcp/server.js +24 -0
  361. package/dist/mcp/server.js.map +1 -0
  362. package/dist/mcp/types.d.ts +27 -0
  363. package/dist/mcp/types.d.ts.map +1 -0
  364. package/dist/mcp/types.js +2 -0
  365. package/dist/mcp/types.js.map +1 -0
  366. package/dist/mcpServer.d.ts +2 -0
  367. package/dist/mcpServer.d.ts.map +1 -0
  368. package/dist/mcpServer.js +16 -0
  369. package/dist/mcpServer.js.map +1 -0
  370. package/dist/queue/reviewQueue.d.ts +3 -0
  371. package/dist/queue/reviewQueue.d.ts.map +1 -0
  372. package/dist/queue/reviewQueue.js +4 -0
  373. package/dist/queue/reviewQueue.js.map +1 -0
  374. package/dist/security/verifier.d.ts +21 -0
  375. package/dist/security/verifier.d.ts.map +1 -0
  376. package/dist/security/verifier.js +67 -0
  377. package/dist/security/verifier.js.map +1 -0
  378. package/dist/server.d.ts +2 -0
  379. package/dist/server.d.ts.map +1 -0
  380. package/dist/server.js +6 -0
  381. package/dist/server.js.map +1 -0
  382. package/dist/services/agentInstructionsBuilder.d.ts +4 -0
  383. package/dist/services/agentInstructionsBuilder.d.ts.map +1 -0
  384. package/dist/services/agentInstructionsBuilder.js +65 -0
  385. package/dist/services/agentInstructionsBuilder.js.map +1 -0
  386. package/dist/services/contextActionsExecutor.d.ts +19 -0
  387. package/dist/services/contextActionsExecutor.d.ts.map +1 -0
  388. package/dist/services/contextActionsExecutor.js +18 -0
  389. package/dist/services/contextActionsExecutor.js.map +1 -0
  390. package/dist/services/logService.d.ts +3 -0
  391. package/dist/services/logService.d.ts.map +1 -0
  392. package/dist/services/logService.js +4 -0
  393. package/dist/services/logService.js.map +1 -0
  394. package/dist/services/mrTrackingService.d.ts +196 -0
  395. package/dist/services/mrTrackingService.d.ts.map +1 -0
  396. package/dist/services/mrTrackingService.js +540 -0
  397. package/dist/services/mrTrackingService.js.map +1 -0
  398. package/dist/services/reviewContextWatcher.service.d.ts +15 -0
  399. package/dist/services/reviewContextWatcher.service.d.ts.map +1 -0
  400. package/dist/services/reviewContextWatcher.service.js +44 -0
  401. package/dist/services/reviewContextWatcher.service.js.map +1 -0
  402. package/dist/services/runtimeSettings.d.ts +3 -0
  403. package/dist/services/runtimeSettings.d.ts.map +1 -0
  404. package/dist/services/runtimeSettings.js +4 -0
  405. package/dist/services/runtimeSettings.js.map +1 -0
  406. package/dist/services/statsService.d.ts +76 -0
  407. package/dist/services/statsService.d.ts.map +1 -0
  408. package/dist/services/statsService.js +250 -0
  409. package/dist/services/statsService.js.map +1 -0
  410. package/dist/services/threadActionsExecutor.d.ts +26 -0
  411. package/dist/services/threadActionsExecutor.d.ts.map +1 -0
  412. package/dist/services/threadActionsExecutor.js +27 -0
  413. package/dist/services/threadActionsExecutor.js.map +1 -0
  414. package/dist/services/threadActionsParser.d.ts +4 -0
  415. package/dist/services/threadActionsParser.d.ts.map +1 -0
  416. package/dist/services/threadActionsParser.js +50 -0
  417. package/dist/services/threadActionsParser.js.map +1 -0
  418. package/dist/shared/foundation/executionGateway.base.d.ts +14 -0
  419. package/dist/shared/foundation/executionGateway.base.d.ts.map +1 -0
  420. package/dist/shared/foundation/executionGateway.base.js +30 -0
  421. package/dist/shared/foundation/executionGateway.base.js.map +1 -0
  422. package/dist/shared/foundation/gateway.base.d.ts +9 -0
  423. package/dist/shared/foundation/gateway.base.d.ts.map +1 -0
  424. package/dist/shared/foundation/gateway.base.js +2 -0
  425. package/dist/shared/foundation/gateway.base.js.map +1 -0
  426. package/dist/shared/foundation/guard.base.d.ts +8 -0
  427. package/dist/shared/foundation/guard.base.d.ts.map +1 -0
  428. package/dist/shared/foundation/guard.base.js +17 -0
  429. package/dist/shared/foundation/guard.base.js.map +1 -0
  430. package/dist/shared/foundation/presenter.base.d.ts +4 -0
  431. package/dist/shared/foundation/presenter.base.d.ts.map +1 -0
  432. package/dist/shared/foundation/presenter.base.js +2 -0
  433. package/dist/shared/foundation/presenter.base.js.map +1 -0
  434. package/dist/shared/foundation/usecase.base.d.ts +4 -0
  435. package/dist/shared/foundation/usecase.base.d.ts.map +1 -0
  436. package/dist/shared/foundation/usecase.base.js +2 -0
  437. package/dist/shared/foundation/usecase.base.js.map +1 -0
  438. package/dist/shared/services/claudePathResolver.d.ts +3 -0
  439. package/dist/shared/services/claudePathResolver.d.ts.map +1 -0
  440. package/dist/shared/services/claudePathResolver.js +62 -0
  441. package/dist/shared/services/claudePathResolver.js.map +1 -0
  442. package/dist/shared/services/dependencyChecker.d.ts +13 -0
  443. package/dist/shared/services/dependencyChecker.d.ts.map +1 -0
  444. package/dist/shared/services/dependencyChecker.js +37 -0
  445. package/dist/shared/services/dependencyChecker.js.map +1 -0
  446. package/dist/shared/services/mcpJobContext.d.ts +3 -0
  447. package/dist/shared/services/mcpJobContext.d.ts.map +1 -0
  448. package/dist/shared/services/mcpJobContext.js +10 -0
  449. package/dist/shared/services/mcpJobContext.js.map +1 -0
  450. package/dist/tests/factories/config.factory.d.ts +4 -0
  451. package/dist/tests/factories/config.factory.d.ts.map +1 -0
  452. package/dist/tests/factories/config.factory.js +27 -0
  453. package/dist/tests/factories/config.factory.js.map +1 -0
  454. package/dist/tests/factories/gitHubEvent.factory.d.ts +14 -0
  455. package/dist/tests/factories/gitHubEvent.factory.d.ts.map +1 -0
  456. package/dist/tests/factories/gitHubEvent.factory.js +93 -0
  457. package/dist/tests/factories/gitHubEvent.factory.js.map +1 -0
  458. package/dist/tests/factories/gitLabEvent.factory.d.ts +18 -0
  459. package/dist/tests/factories/gitLabEvent.factory.d.ts.map +1 -0
  460. package/dist/tests/factories/gitLabEvent.factory.js +129 -0
  461. package/dist/tests/factories/gitLabEvent.factory.js.map +1 -0
  462. package/dist/tests/factories/githubApiResponse.factory.d.ts +21 -0
  463. package/dist/tests/factories/githubApiResponse.factory.d.ts.map +1 -0
  464. package/dist/tests/factories/githubApiResponse.factory.js +25 -0
  465. package/dist/tests/factories/githubApiResponse.factory.js.map +1 -0
  466. package/dist/tests/factories/gitlabApiResponse.factory.d.ts +26 -0
  467. package/dist/tests/factories/gitlabApiResponse.factory.d.ts.map +1 -0
  468. package/dist/tests/factories/gitlabApiResponse.factory.js +9 -0
  469. package/dist/tests/factories/gitlabApiResponse.factory.js.map +1 -0
  470. package/dist/tests/factories/projectStats.factory.d.ts +9 -0
  471. package/dist/tests/factories/projectStats.factory.d.ts.map +1 -0
  472. package/dist/tests/factories/projectStats.factory.js +48 -0
  473. package/dist/tests/factories/projectStats.factory.js.map +1 -0
  474. package/dist/tests/factories/reviewContext.factory.d.ts +9 -0
  475. package/dist/tests/factories/reviewContext.factory.d.ts.map +1 -0
  476. package/dist/tests/factories/reviewContext.factory.js +59 -0
  477. package/dist/tests/factories/reviewContext.factory.js.map +1 -0
  478. package/dist/tests/factories/reviewJob.factory.d.ts +10 -0
  479. package/dist/tests/factories/reviewJob.factory.d.ts.map +1 -0
  480. package/dist/tests/factories/reviewJob.factory.js +43 -0
  481. package/dist/tests/factories/reviewJob.factory.js.map +1 -0
  482. package/dist/tests/factories/trackedMr.factory.d.ts +10 -0
  483. package/dist/tests/factories/trackedMr.factory.d.ts.map +1 -0
  484. package/dist/tests/factories/trackedMr.factory.js +65 -0
  485. package/dist/tests/factories/trackedMr.factory.js.map +1 -0
  486. package/dist/tests/factories/webhookEvent.factory.d.ts +8 -0
  487. package/dist/tests/factories/webhookEvent.factory.d.ts.map +1 -0
  488. package/dist/tests/factories/webhookEvent.factory.js +72 -0
  489. package/dist/tests/factories/webhookEvent.factory.js.map +1 -0
  490. package/dist/tests/integration/server.integration.test.d.ts +2 -0
  491. package/dist/tests/integration/server.integration.test.d.ts.map +1 -0
  492. package/dist/tests/integration/server.integration.test.js +93 -0
  493. package/dist/tests/integration/server.integration.test.js.map +1 -0
  494. package/dist/tests/stubs/fastifyRequest.stub.d.ts +9 -0
  495. package/dist/tests/stubs/fastifyRequest.stub.d.ts.map +1 -0
  496. package/dist/tests/stubs/fastifyRequest.stub.js +11 -0
  497. package/dist/tests/stubs/fastifyRequest.stub.js.map +1 -0
  498. package/dist/tests/stubs/logger.stub.d.ts +3 -0
  499. package/dist/tests/stubs/logger.stub.d.ts.map +1 -0
  500. package/dist/tests/stubs/logger.stub.js +14 -0
  501. package/dist/tests/stubs/logger.stub.js.map +1 -0
  502. package/dist/tests/stubs/reviewContextGateway.stub.d.ts +18 -0
  503. package/dist/tests/stubs/reviewContextGateway.stub.d.ts.map +1 -0
  504. package/dist/tests/stubs/reviewContextGateway.stub.js +69 -0
  505. package/dist/tests/stubs/reviewContextGateway.stub.js.map +1 -0
  506. package/dist/tests/stubs/reviewFile.stub.d.ts +13 -0
  507. package/dist/tests/stubs/reviewFile.stub.d.ts.map +1 -0
  508. package/dist/tests/stubs/reviewFile.stub.js +56 -0
  509. package/dist/tests/stubs/reviewFile.stub.js.map +1 -0
  510. package/dist/tests/stubs/reviewQueue.stub.d.ts +20 -0
  511. package/dist/tests/stubs/reviewQueue.stub.d.ts.map +1 -0
  512. package/dist/tests/stubs/reviewQueue.stub.js +46 -0
  513. package/dist/tests/stubs/reviewQueue.stub.js.map +1 -0
  514. package/dist/tests/stubs/reviewRequestTracking.stub.d.ts +21 -0
  515. package/dist/tests/stubs/reviewRequestTracking.stub.d.ts.map +1 -0
  516. package/dist/tests/stubs/reviewRequestTracking.stub.js +121 -0
  517. package/dist/tests/stubs/reviewRequestTracking.stub.js.map +1 -0
  518. package/dist/tests/stubs/stats.stub.d.ts +10 -0
  519. package/dist/tests/stubs/stats.stub.d.ts.map +1 -0
  520. package/dist/tests/stubs/stats.stub.js +17 -0
  521. package/dist/tests/stubs/stats.stub.js.map +1 -0
  522. package/dist/tests/stubs/threadFetch.stub.d.ts +8 -0
  523. package/dist/tests/stubs/threadFetch.stub.d.ts.map +1 -0
  524. package/dist/tests/stubs/threadFetch.stub.js +10 -0
  525. package/dist/tests/stubs/threadFetch.stub.js.map +1 -0
  526. package/dist/tests/units/claude/progressParser.test.d.ts +2 -0
  527. package/dist/tests/units/claude/progressParser.test.d.ts.map +1 -0
  528. package/dist/tests/units/claude/progressParser.test.js +202 -0
  529. package/dist/tests/units/claude/progressParser.test.js.map +1 -0
  530. package/dist/tests/units/cli/cli.integration.test.d.ts +2 -0
  531. package/dist/tests/units/cli/cli.integration.test.d.ts.map +1 -0
  532. package/dist/tests/units/cli/cli.integration.test.js +18 -0
  533. package/dist/tests/units/cli/cli.integration.test.js.map +1 -0
  534. package/dist/tests/units/cli/parseCliArgs.test.d.ts +2 -0
  535. package/dist/tests/units/cli/parseCliArgs.test.d.ts.map +1 -0
  536. package/dist/tests/units/cli/parseCliArgs.test.js +35 -0
  537. package/dist/tests/units/cli/parseCliArgs.test.js.map +1 -0
  538. package/dist/tests/units/entities/duration.valueObject.test.d.ts +2 -0
  539. package/dist/tests/units/entities/duration.valueObject.test.d.ts.map +1 -0
  540. package/dist/tests/units/entities/duration.valueObject.test.js +112 -0
  541. package/dist/tests/units/entities/duration.valueObject.test.js.map +1 -0
  542. package/dist/tests/units/entities/github/githubPullRequestEvent.guard.test.d.ts +2 -0
  543. package/dist/tests/units/entities/github/githubPullRequestEvent.guard.test.d.ts.map +1 -0
  544. package/dist/tests/units/entities/github/githubPullRequestEvent.guard.test.js +53 -0
  545. package/dist/tests/units/entities/github/githubPullRequestEvent.guard.test.js.map +1 -0
  546. package/dist/tests/units/entities/gitlab/gitlabMergeRequestEvent.guard.test.d.ts +2 -0
  547. package/dist/tests/units/entities/gitlab/gitlabMergeRequestEvent.guard.test.d.ts.map +1 -0
  548. package/dist/tests/units/entities/gitlab/gitlabMergeRequestEvent.guard.test.js +97 -0
  549. package/dist/tests/units/entities/gitlab/gitlabMergeRequestEvent.guard.test.js.map +1 -0
  550. package/dist/tests/units/entities/progress/progress.test.d.ts +2 -0
  551. package/dist/tests/units/entities/progress/progress.test.d.ts.map +1 -0
  552. package/dist/tests/units/entities/progress/progress.test.js +137 -0
  553. package/dist/tests/units/entities/progress/progress.test.js.map +1 -0
  554. package/dist/tests/units/entities/reviewAction/reviewAction.guard.test.d.ts +2 -0
  555. package/dist/tests/units/entities/reviewAction/reviewAction.guard.test.d.ts.map +1 -0
  556. package/dist/tests/units/entities/reviewAction/reviewAction.guard.test.js +89 -0
  557. package/dist/tests/units/entities/reviewAction/reviewAction.guard.test.js.map +1 -0
  558. package/dist/tests/units/entities/reviewContext/reviewContext.schema.test.d.ts +2 -0
  559. package/dist/tests/units/entities/reviewContext/reviewContext.schema.test.d.ts.map +1 -0
  560. package/dist/tests/units/entities/reviewContext/reviewContext.schema.test.js +176 -0
  561. package/dist/tests/units/entities/reviewContext/reviewContext.schema.test.js.map +1 -0
  562. package/dist/tests/units/entities/reviewContext/reviewContextAction.guard.test.d.ts +2 -0
  563. package/dist/tests/units/entities/reviewContext/reviewContextAction.guard.test.d.ts.map +1 -0
  564. package/dist/tests/units/entities/reviewContext/reviewContextAction.guard.test.js +88 -0
  565. package/dist/tests/units/entities/reviewContext/reviewContextAction.guard.test.js.map +1 -0
  566. package/dist/tests/units/entities/reviewContext/reviewContextAction.schema.test.d.ts +2 -0
  567. package/dist/tests/units/entities/reviewContext/reviewContextAction.schema.test.d.ts.map +1 -0
  568. package/dist/tests/units/entities/reviewContext/reviewContextAction.schema.test.js +132 -0
  569. package/dist/tests/units/entities/reviewContext/reviewContextAction.schema.test.js.map +1 -0
  570. package/dist/tests/units/entities/reviewRequestState.valueObject.test.d.ts +2 -0
  571. package/dist/tests/units/entities/reviewRequestState.valueObject.test.d.ts.map +1 -0
  572. package/dist/tests/units/entities/reviewRequestState.valueObject.test.js +100 -0
  573. package/dist/tests/units/entities/reviewRequestState.valueObject.test.js.map +1 -0
  574. package/dist/tests/units/entities/reviewScore.valueObject.test.d.ts +2 -0
  575. package/dist/tests/units/entities/reviewScore.valueObject.test.d.ts.map +1 -0
  576. package/dist/tests/units/entities/reviewScore.valueObject.test.js +90 -0
  577. package/dist/tests/units/entities/reviewScore.valueObject.test.js.map +1 -0
  578. package/dist/tests/units/factories/factories.test.d.ts +2 -0
  579. package/dist/tests/units/factories/factories.test.d.ts.map +1 -0
  580. package/dist/tests/units/factories/factories.test.js +100 -0
  581. package/dist/tests/units/factories/factories.test.js.map +1 -0
  582. package/dist/tests/units/frameworks/claude/ensureProjectMcpConfig.test.d.ts +2 -0
  583. package/dist/tests/units/frameworks/claude/ensureProjectMcpConfig.test.d.ts.map +1 -0
  584. package/dist/tests/units/frameworks/claude/ensureProjectMcpConfig.test.js +88 -0
  585. package/dist/tests/units/frameworks/claude/ensureProjectMcpConfig.test.js.map +1 -0
  586. package/dist/tests/units/frameworks/claude/mcpContext.test.d.ts +2 -0
  587. package/dist/tests/units/frameworks/claude/mcpContext.test.d.ts.map +1 -0
  588. package/dist/tests/units/frameworks/claude/mcpContext.test.js +88 -0
  589. package/dist/tests/units/frameworks/claude/mcpContext.test.js.map +1 -0
  590. package/dist/tests/units/frameworks/claude/resolveMcpServerPath.test.d.ts +2 -0
  591. package/dist/tests/units/frameworks/claude/resolveMcpServerPath.test.d.ts.map +1 -0
  592. package/dist/tests/units/frameworks/claude/resolveMcpServerPath.test.js +20 -0
  593. package/dist/tests/units/frameworks/claude/resolveMcpServerPath.test.js.map +1 -0
  594. package/dist/tests/units/interface-adapters/adapters/platformAdapter.test.d.ts +2 -0
  595. package/dist/tests/units/interface-adapters/adapters/platformAdapter.test.d.ts.map +1 -0
  596. package/dist/tests/units/interface-adapters/adapters/platformAdapter.test.js +181 -0
  597. package/dist/tests/units/interface-adapters/adapters/platformAdapter.test.js.map +1 -0
  598. package/dist/tests/units/interface-adapters/controllers/mcp/addAction.handler.test.d.ts +2 -0
  599. package/dist/tests/units/interface-adapters/controllers/mcp/addAction.handler.test.d.ts.map +1 -0
  600. package/dist/tests/units/interface-adapters/controllers/mcp/addAction.handler.test.js +84 -0
  601. package/dist/tests/units/interface-adapters/controllers/mcp/addAction.handler.test.js.map +1 -0
  602. package/dist/tests/units/interface-adapters/controllers/mcp/completeAgent.handler.test.d.ts +2 -0
  603. package/dist/tests/units/interface-adapters/controllers/mcp/completeAgent.handler.test.d.ts.map +1 -0
  604. package/dist/tests/units/interface-adapters/controllers/mcp/completeAgent.handler.test.js +71 -0
  605. package/dist/tests/units/interface-adapters/controllers/mcp/completeAgent.handler.test.js.map +1 -0
  606. package/dist/tests/units/interface-adapters/controllers/mcp/getThreads.handler.test.d.ts +2 -0
  607. package/dist/tests/units/interface-adapters/controllers/mcp/getThreads.handler.test.d.ts.map +1 -0
  608. package/dist/tests/units/interface-adapters/controllers/mcp/getThreads.handler.test.js +52 -0
  609. package/dist/tests/units/interface-adapters/controllers/mcp/getThreads.handler.test.js.map +1 -0
  610. package/dist/tests/units/interface-adapters/controllers/mcp/getWorkflow.handler.test.d.ts +2 -0
  611. package/dist/tests/units/interface-adapters/controllers/mcp/getWorkflow.handler.test.d.ts.map +1 -0
  612. package/dist/tests/units/interface-adapters/controllers/mcp/getWorkflow.handler.test.js +32 -0
  613. package/dist/tests/units/interface-adapters/controllers/mcp/getWorkflow.handler.test.js.map +1 -0
  614. package/dist/tests/units/interface-adapters/controllers/mcp/setPhase.handler.test.d.ts +2 -0
  615. package/dist/tests/units/interface-adapters/controllers/mcp/setPhase.handler.test.d.ts.map +1 -0
  616. package/dist/tests/units/interface-adapters/controllers/mcp/setPhase.handler.test.js +44 -0
  617. package/dist/tests/units/interface-adapters/controllers/mcp/setPhase.handler.test.js.map +1 -0
  618. package/dist/tests/units/interface-adapters/controllers/mcp/startAgent.handler.test.d.ts +2 -0
  619. package/dist/tests/units/interface-adapters/controllers/mcp/startAgent.handler.test.d.ts.map +1 -0
  620. package/dist/tests/units/interface-adapters/controllers/mcp/startAgent.handler.test.js +38 -0
  621. package/dist/tests/units/interface-adapters/controllers/mcp/startAgent.handler.test.js.map +1 -0
  622. package/dist/tests/units/interface-adapters/controllers/webhook/eventFilter.test.d.ts +2 -0
  623. package/dist/tests/units/interface-adapters/controllers/webhook/eventFilter.test.d.ts.map +1 -0
  624. package/dist/tests/units/interface-adapters/controllers/webhook/eventFilter.test.js +389 -0
  625. package/dist/tests/units/interface-adapters/controllers/webhook/eventFilter.test.js.map +1 -0
  626. package/dist/tests/units/interface-adapters/controllers/webhook/github.controller.test.d.ts +2 -0
  627. package/dist/tests/units/interface-adapters/controllers/webhook/github.controller.test.d.ts.map +1 -0
  628. package/dist/tests/units/interface-adapters/controllers/webhook/github.controller.test.js +284 -0
  629. package/dist/tests/units/interface-adapters/controllers/webhook/github.controller.test.js.map +1 -0
  630. package/dist/tests/units/interface-adapters/controllers/webhook/gitlab.controller.test.d.ts +2 -0
  631. package/dist/tests/units/interface-adapters/controllers/webhook/gitlab.controller.test.d.ts.map +1 -0
  632. package/dist/tests/units/interface-adapters/controllers/webhook/gitlab.controller.test.js +202 -0
  633. package/dist/tests/units/interface-adapters/controllers/webhook/gitlab.controller.test.js.map +1 -0
  634. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.test.d.ts +2 -0
  635. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.test.d.ts.map +1 -0
  636. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.test.js +83 -0
  637. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.github.cli.gateway.test.js.map +1 -0
  638. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.test.d.ts +2 -0
  639. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.test.d.ts.map +1 -0
  640. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.test.js +92 -0
  641. package/dist/tests/units/interface-adapters/gateways/cli/reviewAction.gitlab.cli.gateway.test.js.map +1 -0
  642. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.github.gateway.test.d.ts +2 -0
  643. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.github.gateway.test.d.ts.map +1 -0
  644. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.github.gateway.test.js +41 -0
  645. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.github.gateway.test.js.map +1 -0
  646. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.test.d.ts +2 -0
  647. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.test.d.ts.map +1 -0
  648. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.test.js +57 -0
  649. package/dist/tests/units/interface-adapters/gateways/diffMetadataFetch.gitlab.gateway.test.js.map +1 -0
  650. package/dist/tests/units/interface-adapters/gateways/reviewContext.fileSystem.gateway.test.d.ts +2 -0
  651. package/dist/tests/units/interface-adapters/gateways/reviewContext.fileSystem.gateway.test.d.ts.map +1 -0
  652. package/dist/tests/units/interface-adapters/gateways/reviewContext.fileSystem.gateway.test.js +204 -0
  653. package/dist/tests/units/interface-adapters/gateways/reviewContext.fileSystem.gateway.test.js.map +1 -0
  654. package/dist/tests/units/interface-adapters/gateways/reviewFile.gateway.test.d.ts +2 -0
  655. package/dist/tests/units/interface-adapters/gateways/reviewFile.gateway.test.d.ts.map +1 -0
  656. package/dist/tests/units/interface-adapters/gateways/reviewFile.gateway.test.js +126 -0
  657. package/dist/tests/units/interface-adapters/gateways/reviewFile.gateway.test.js.map +1 -0
  658. package/dist/tests/units/interface-adapters/gateways/reviewProgress.memory.gateway.test.d.ts +2 -0
  659. package/dist/tests/units/interface-adapters/gateways/reviewProgress.memory.gateway.test.d.ts.map +1 -0
  660. package/dist/tests/units/interface-adapters/gateways/reviewProgress.memory.gateway.test.js +137 -0
  661. package/dist/tests/units/interface-adapters/gateways/reviewProgress.memory.gateway.test.js.map +1 -0
  662. package/dist/tests/units/interface-adapters/gateways/reviewRequestTracking.gateway.test.d.ts +2 -0
  663. package/dist/tests/units/interface-adapters/gateways/reviewRequestTracking.gateway.test.d.ts.map +1 -0
  664. package/dist/tests/units/interface-adapters/gateways/reviewRequestTracking.gateway.test.js +242 -0
  665. package/dist/tests/units/interface-adapters/gateways/reviewRequestTracking.gateway.test.js.map +1 -0
  666. package/dist/tests/units/interface-adapters/gateways/stats.gateway.test.d.ts +2 -0
  667. package/dist/tests/units/interface-adapters/gateways/stats.gateway.test.d.ts.map +1 -0
  668. package/dist/tests/units/interface-adapters/gateways/stats.gateway.test.js +52 -0
  669. package/dist/tests/units/interface-adapters/gateways/stats.gateway.test.js.map +1 -0
  670. package/dist/tests/units/interface-adapters/gateways/threadFetch.github.gateway.test.d.ts +2 -0
  671. package/dist/tests/units/interface-adapters/gateways/threadFetch.github.gateway.test.d.ts.map +1 -0
  672. package/dist/tests/units/interface-adapters/gateways/threadFetch.github.gateway.test.js +41 -0
  673. package/dist/tests/units/interface-adapters/gateways/threadFetch.github.gateway.test.js.map +1 -0
  674. package/dist/tests/units/interface-adapters/gateways/threadFetch.gitlab.gateway.test.d.ts +2 -0
  675. package/dist/tests/units/interface-adapters/gateways/threadFetch.gitlab.gateway.test.d.ts.map +1 -0
  676. package/dist/tests/units/interface-adapters/gateways/threadFetch.gitlab.gateway.test.js +31 -0
  677. package/dist/tests/units/interface-adapters/gateways/threadFetch.gitlab.gateway.test.js.map +1 -0
  678. package/dist/tests/units/interface-adapters/presenters/jobStatus.presenter.test.d.ts +2 -0
  679. package/dist/tests/units/interface-adapters/presenters/jobStatus.presenter.test.d.ts.map +1 -0
  680. package/dist/tests/units/interface-adapters/presenters/jobStatus.presenter.test.js +128 -0
  681. package/dist/tests/units/interface-adapters/presenters/jobStatus.presenter.test.js.map +1 -0
  682. package/dist/tests/units/interface-adapters/presenters/reviewContextProgress.presenter.test.d.ts +2 -0
  683. package/dist/tests/units/interface-adapters/presenters/reviewContextProgress.presenter.test.d.ts.map +1 -0
  684. package/dist/tests/units/interface-adapters/presenters/reviewContextProgress.presenter.test.js +83 -0
  685. package/dist/tests/units/interface-adapters/presenters/reviewContextProgress.presenter.test.js.map +1 -0
  686. package/dist/tests/units/interface-adapters/presenters/reviewList.presenter.test.d.ts +2 -0
  687. package/dist/tests/units/interface-adapters/presenters/reviewList.presenter.test.d.ts.map +1 -0
  688. package/dist/tests/units/interface-adapters/presenters/reviewList.presenter.test.js +64 -0
  689. package/dist/tests/units/interface-adapters/presenters/reviewList.presenter.test.js.map +1 -0
  690. package/dist/tests/units/interface-adapters/services/projectStats.calculator.test.d.ts +2 -0
  691. package/dist/tests/units/interface-adapters/services/projectStats.calculator.test.d.ts.map +1 -0
  692. package/dist/tests/units/interface-adapters/services/projectStats.calculator.test.js +85 -0
  693. package/dist/tests/units/interface-adapters/services/projectStats.calculator.test.js.map +1 -0
  694. package/dist/tests/units/main/dependencies.test.d.ts +2 -0
  695. package/dist/tests/units/main/dependencies.test.d.ts.map +1 -0
  696. package/dist/tests/units/main/dependencies.test.js +43 -0
  697. package/dist/tests/units/main/dependencies.test.js.map +1 -0
  698. package/dist/tests/units/main/executeStart.test.d.ts +2 -0
  699. package/dist/tests/units/main/executeStart.test.d.ts.map +1 -0
  700. package/dist/tests/units/main/executeStart.test.js +61 -0
  701. package/dist/tests/units/main/executeStart.test.js.map +1 -0
  702. package/dist/tests/units/main/mcpDependencies.test.d.ts +2 -0
  703. package/dist/tests/units/main/mcpDependencies.test.d.ts.map +1 -0
  704. package/dist/tests/units/main/mcpDependencies.test.js +56 -0
  705. package/dist/tests/units/main/mcpDependencies.test.js.map +1 -0
  706. package/dist/tests/units/main/websocket.test.d.ts +2 -0
  707. package/dist/tests/units/main/websocket.test.d.ts.map +1 -0
  708. package/dist/tests/units/main/websocket.test.js +63 -0
  709. package/dist/tests/units/main/websocket.test.js.map +1 -0
  710. package/dist/tests/units/mcp/mcpServerStdio.test.d.ts +2 -0
  711. package/dist/tests/units/mcp/mcpServerStdio.test.d.ts.map +1 -0
  712. package/dist/tests/units/mcp/mcpServerStdio.test.js +179 -0
  713. package/dist/tests/units/mcp/mcpServerStdio.test.js.map +1 -0
  714. package/dist/tests/units/mcp/server.test.d.ts +2 -0
  715. package/dist/tests/units/mcp/server.test.d.ts.map +1 -0
  716. package/dist/tests/units/mcp/server.test.js +85 -0
  717. package/dist/tests/units/mcp/server.test.js.map +1 -0
  718. package/dist/tests/units/security/verifier.test.d.ts +2 -0
  719. package/dist/tests/units/security/verifier.test.d.ts.map +1 -0
  720. package/dist/tests/units/security/verifier.test.js +200 -0
  721. package/dist/tests/units/security/verifier.test.js.map +1 -0
  722. package/dist/tests/units/services/contextActionsExecutor.test.d.ts +2 -0
  723. package/dist/tests/units/services/contextActionsExecutor.test.d.ts.map +1 -0
  724. package/dist/tests/units/services/contextActionsExecutor.test.js +112 -0
  725. package/dist/tests/units/services/contextActionsExecutor.test.js.map +1 -0
  726. package/dist/tests/units/services/mrTrackingRemoveMr.test.d.ts +2 -0
  727. package/dist/tests/units/services/mrTrackingRemoveMr.test.d.ts.map +1 -0
  728. package/dist/tests/units/services/mrTrackingRemoveMr.test.js +155 -0
  729. package/dist/tests/units/services/mrTrackingRemoveMr.test.js.map +1 -0
  730. package/dist/tests/units/services/mrTrackingService.autoFollowup.test.d.ts +2 -0
  731. package/dist/tests/units/services/mrTrackingService.autoFollowup.test.d.ts.map +1 -0
  732. package/dist/tests/units/services/mrTrackingService.autoFollowup.test.js +82 -0
  733. package/dist/tests/units/services/mrTrackingService.autoFollowup.test.js.map +1 -0
  734. package/dist/tests/units/services/reviewContextWatcher.service.test.d.ts +2 -0
  735. package/dist/tests/units/services/reviewContextWatcher.service.test.d.ts.map +1 -0
  736. package/dist/tests/units/services/reviewContextWatcher.service.test.js +112 -0
  737. package/dist/tests/units/services/reviewContextWatcher.service.test.js.map +1 -0
  738. package/dist/tests/units/services/threadActionsExecutor.test.d.ts +2 -0
  739. package/dist/tests/units/services/threadActionsExecutor.test.d.ts.map +1 -0
  740. package/dist/tests/units/services/threadActionsExecutor.test.js +206 -0
  741. package/dist/tests/units/services/threadActionsExecutor.test.js.map +1 -0
  742. package/dist/tests/units/services/threadActionsParser.test.d.ts +2 -0
  743. package/dist/tests/units/services/threadActionsParser.test.d.ts.map +1 -0
  744. package/dist/tests/units/services/threadActionsParser.test.js +148 -0
  745. package/dist/tests/units/services/threadActionsParser.test.js.map +1 -0
  746. package/dist/tests/units/shared/foundation/foundation.contracts.test.d.ts +2 -0
  747. package/dist/tests/units/shared/foundation/foundation.contracts.test.d.ts.map +1 -0
  748. package/dist/tests/units/shared/foundation/foundation.contracts.test.js +46 -0
  749. package/dist/tests/units/shared/foundation/foundation.contracts.test.js.map +1 -0
  750. package/dist/tests/units/shared/foundation/guard.base.test.d.ts +2 -0
  751. package/dist/tests/units/shared/foundation/guard.base.test.d.ts.map +1 -0
  752. package/dist/tests/units/shared/foundation/guard.base.test.js +40 -0
  753. package/dist/tests/units/shared/foundation/guard.base.test.js.map +1 -0
  754. package/dist/tests/units/shared/services/claudePathResolver.test.d.ts +2 -0
  755. package/dist/tests/units/shared/services/claudePathResolver.test.d.ts.map +1 -0
  756. package/dist/tests/units/shared/services/claudePathResolver.test.js +61 -0
  757. package/dist/tests/units/shared/services/claudePathResolver.test.js.map +1 -0
  758. package/dist/tests/units/shared/services/dependencyChecker.test.d.ts +2 -0
  759. package/dist/tests/units/shared/services/dependencyChecker.test.d.ts.map +1 -0
  760. package/dist/tests/units/shared/services/dependencyChecker.test.js +35 -0
  761. package/dist/tests/units/shared/services/dependencyChecker.test.js.map +1 -0
  762. package/dist/tests/units/shared/services/mcpJobContext.test.d.ts +2 -0
  763. package/dist/tests/units/shared/services/mcpJobContext.test.d.ts.map +1 -0
  764. package/dist/tests/units/shared/services/mcpJobContext.test.js +38 -0
  765. package/dist/tests/units/shared/services/mcpJobContext.test.js.map +1 -0
  766. package/dist/tests/units/types/progress.test.d.ts +2 -0
  767. package/dist/tests/units/types/progress.test.d.ts.map +1 -0
  768. package/dist/tests/units/types/progress.test.js +135 -0
  769. package/dist/tests/units/types/progress.test.js.map +1 -0
  770. package/dist/tests/units/usecases/cancelReview.usecase.test.d.ts +2 -0
  771. package/dist/tests/units/usecases/cancelReview.usecase.test.d.ts.map +1 -0
  772. package/dist/tests/units/usecases/cancelReview.usecase.test.js +57 -0
  773. package/dist/tests/units/usecases/cancelReview.usecase.test.js.map +1 -0
  774. package/dist/tests/units/usecases/handleReviewRequestPush.usecase.test.d.ts +2 -0
  775. package/dist/tests/units/usecases/handleReviewRequestPush.usecase.test.d.ts.map +1 -0
  776. package/dist/tests/units/usecases/handleReviewRequestPush.usecase.test.js +124 -0
  777. package/dist/tests/units/usecases/handleReviewRequestPush.usecase.test.js.map +1 -0
  778. package/dist/tests/units/usecases/mcp/addAction.usecase.test.d.ts +2 -0
  779. package/dist/tests/units/usecases/mcp/addAction.usecase.test.d.ts.map +1 -0
  780. package/dist/tests/units/usecases/mcp/addAction.usecase.test.js +123 -0
  781. package/dist/tests/units/usecases/mcp/addAction.usecase.test.js.map +1 -0
  782. package/dist/tests/units/usecases/mcp/completeAgent.usecase.test.d.ts +2 -0
  783. package/dist/tests/units/usecases/mcp/completeAgent.usecase.test.d.ts.map +1 -0
  784. package/dist/tests/units/usecases/mcp/completeAgent.usecase.test.js +67 -0
  785. package/dist/tests/units/usecases/mcp/completeAgent.usecase.test.js.map +1 -0
  786. package/dist/tests/units/usecases/mcp/getThreads.usecase.test.d.ts +2 -0
  787. package/dist/tests/units/usecases/mcp/getThreads.usecase.test.d.ts.map +1 -0
  788. package/dist/tests/units/usecases/mcp/getThreads.usecase.test.js +77 -0
  789. package/dist/tests/units/usecases/mcp/getThreads.usecase.test.js.map +1 -0
  790. package/dist/tests/units/usecases/mcp/getWorkflow.usecase.test.d.ts +2 -0
  791. package/dist/tests/units/usecases/mcp/getWorkflow.usecase.test.d.ts.map +1 -0
  792. package/dist/tests/units/usecases/mcp/getWorkflow.usecase.test.js +55 -0
  793. package/dist/tests/units/usecases/mcp/getWorkflow.usecase.test.js.map +1 -0
  794. package/dist/tests/units/usecases/mcp/setPhase.usecase.test.d.ts +2 -0
  795. package/dist/tests/units/usecases/mcp/setPhase.usecase.test.d.ts.map +1 -0
  796. package/dist/tests/units/usecases/mcp/setPhase.usecase.test.js +41 -0
  797. package/dist/tests/units/usecases/mcp/setPhase.usecase.test.js.map +1 -0
  798. package/dist/tests/units/usecases/mcp/startAgent.usecase.test.d.ts +2 -0
  799. package/dist/tests/units/usecases/mcp/startAgent.usecase.test.d.ts.map +1 -0
  800. package/dist/tests/units/usecases/mcp/startAgent.usecase.test.js +42 -0
  801. package/dist/tests/units/usecases/mcp/startAgent.usecase.test.js.map +1 -0
  802. package/dist/tests/units/usecases/tracking/checkFollowupNeeded.usecase.test.d.ts +2 -0
  803. package/dist/tests/units/usecases/tracking/checkFollowupNeeded.usecase.test.d.ts.map +1 -0
  804. package/dist/tests/units/usecases/tracking/checkFollowupNeeded.usecase.test.js +71 -0
  805. package/dist/tests/units/usecases/tracking/checkFollowupNeeded.usecase.test.js.map +1 -0
  806. package/dist/tests/units/usecases/tracking/recordPush.usecase.test.d.ts +2 -0
  807. package/dist/tests/units/usecases/tracking/recordPush.usecase.test.d.ts.map +1 -0
  808. package/dist/tests/units/usecases/tracking/recordPush.usecase.test.js +22 -0
  809. package/dist/tests/units/usecases/tracking/recordPush.usecase.test.js.map +1 -0
  810. package/dist/tests/units/usecases/tracking/recordReviewCompletion.usecase.test.d.ts +2 -0
  811. package/dist/tests/units/usecases/tracking/recordReviewCompletion.usecase.test.d.ts.map +1 -0
  812. package/dist/tests/units/usecases/tracking/recordReviewCompletion.usecase.test.js +106 -0
  813. package/dist/tests/units/usecases/tracking/recordReviewCompletion.usecase.test.js.map +1 -0
  814. package/dist/tests/units/usecases/tracking/syncThreads.usecase.test.d.ts +2 -0
  815. package/dist/tests/units/usecases/tracking/syncThreads.usecase.test.d.ts.map +1 -0
  816. package/dist/tests/units/usecases/tracking/syncThreads.usecase.test.js +76 -0
  817. package/dist/tests/units/usecases/tracking/syncThreads.usecase.test.js.map +1 -0
  818. package/dist/tests/units/usecases/tracking/trackAssignment.usecase.test.d.ts +2 -0
  819. package/dist/tests/units/usecases/tracking/trackAssignment.usecase.test.d.ts.map +1 -0
  820. package/dist/tests/units/usecases/tracking/trackAssignment.usecase.test.js +70 -0
  821. package/dist/tests/units/usecases/tracking/trackAssignment.usecase.test.js.map +1 -0
  822. package/dist/tests/units/usecases/tracking/transitionState.usecase.test.d.ts +2 -0
  823. package/dist/tests/units/usecases/tracking/transitionState.usecase.test.d.ts.map +1 -0
  824. package/dist/tests/units/usecases/tracking/transitionState.usecase.test.js +48 -0
  825. package/dist/tests/units/usecases/tracking/transitionState.usecase.test.js.map +1 -0
  826. package/dist/tests/units/usecases/triggerReview.usecase.test.d.ts +2 -0
  827. package/dist/tests/units/usecases/triggerReview.usecase.test.d.ts.map +1 -0
  828. package/dist/tests/units/usecases/triggerReview.usecase.test.js +103 -0
  829. package/dist/tests/units/usecases/triggerReview.usecase.test.js.map +1 -0
  830. package/dist/types/progress.d.ts +55 -0
  831. package/dist/types/progress.d.ts.map +1 -0
  832. package/dist/types/progress.js +63 -0
  833. package/dist/types/progress.js.map +1 -0
  834. package/dist/usecases/cancelReview.usecase.d.ts +21 -0
  835. package/dist/usecases/cancelReview.usecase.d.ts.map +1 -0
  836. package/dist/usecases/cancelReview.usecase.js +19 -0
  837. package/dist/usecases/cancelReview.usecase.js.map +1 -0
  838. package/dist/usecases/handleReviewRequestPush.usecase.d.ts +26 -0
  839. package/dist/usecases/handleReviewRequestPush.usecase.d.ts.map +1 -0
  840. package/dist/usecases/handleReviewRequestPush.usecase.js +45 -0
  841. package/dist/usecases/handleReviewRequestPush.usecase.js.map +1 -0
  842. package/dist/usecases/mcp/addAction.usecase.d.ts +33 -0
  843. package/dist/usecases/mcp/addAction.usecase.d.ts.map +1 -0
  844. package/dist/usecases/mcp/addAction.usecase.js +94 -0
  845. package/dist/usecases/mcp/addAction.usecase.js.map +1 -0
  846. package/dist/usecases/mcp/completeAgent.usecase.d.ts +18 -0
  847. package/dist/usecases/mcp/completeAgent.usecase.d.ts.map +1 -0
  848. package/dist/usecases/mcp/completeAgent.usecase.js +20 -0
  849. package/dist/usecases/mcp/completeAgent.usecase.js.map +1 -0
  850. package/dist/usecases/mcp/getThreads.usecase.d.ts +16 -0
  851. package/dist/usecases/mcp/getThreads.usecase.d.ts.map +1 -0
  852. package/dist/usecases/mcp/getThreads.usecase.js +22 -0
  853. package/dist/usecases/mcp/getThreads.usecase.js.map +1 -0
  854. package/dist/usecases/mcp/getWorkflow.usecase.d.ts +28 -0
  855. package/dist/usecases/mcp/getWorkflow.usecase.d.ts.map +1 -0
  856. package/dist/usecases/mcp/getWorkflow.usecase.js +36 -0
  857. package/dist/usecases/mcp/getWorkflow.usecase.js.map +1 -0
  858. package/dist/usecases/mcp/setPhase.usecase.d.ts +15 -0
  859. package/dist/usecases/mcp/setPhase.usecase.d.ts.map +1 -0
  860. package/dist/usecases/mcp/setPhase.usecase.js +16 -0
  861. package/dist/usecases/mcp/setPhase.usecase.js.map +1 -0
  862. package/dist/usecases/mcp/startAgent.usecase.d.ts +15 -0
  863. package/dist/usecases/mcp/startAgent.usecase.d.ts.map +1 -0
  864. package/dist/usecases/mcp/startAgent.usecase.js +18 -0
  865. package/dist/usecases/mcp/startAgent.usecase.js.map +1 -0
  866. package/dist/usecases/tracking/checkFollowupNeeded.usecase.d.ts +14 -0
  867. package/dist/usecases/tracking/checkFollowupNeeded.usecase.d.ts.map +1 -0
  868. package/dist/usecases/tracking/checkFollowupNeeded.usecase.js +17 -0
  869. package/dist/usecases/tracking/checkFollowupNeeded.usecase.js.map +1 -0
  870. package/dist/usecases/tracking/recordPush.usecase.d.ts +15 -0
  871. package/dist/usecases/tracking/recordPush.usecase.d.ts.map +1 -0
  872. package/dist/usecases/tracking/recordPush.usecase.js +10 -0
  873. package/dist/usecases/tracking/recordPush.usecase.js.map +1 -0
  874. package/dist/usecases/tracking/recordReviewCompletion.usecase.d.ts +24 -0
  875. package/dist/usecases/tracking/recordReviewCompletion.usecase.d.ts.map +1 -0
  876. package/dist/usecases/tracking/recordReviewCompletion.usecase.js +52 -0
  877. package/dist/usecases/tracking/recordReviewCompletion.usecase.js.map +1 -0
  878. package/dist/usecases/tracking/syncThreads.usecase.d.ts +16 -0
  879. package/dist/usecases/tracking/syncThreads.usecase.d.ts.map +1 -0
  880. package/dist/usecases/tracking/syncThreads.usecase.js +26 -0
  881. package/dist/usecases/tracking/syncThreads.usecase.js.map +1 -0
  882. package/dist/usecases/tracking/trackAssignment.usecase.d.ts +28 -0
  883. package/dist/usecases/tracking/trackAssignment.usecase.d.ts.map +1 -0
  884. package/dist/usecases/tracking/trackAssignment.usecase.js +69 -0
  885. package/dist/usecases/tracking/trackAssignment.usecase.js.map +1 -0
  886. package/dist/usecases/tracking/transitionState.usecase.d.ts +14 -0
  887. package/dist/usecases/tracking/transitionState.usecase.d.ts.map +1 -0
  888. package/dist/usecases/tracking/transitionState.usecase.js +22 -0
  889. package/dist/usecases/tracking/transitionState.usecase.js.map +1 -0
  890. package/dist/usecases/triggerReview.usecase.d.ts +41 -0
  891. package/dist/usecases/triggerReview.usecase.d.ts.map +1 -0
  892. package/dist/usecases/triggerReview.usecase.js +34 -0
  893. package/dist/usecases/triggerReview.usecase.js.map +1 -0
  894. package/package.json +82 -0
  895. package/scripts/copyAssets.mjs +10 -0
  896. package/scripts/launcher.sh +35 -0
  897. package/templates/SETUP.md +183 -0
  898. package/templates/SKILL.md.template +207 -0
  899. package/templates/claude-mcp-config.example.json +12 -0
  900. package/templates/config.json.template +15 -0
  901. package/templates/en/followup-basic/README.md +66 -0
  902. package/templates/en/followup-basic/SKILL.md +317 -0
  903. package/templates/en/review-basic/README.md +75 -0
  904. package/templates/en/review-basic/SKILL.md +160 -0
  905. package/templates/en/review-with-agents/README.md +78 -0
  906. package/templates/en/review-with-agents/SKILL.md +225 -0
  907. package/templates/fr/followup-basic/README.md +66 -0
  908. package/templates/fr/followup-basic/SKILL.md +317 -0
  909. package/templates/fr/review-basic/README.md +59 -0
  910. package/templates/fr/review-basic/SKILL.md +160 -0
  911. package/templates/fr/review-with-agents/README.md +54 -0
  912. package/templates/fr/review-with-agents/SKILL.md +225 -0
  913. package/templates/skills/review-bootstrap/SKILL.md +119 -0
  914. package/templates/skills/review-with-mcp.md +133 -0
@@ -0,0 +1,1537 @@
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Reviewflow Dashboard</title>
7
+ <link rel="stylesheet" href="styles.css">
8
+ <script src="https://unpkg.com/lucide@latest"></script>
9
+ </head>
10
+ <body>
11
+ <div class="container">
12
+ <header>
13
+ <div class="logo"><i data-lucide="bot"></i></div>
14
+ <h1>Reviewflow</h1>
15
+ <div class="header-actions">
16
+ <button id="check-claude-btn" class="btn btn-primary" onclick="checkClaudeStatus()">
17
+ <i data-lucide="search"></i> Vérifier Claude
18
+ </button>
19
+ <button id="toggle-logs-btn" class="btn btn-secondary" onclick="toggleLogs()">
20
+ <i data-lucide="scroll-text"></i> Logs
21
+ </button>
22
+ <div id="server-status" class="status-indicator connecting">
23
+ <span class="status-dot"></span>
24
+ <span>Connexion...</span>
25
+ </div>
26
+ </div>
27
+ </header>
28
+
29
+ <div class="cards">
30
+ <div class="card">
31
+ <div class="card-label">En cours</div>
32
+ <div id="running-count" class="card-value running">-</div>
33
+ </div>
34
+ <div class="card">
35
+ <div class="card-label">En attente</div>
36
+ <div id="queued-count" class="card-value queued">-</div>
37
+ </div>
38
+ <div class="card">
39
+ <div class="card-label">Terminées</div>
40
+ <div id="completed-count" class="card-value">-</div>
41
+ </div>
42
+ <div class="card">
43
+ <div class="card-label">Claude CLI</div>
44
+ <div id="claude-status" class="card-claude checking">
45
+ <span class="status">Vérification...</span>
46
+ <span class="version"></span>
47
+ </div>
48
+ </div>
49
+ <div class="card" id="git-cli-card">
50
+ <div class="card-label" id="git-cli-label">Git CLI</div>
51
+ <div id="git-cli-status" class="card-claude checking">
52
+ <span class="status">Charger un projet...</span>
53
+ <span class="version"></span>
54
+ </div>
55
+ </div>
56
+ <div class="card">
57
+ <div class="card-label">Modèle</div>
58
+ <div class="card-model">
59
+ <select id="model-select" class="model-select" onchange="changeModel(this.value)">
60
+ <option value="opus">Opus (puissant)</option>
61
+ <option value="sonnet">Sonnet (rapide)</option>
62
+ </select>
63
+ </div>
64
+ </div>
65
+ </div>
66
+
67
+ <div class="project-loader">
68
+ <select id="project-select" class="project-input" style="min-width: 350px;" onchange="onProjectSelect(this.value)">
69
+ <option value="">-- Sélectionner un projet --</option>
70
+ </select>
71
+ <input type="text" id="project-path-input" class="project-input" style="min-width: 250px;"
72
+ placeholder="Ou entrer un nouveau chemin..."
73
+ value="">
74
+ <button class="btn btn-primary" onclick="loadProjectConfig()">
75
+ <i data-lucide="folder-open"></i> Charger
76
+ </button>
77
+ <button class="btn btn-secondary" onclick="removeCurrentProject()" title="Retirer de la liste">
78
+ <i data-lucide="trash-2"></i>
79
+ </button>
80
+ <span id="config-status" class="config-status hidden"></span>
81
+ </div>
82
+ <div id="config-info" class="config-info hidden"></div>
83
+
84
+ <div id="claude-login-section" class="login-instructions hidden">
85
+ <strong><i data-lucide="alert-triangle"></i> Claude n'est pas authentifié</strong>
86
+ <p style="margin-top: 0.5rem;">Exécutez cette commande dans un terminal :</p>
87
+ <p style="margin-top: 0.5rem;"><code>claude login</code></p>
88
+ <p style="margin-top: 0.5rem; font-size: 0.875rem; color: #a1a1aa;">Puis rechargez cette page.</p>
89
+ </div>
90
+
91
+ <div id="git-login-section" class="login-instructions hidden">
92
+ <strong id="git-login-title"><i data-lucide="alert-triangle"></i> CLI non authentifié</strong>
93
+ <div style="margin-top: 0.75rem;" id="git-login-instructions"></div>
94
+ </div>
95
+
96
+ <div id="logs-section" class="section hidden">
97
+ <div class="section-header">
98
+ <i data-lucide="scroll-text"></i> Logs récents
99
+ <span id="error-count" class="badge-count hidden">0 erreurs</span>
100
+ </div>
101
+ <div id="logs-content" class="section-content logs">
102
+ <div class="empty-state">Aucun log</div>
103
+ </div>
104
+ </div>
105
+
106
+ <div id="stats-section" class="section hidden">
107
+ <div class="section-header clickable" onclick="toggleStats()">
108
+ <i data-lucide="bar-chart-3"></i> Statistiques du projet
109
+ <span id="stats-toggle" class="toggle-icon collapsed"><i data-lucide="chevron-down"></i></span>
110
+ </div>
111
+ <div id="project-stats" class="section-content stats-grid hidden">
112
+ <div class="empty-state">Charger un projet pour voir les stats</div>
113
+ </div>
114
+ </div>
115
+
116
+ <div class="section" id="active-reviews-section">
117
+ <div class="section-header">
118
+ <i data-lucide="file-search"></i> Reviews actives
119
+ <span id="active-reviews-count" class="badge-count hidden">0</span>
120
+ </div>
121
+ <div id="active-reviews" class="section-content">
122
+ <div class="empty-state">Aucune review en cours</div>
123
+ </div>
124
+ </div>
125
+
126
+ <div class="section hidden" id="active-followups-section">
127
+ <div class="section-header">
128
+ <i data-lucide="refresh-cw"></i> Followups actifs
129
+ <span id="active-followups-count" class="badge-count hidden">0</span>
130
+ </div>
131
+ <div id="active-followups" class="section-content">
132
+ <div class="empty-state">Aucun followup en cours</div>
133
+ </div>
134
+ </div>
135
+
136
+ <div class="section hidden" id="pending-fix-section">
137
+ <div class="section-header">
138
+ <i data-lucide="wrench"></i> En attente de correctif
139
+ <span id="pending-fix-count" class="badge-count hidden">0</span>
140
+ <button id="sync-threads-btn" class="btn-icon btn-sync" title="Synchroniser les threads GitLab" onclick="syncGitLabThreads()">
141
+ <i data-lucide="refresh-cw"></i>
142
+ </button>
143
+ </div>
144
+ <div id="pending-fix-reviews" class="section-content">
145
+ <div class="empty-state">Aucune MR en attente de correctif</div>
146
+ </div>
147
+ </div>
148
+
149
+ <div class="section hidden" id="pending-approval-section">
150
+ <div class="section-header">
151
+ <i data-lucide="circle-check"></i> En attente d'approbation
152
+ <span id="pending-approval-count" class="badge-count hidden">0</span>
153
+ </div>
154
+ <div id="pending-approval-reviews" class="section-content">
155
+ <div class="empty-state">Aucune MR en attente d'approbation</div>
156
+ </div>
157
+ </div>
158
+
159
+ <div class="section">
160
+ <div class="section-header">
161
+ <i data-lucide="file-check"></i> Reviews terminées
162
+ </div>
163
+ <div id="recent-reviews" class="section-content">
164
+ <div class="empty-state">Chargement...</div>
165
+ </div>
166
+ </div>
167
+
168
+ <div class="refresh-info">
169
+ <span id="connection-mode">WebSocket temps réel</span> • Fallback polling 5s
170
+ </div>
171
+ </div>
172
+
173
+ <div id="cancel-modal" class="modal-overlay hidden" onclick="closeCancelModal(event)">
174
+ <div class="modal-content" onclick="event.stopPropagation()">
175
+ <div class="modal-title" id="cancel-modal-title"></div>
176
+ <div class="modal-message">Cette action est irréversible. La review sera arrêtée immédiatement.</div>
177
+ <div class="modal-actions">
178
+ <button class="btn-modal-back" onclick="closeCancelModal()">Revenir</button>
179
+ <button class="btn-modal-confirm" id="cancel-modal-confirm" onclick="confirmCancelReview()">Confirmer</button>
180
+ </div>
181
+ </div>
182
+ </div>
183
+
184
+ <div id="toast-container" class="toast-container"></div>
185
+
186
+ <script>
187
+ const API_URL = window.location.origin;
188
+ const WS_URL = `ws://${window.location.host}/ws`;
189
+
190
+ let ws = null;
191
+ let wsConnected = false;
192
+ let reconnectAttempts = 0;
193
+ let logsVisible = false;
194
+ const MAX_RECONNECT_ATTEMPTS = 10;
195
+ const RECONNECT_DELAY = 3000;
196
+
197
+ let currentData = { activeReviews: [], recentReviews: [], logs: [], reviewFiles: [], pendingFix: [], pendingApproval: [] };
198
+ let loadedReviews = {}; // Cache for loaded review content
199
+ let statsCollapsed = true; // Track stats section state (collapsed by default)
200
+
201
+ // Agent status icons (will be replaced with Lucide icons after render)
202
+ const agentIconNames = { pending: 'clock', running: 'loader', completed: 'check', failed: 'x' };
203
+ const getAgentIcon = (status) => `<i data-lucide="${agentIconNames[status] || 'help-circle'}"></i>`;
204
+
205
+ function formatTime(dateStr) {
206
+ if (!dateStr) return '-';
207
+ const date = new Date(dateStr);
208
+ const now = new Date();
209
+ const diff = now - date;
210
+ if (diff < 60000) return "À l'instant";
211
+ if (diff < 3600000) return `Il y a ${Math.floor(diff / 60000)} min`;
212
+ if (diff < 86400000) return `Il y a ${Math.floor(diff / 3600000)}h`;
213
+ return date.toLocaleDateString('fr-FR');
214
+ }
215
+
216
+ function formatDuration(startStr, endStr, totalMs) {
217
+ let diff;
218
+ if (totalMs !== undefined && totalMs !== null) {
219
+ diff = Math.floor(totalMs / 1000);
220
+ } else if (startStr) {
221
+ const start = new Date(startStr);
222
+ const end = endStr ? new Date(endStr) : new Date();
223
+ diff = Math.floor((end - start) / 1000);
224
+ } else {
225
+ return '';
226
+ }
227
+ if (diff < 60) return `${diff}s`;
228
+ if (diff < 3600) return `${Math.floor(diff / 60)}m ${diff % 60}s`;
229
+ return `${Math.floor(diff / 3600)}h ${Math.floor((diff % 3600) / 60)}m`;
230
+ }
231
+
232
+ function formatPhase(phase) {
233
+ const labels = {
234
+ 'initializing': 'Initialisation',
235
+ 'agents-running': 'Agents en cours',
236
+ 'synthesizing': 'Synthèse',
237
+ 'publishing': 'Publication',
238
+ 'completed': 'Terminé'
239
+ };
240
+ return labels[phase] || phase;
241
+ }
242
+
243
+ function formatLogTime(timestamp) {
244
+ const date = new Date(timestamp);
245
+ return date.toLocaleTimeString('fr-FR');
246
+ }
247
+
248
+ function renderAgentTimeline(progress) {
249
+ if (!progress?.agents?.length) return '';
250
+ const agentsHtml = progress.agents.map(agent => `
251
+ <div class="agent-box ${agent.status}" title="${agent.displayName}: ${agent.status}">
252
+ <span class="agent-icon">${getAgentIcon(agent.status)}</span>
253
+ <span class="agent-name">${agent.displayName}</span>
254
+ </div>
255
+ `).join('');
256
+ return `<div class="agent-timeline">${agentsHtml}</div>`;
257
+ }
258
+
259
+ function renderProgressBar(progress) {
260
+ if (!progress) return '';
261
+ return `
262
+ <div class="progress-container">
263
+ <div class="progress-bar-wrapper">
264
+ <div class="progress-bar">
265
+ <div class="progress-bar-fill" style="width: ${progress.overallProgress}%"></div>
266
+ </div>
267
+ <span class="progress-percent">${progress.overallProgress}%</span>
268
+ </div>
269
+ <div class="progress-phase">${formatPhase(progress.currentPhase)}</div>
270
+ </div>
271
+ `;
272
+ }
273
+
274
+ function renderReview(review, isActive) {
275
+ const statusClass = review.status;
276
+ const mrNumber = review.mrNumber;
277
+ const project = review.project.split('/').pop();
278
+ const mrPrefix = review.id.startsWith('github') ? '#' : '!';
279
+ const mrLabel = getMrLabel(review.id.startsWith('github') ? 'github' : 'gitlab');
280
+
281
+ const progressHtml = isActive && review.progress ? `
282
+ ${renderAgentTimeline(review.progress)}
283
+ ${renderProgressBar(review.progress)}
284
+ ` : '';
285
+
286
+ // Assignee info with avatar
287
+ const assignerUsername = review.assignedBy?.username || 'unknown';
288
+ const assignerDisplay = review.assignedBy?.displayName || assignerUsername;
289
+ const assignerInitial = assignerDisplay.charAt(0).toUpperCase();
290
+
291
+ // Description accordion (for active reviews)
292
+ const descriptionHtml = isActive && review.description ? `
293
+ <div class="review-description-accordion">
294
+ <div class="review-description-toggle" onclick="toggleReviewDescription('${review.id}')">
295
+ <i data-lucide="chevron-right"></i> Description
296
+ </div>
297
+ <div class="review-description-content" id="review-desc-${review.id.replace(/[^a-zA-Z0-9-]/g, '-')}">
298
+ <div class="review-description-text">${escapeHtml(review.description)}</div>
299
+ </div>
300
+ </div>
301
+ ` : '';
302
+
303
+ // Title: use MR title if available, else fallback to project name
304
+ const displayTitle = review.title || project;
305
+
306
+ return `
307
+ <div class="review-item" data-job-id="${review.id}">
308
+ <div class="review-header">
309
+ <div class="review-status ${statusClass}"></div>
310
+ <div class="review-info">
311
+ <div class="review-title">
312
+ <a href="${review.mrUrl}" target="_blank">${mrPrefix}${mrNumber}</a> - ${displayTitle}
313
+ </div>
314
+ <div class="review-meta">
315
+ <span class="badge ${statusClass}">${review.status}</span>
316
+ ${isActive ? `<i data-lucide="clock"></i> ${formatDuration(review.startedAt)}` : ''}
317
+ </div>
318
+ ${review.error ? `<div class="error-message">${review.error}</div>` : ''}
319
+ </div>
320
+ ${isActive ? `<button class="btn-cancel-review" onclick="event.stopPropagation(); showCancelModal('${review.id}', ${mrNumber}, '${review.jobType || 'review'}')" title="Annuler"><i data-lucide="x"></i> Annuler</button>` : ''}
321
+ <div class="review-assigner">
322
+ <div class="review-assigner-info">
323
+ <span class="review-assigner-name">${assignerDisplay}</span>
324
+ <span class="review-assigner-time">${isActive ? formatTime(review.startedAt) : formatTime(review.completedAt)}</span>
325
+ </div>
326
+ <div class="review-avatar" title="${assignerDisplay}">${assignerInitial}</div>
327
+ </div>
328
+ </div>
329
+ ${descriptionHtml}
330
+ ${progressHtml}
331
+ </div>
332
+ `;
333
+ }
334
+
335
+ function toggleReviewDescription(reviewId) {
336
+ const safeId = reviewId.replace(/[^a-zA-Z0-9-]/g, '-');
337
+ const content = document.getElementById(`review-desc-${safeId}`);
338
+ const toggle = content?.previousElementSibling;
339
+ if (!content || !toggle) return;
340
+
341
+ const isOpen = content.classList.contains('open');
342
+ if (isOpen) {
343
+ content.classList.remove('open');
344
+ toggle.classList.remove('open');
345
+ } else {
346
+ content.classList.add('open');
347
+ toggle.classList.add('open');
348
+ refreshIcons();
349
+ }
350
+ }
351
+
352
+ function escapeHtml(text) {
353
+ if (!text) return '';
354
+ const div = document.createElement('div');
355
+ div.textContent = text;
356
+ return div.innerHTML;
357
+ }
358
+
359
+ function renderLog(log) {
360
+ const dataStr = log.data ? JSON.stringify(log.data, null, 2) : '';
361
+ return `
362
+ <div class="log-entry">
363
+ <span class="log-time">${formatLogTime(log.timestamp)}</span>
364
+ <span class="log-level ${log.level}">${log.level.toUpperCase()}</span>
365
+ <div class="log-message">
366
+ ${log.message}
367
+ ${dataStr ? `<div class="log-data">${dataStr}</div>` : ''}
368
+ </div>
369
+ </div>
370
+ `;
371
+ }
372
+
373
+ function updateUI() {
374
+ // Separate reviews and followups
375
+ const reviews = currentData.activeReviews.filter(r => r.jobType !== 'followup');
376
+ const followups = currentData.activeReviews.filter(r => r.jobType === 'followup');
377
+
378
+ const running = currentData.activeReviews.filter(r => r.status === 'running').length;
379
+ const queued = currentData.activeReviews.filter(r => r.status === 'queued').length;
380
+ document.getElementById('running-count').textContent = running;
381
+ document.getElementById('queued-count').textContent = queued;
382
+ document.getElementById('completed-count').textContent = currentData.reviewFiles.length;
383
+
384
+ // Update Reviews section
385
+ const activeReviewsSection = document.getElementById('active-reviews-section');
386
+ const activeReviewsEl = document.getElementById('active-reviews');
387
+ const activeReviewsCount = document.getElementById('active-reviews-count');
388
+
389
+ if (reviews.length === 0) {
390
+ activeReviewsSection.classList.add('hidden');
391
+ } else {
392
+ activeReviewsSection.classList.remove('hidden');
393
+ activeReviewsEl.innerHTML = reviews.map(r => renderReview(r, true)).join('');
394
+ activeReviewsCount.textContent = reviews.length;
395
+ activeReviewsCount.classList.remove('hidden');
396
+ }
397
+
398
+ // Update Followups section
399
+ const activeFollowupsSection = document.getElementById('active-followups-section');
400
+ const activeFollowupsEl = document.getElementById('active-followups');
401
+ const activeFollowupsCount = document.getElementById('active-followups-count');
402
+
403
+ if (followups.length === 0) {
404
+ activeFollowupsSection.classList.add('hidden');
405
+ } else {
406
+ activeFollowupsSection.classList.remove('hidden');
407
+ activeFollowupsEl.innerHTML = followups.map(r => renderReview(r, true)).join('');
408
+ activeFollowupsCount.textContent = followups.length;
409
+ activeFollowupsCount.classList.remove('hidden');
410
+ }
411
+
412
+ refreshIcons();
413
+ // Note: recent-reviews is managed by updateReviewFilesUI() - don't overwrite here
414
+ }
415
+
416
+ function updateLogs() {
417
+ const logsEl = document.getElementById('logs-content');
418
+ const errorCount = currentData.logs.filter(l => l.level === 'error' || l.level === 'warn').length;
419
+ const errorBadge = document.getElementById('error-count');
420
+
421
+ if (errorCount > 0) {
422
+ errorBadge.textContent = `${errorCount} erreurs`;
423
+ errorBadge.classList.remove('hidden');
424
+ } else {
425
+ errorBadge.classList.add('hidden');
426
+ }
427
+
428
+ if (currentData.logs.length === 0) {
429
+ logsEl.innerHTML = '<div class="empty-state">Aucun log</div>';
430
+ } else {
431
+ logsEl.innerHTML = currentData.logs.slice().reverse().map(renderLog).join('');
432
+ }
433
+ }
434
+
435
+ function updateConnectionStatus(status, text) {
436
+ const statusEl = document.getElementById('server-status');
437
+ statusEl.className = `status-indicator ${status}`;
438
+ statusEl.innerHTML = `<span class="status-dot"></span><span>${text}</span>`;
439
+
440
+ const modeEl = document.getElementById('connection-mode');
441
+ modeEl.textContent = status === 'online' && wsConnected
442
+ ? 'WebSocket temps réel'
443
+ : status === 'online' ? 'Mode polling' : 'Déconnecté';
444
+ }
445
+
446
+ // Simple markdown to HTML converter
447
+ function markdownToHtml(md) {
448
+ let html = md
449
+ // Escape HTML
450
+ .replace(/&/g, '&amp;')
451
+ .replace(/</g, '&lt;')
452
+ .replace(/>/g, '&gt;')
453
+ // Code blocks
454
+ .replace(/```(\w*)\n([\s\S]*?)```/g, '<pre><code>$2</code></pre>')
455
+ // Inline code
456
+ .replace(/`([^`]+)`/g, '<code>$1</code>')
457
+ // Headers
458
+ .replace(/^### (.+)$/gm, '<h3>$1</h3>')
459
+ .replace(/^## (.+)$/gm, '<h2>$1</h2>')
460
+ .replace(/^# (.+)$/gm, '<h1>$1</h1>')
461
+ // Bold
462
+ .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
463
+ // Italic
464
+ .replace(/\*([^*]+)\*/g, '<em>$1</em>')
465
+ // Links
466
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>')
467
+ // Blockquotes
468
+ .replace(/^> (.+)$/gm, '<blockquote>$1</blockquote>')
469
+ // Unordered lists
470
+ .replace(/^- (.+)$/gm, '<li>$1</li>')
471
+ // Ordered lists
472
+ .replace(/^\d+\. (.+)$/gm, '<li>$1</li>')
473
+ // Horizontal rules
474
+ .replace(/^---$/gm, '<hr>')
475
+ // Tables (simple)
476
+ .replace(/^\|(.+)\|$/gm, (match, content) => {
477
+ const cells = content.split('|').map(c => c.trim());
478
+ if (cells.every(c => c.match(/^-+$/))) return '';
479
+ const cellTag = match.includes('---') ? 'th' : 'td';
480
+ return '<tr>' + cells.map(c => `<${cellTag}>${c}</${cellTag}>`).join('') + '</tr>';
481
+ })
482
+ // Wrap consecutive table rows
483
+ .replace(/(<tr>[\s\S]*?<\/tr>)+/g, '<table>$&</table>')
484
+ // Wrap consecutive list items
485
+ .replace(/(<li>[\s\S]*?<\/li>)+/g, '<ul>$&</ul>')
486
+ // Paragraphs
487
+ .replace(/\n\n/g, '</p><p>')
488
+ .replace(/\n/g, '<br>');
489
+
490
+ return '<p>' + html + '</p>';
491
+ }
492
+
493
+ function renderReviewFile(review) {
494
+ const typeIcon = review.type === 'review' ? 'file-text' : review.type === 'followup' ? 'refresh-cw' : 'file';
495
+ const typeLabel = review.type === 'review' ? 'Review' : review.type === 'followup' ? 'Followup' : review.type;
496
+ const sizeKb = (review.size / 1024).toFixed(1);
497
+ const mrLabel = getMrLabel();
498
+
499
+ return `
500
+ <div class="review-accordion" data-filename="${review.filename}">
501
+ <div class="review-accordion-header">
502
+ <div class="review-accordion-toggle" onclick="toggleReviewAccordion('${review.filename}')"><i data-lucide="chevron-right"></i></div>
503
+ <div class="review-status completed" onclick="toggleReviewAccordion('${review.filename}')"></div>
504
+ <div class="review-info" onclick="toggleReviewAccordion('${review.filename}')" style="cursor: pointer;">
505
+ <div class="review-title">${mrLabel} ${review.mrNumber}${review.title ? ` - ${review.title}` : ''}</div>
506
+ <div class="review-meta">
507
+ <span class="badge completed"><i data-lucide="${typeIcon}"></i> ${typeLabel}</span>
508
+ <span style="margin-left: 0.5rem; color: #71717a;">${sizeKb} KB</span>
509
+ </div>
510
+ </div>
511
+ <div class="review-time" onclick="toggleReviewAccordion('${review.filename}')" style="cursor: pointer;">${review.date}</div>
512
+ <button class="btn-delete" onclick="deleteReviewFile('${review.filename}')" title="Supprimer"><i data-lucide="trash-2"></i></button>
513
+ </div>
514
+ <div class="review-accordion-content">
515
+ <div class="markdown-content" id="review-content-${review.filename.replace(/\./g, '-')}">
516
+ <div class="empty-state">Chargement...</div>
517
+ </div>
518
+ </div>
519
+ </div>
520
+ `;
521
+ }
522
+
523
+ async function toggleReviewAccordion(filename) {
524
+ const accordion = document.querySelector(`.review-accordion[data-filename="${filename}"]`);
525
+ const isOpen = accordion.classList.contains('open');
526
+
527
+ // Close all other accordions
528
+ document.querySelectorAll('.review-accordion.open').forEach(el => {
529
+ if (el !== accordion) el.classList.remove('open');
530
+ });
531
+
532
+ if (isOpen) {
533
+ accordion.classList.remove('open');
534
+ return;
535
+ }
536
+
537
+ accordion.classList.add('open');
538
+ const contentId = `review-content-${filename.replace(/\./g, '-')}`;
539
+ const contentEl = document.getElementById(contentId);
540
+
541
+ // Load content if not cached
542
+ if (!loadedReviews[filename]) {
543
+ try {
544
+ const response = await fetch(`${API_URL}/api/reviews/${filename}`);
545
+ const data = await response.json();
546
+ loadedReviews[filename] = data.content;
547
+ } catch (error) {
548
+ contentEl.innerHTML = '<div class="empty-state">Erreur de chargement</div>';
549
+ return;
550
+ }
551
+ }
552
+
553
+ contentEl.innerHTML = markdownToHtml(loadedReviews[filename]);
554
+ }
555
+
556
+ async function fetchReviewFiles() {
557
+ try {
558
+ // Fetch reviews for current project if loaded, otherwise all
559
+ const url = currentProjectPath
560
+ ? `${API_URL}/api/reviews?path=${encodeURIComponent(currentProjectPath)}`
561
+ : `${API_URL}/api/reviews`;
562
+ const response = await fetch(url);
563
+ const data = await response.json();
564
+ currentData.reviewFiles = data.reviews || [];
565
+ updateReviewFilesUI();
566
+ } catch (error) {
567
+ console.error('Error fetching review files:', error);
568
+ }
569
+ }
570
+
571
+ async function fetchProjectStats() {
572
+ const statsEl = document.getElementById('project-stats');
573
+
574
+ if (!currentProjectPath) {
575
+ statsEl.innerHTML = '<div class="empty-state">Charger un projet pour voir les stats</div>';
576
+ return;
577
+ }
578
+
579
+ try {
580
+ const response = await fetch(`${API_URL}/api/stats?path=${encodeURIComponent(currentProjectPath)}`);
581
+ const data = await response.json();
582
+
583
+ if (data.summary) {
584
+ const s = data.summary;
585
+ const trendIcon = (t) => t === 'up' ? '<i data-lucide="trending-up"></i>' : t === 'down' ? '<i data-lucide="trending-down"></i>' : '<i data-lucide="minus"></i>';
586
+
587
+ statsEl.innerHTML = `
588
+ <div class="stat-card">
589
+ <div class="stat-value">${s.totalReviews}</div>
590
+ <div class="stat-label"><i data-lucide="file-search"></i> Reviews</div>
591
+ </div>
592
+ <div class="stat-card">
593
+ <div class="stat-value">${s.averageScore}/10 ${trendIcon(s.trend.score)}</div>
594
+ <div class="stat-label"><i data-lucide="star"></i> Score moyen</div>
595
+ </div>
596
+ <div class="stat-card">
597
+ <div class="stat-value">${s.totalTime}</div>
598
+ <div class="stat-label"><i data-lucide="timer"></i> Temps total</div>
599
+ </div>
600
+ <div class="stat-card">
601
+ <div class="stat-value">${s.averageTime}</div>
602
+ <div class="stat-label"><i data-lucide="clock"></i> Durée moyenne</div>
603
+ </div>
604
+ <div class="stat-card warning">
605
+ <div class="stat-value">${s.totalBlocking} ${trendIcon(s.trend.blocking)}</div>
606
+ <div class="stat-label"><i data-lucide="octagon-alert"></i> Bloquants</div>
607
+ </div>
608
+ <div class="stat-card">
609
+ <div class="stat-value">${s.totalWarnings}</div>
610
+ <div class="stat-label"><i data-lucide="alert-triangle"></i> Importants</div>
611
+ </div>
612
+ `;
613
+ refreshIcons();
614
+ } else {
615
+ statsEl.innerHTML = '<div class="empty-state">Aucune statistique disponible</div>';
616
+ }
617
+ } catch (error) {
618
+ console.error('Error fetching stats:', error);
619
+ statsEl.innerHTML = '<div class="empty-state">Erreur de chargement des stats</div>';
620
+ }
621
+ }
622
+
623
+ function updateReviewFilesUI() {
624
+ const recentEl = document.getElementById('recent-reviews');
625
+
626
+ if (currentData.reviewFiles.length === 0) {
627
+ recentEl.innerHTML = '<div class="empty-state">Aucun fichier de review</div>';
628
+ return;
629
+ }
630
+
631
+ recentEl.innerHTML = currentData.reviewFiles.map(renderReviewFile).join('');
632
+ refreshIcons();
633
+ }
634
+
635
+ async function deleteReviewFile(filename) {
636
+ if (!confirm(`Supprimer ${filename} ?`)) return;
637
+
638
+ try {
639
+ const response = await fetch(`${API_URL}/api/reviews/${filename}`, {
640
+ method: 'DELETE'
641
+ });
642
+ const data = await response.json();
643
+
644
+ if (data.success) {
645
+ // Remove from cache
646
+ delete loadedReviews[filename];
647
+ // Remove from list and update UI
648
+ currentData.reviewFiles = currentData.reviewFiles.filter(r => r.filename !== filename);
649
+ updateReviewFilesUI();
650
+ updateUI(); // Update count
651
+ } else {
652
+ alert('Erreur: ' + data.error);
653
+ }
654
+ } catch (error) {
655
+ console.error('Error deleting review:', error);
656
+ alert('Erreur lors de la suppression');
657
+ }
658
+ }
659
+
660
+ async function checkClaudeStatus() {
661
+ const claudeEl = document.getElementById('claude-status');
662
+ const loginSection = document.getElementById('claude-login-section');
663
+
664
+ claudeEl.className = 'card-claude checking';
665
+ claudeEl.innerHTML = '<span class="status">Vérification...</span>';
666
+
667
+ try {
668
+ const response = await fetch(`${API_URL}/api/claude/status`);
669
+ const data = await response.json();
670
+
671
+ if (data.available) {
672
+ claudeEl.className = 'card-claude available';
673
+ claudeEl.innerHTML = `
674
+ <span class="status"><i data-lucide="check-circle"></i> Opérationnel</span>
675
+ <span class="version">${data.version}</span>
676
+ `;
677
+ loginSection.classList.add('hidden');
678
+ refreshIcons();
679
+ } else {
680
+ claudeEl.className = 'card-claude unavailable';
681
+ claudeEl.innerHTML = `
682
+ <span class="status"><i data-lucide="x-circle"></i> ${data.message}</span>
683
+ `;
684
+ refreshIcons();
685
+ if (data.message.includes('authentifié') || data.message.includes('login')) {
686
+ loginSection.classList.remove('hidden');
687
+ }
688
+ }
689
+ } catch (error) {
690
+ claudeEl.className = 'card-claude unavailable';
691
+ claudeEl.innerHTML = '<span class="status"><i data-lucide="x-circle"></i> Erreur de vérification</span>';
692
+ refreshIcons();
693
+ }
694
+ }
695
+
696
+ // Active platform from config (gitlab or github)
697
+ let activePlatform = null;
698
+
699
+ function updateGitCliUI() {
700
+ const labelEl = document.getElementById('git-cli-label');
701
+ const statusEl = document.getElementById('git-cli-status');
702
+ const loginSection = document.getElementById('git-login-section');
703
+
704
+ if (!activePlatform) {
705
+ labelEl.textContent = 'Git CLI';
706
+ statusEl.className = 'card-claude checking';
707
+ statusEl.innerHTML = '<span class="status">Charger un projet...</span>';
708
+ loginSection.classList.add('hidden');
709
+ return;
710
+ }
711
+
712
+ const isGitlab = activePlatform === 'gitlab';
713
+ labelEl.textContent = isGitlab ? 'GitLab CLI' : 'GitHub CLI';
714
+
715
+ // Update login section with CLI + Webhook instructions
716
+ const titleEl = document.getElementById('git-login-title');
717
+ const instructionsEl = document.getElementById('git-login-instructions');
718
+
719
+ if (isGitlab) {
720
+ titleEl.innerHTML = '<i data-lucide="alert-triangle"></i> GitLab CLI non authentifié';
721
+ instructionsEl.innerHTML = `
722
+ <p><strong>1. Installer et authentifier glab :</strong></p>
723
+ <p style="margin: 0.5rem 0;"><code>sudo apt install glab</code></p>
724
+ <p style="margin: 0.5rem 0;"><code>glab auth login</code></p>
725
+ <p style="margin-top: 1rem;"><strong>2. Configurer le webhook GitLab :</strong></p>
726
+ <p style="margin: 0.5rem 0; font-size: 0.8rem;">Settings → Webhooks → Add webhook</p>
727
+ <p style="margin: 0.25rem 0; font-size: 0.8rem;">URL: <code>http://&lt;your-server&gt;:3847/webhooks/gitlab</code></p>
728
+ <p style="margin: 0.25rem 0; font-size: 0.8rem;">Trigger: Merge request events</p>
729
+ <p style="margin-top: 0.75rem; font-size: 0.75rem; color: #a1a1aa;">Puis rechargez cette page.</p>
730
+ `;
731
+ } else {
732
+ titleEl.innerHTML = '<i data-lucide="alert-triangle"></i> GitHub CLI non authentifié';
733
+ instructionsEl.innerHTML = `
734
+ <p><strong>1. Installer et authentifier gh :</strong></p>
735
+ <p style="margin: 0.5rem 0;"><code>sudo apt install gh</code></p>
736
+ <p style="margin: 0.5rem 0;"><code>gh auth login</code></p>
737
+ <p style="margin-top: 1rem;"><strong>2. Configurer le webhook GitHub :</strong></p>
738
+ <p style="margin: 0.5rem 0; font-size: 0.8rem;">Settings → Webhooks → Add webhook</p>
739
+ <p style="margin: 0.25rem 0; font-size: 0.8rem;">Payload URL: <code>http://&lt;your-server&gt;:3847/webhooks/github</code></p>
740
+ <p style="margin: 0.25rem 0; font-size: 0.8rem;">Content type: application/json</p>
741
+ <p style="margin: 0.25rem 0; font-size: 0.8rem;">Events: Pull requests</p>
742
+ <p style="margin-top: 0.75rem; font-size: 0.75rem; color: #a1a1aa;">Puis rechargez cette page.</p>
743
+ `;
744
+ }
745
+
746
+ refreshIcons();
747
+ checkGitCliStatus();
748
+ }
749
+
750
+ async function checkGitCliStatus() {
751
+ if (!activePlatform) return;
752
+
753
+ const statusEl = document.getElementById('git-cli-status');
754
+ const loginSection = document.getElementById('git-login-section');
755
+ const isGitlab = activePlatform === 'gitlab';
756
+ const endpoint = isGitlab ? '/api/gitlab/status' : '/api/github/status';
757
+
758
+ statusEl.className = 'card-claude checking';
759
+ statusEl.innerHTML = '<span class="status">Vérification...</span>';
760
+
761
+ try {
762
+ const response = await fetch(`${API_URL}${endpoint}`);
763
+ const data = await response.json();
764
+
765
+ if (data.available && data.authenticated) {
766
+ statusEl.className = 'card-claude available';
767
+ statusEl.innerHTML = `
768
+ <span class="status"><i data-lucide="check-circle"></i> Opérationnel</span>
769
+ <span class="version">@${data.username}</span>
770
+ `;
771
+ loginSection.classList.add('hidden');
772
+ refreshIcons();
773
+ } else if (data.available && !data.authenticated) {
774
+ statusEl.className = 'card-claude unavailable';
775
+ statusEl.innerHTML = `<span class="status"><i data-lucide="x-circle"></i> ${data.message}</span>`;
776
+ loginSection.classList.remove('hidden');
777
+ refreshIcons();
778
+ } else {
779
+ statusEl.className = 'card-claude unavailable';
780
+ statusEl.innerHTML = `<span class="status"><i data-lucide="x-circle"></i> ${data.message}</span>`;
781
+ loginSection.classList.remove('hidden');
782
+ refreshIcons();
783
+ }
784
+ } catch (error) {
785
+ statusEl.className = 'card-claude unavailable';
786
+ statusEl.innerHTML = '<span class="status"><i data-lucide="x-circle"></i> Erreur de vérification</span>';
787
+ refreshIcons();
788
+ }
789
+ }
790
+
791
+ function toggleLogs() {
792
+ logsVisible = !logsVisible;
793
+ const logsSection = document.getElementById('logs-section');
794
+ const btn = document.getElementById('toggle-logs-btn');
795
+
796
+ if (logsVisible) {
797
+ logsSection.classList.remove('hidden');
798
+ btn.innerHTML = '<i data-lucide="scroll-text"></i> Masquer Logs';
799
+ fetchLogs();
800
+ } else {
801
+ logsSection.classList.add('hidden');
802
+ btn.innerHTML = '<i data-lucide="scroll-text"></i> Logs';
803
+ }
804
+ refreshIcons();
805
+ }
806
+
807
+ function toggleStats() {
808
+ statsCollapsed = !statsCollapsed;
809
+ const content = document.getElementById('project-stats');
810
+ const toggle = document.getElementById('stats-toggle');
811
+
812
+ if (statsCollapsed) {
813
+ content.classList.add('hidden');
814
+ toggle.classList.add('collapsed');
815
+ } else {
816
+ content.classList.remove('hidden');
817
+ toggle.classList.remove('collapsed');
818
+ }
819
+ }
820
+
821
+ function renderMrItem(mr, type) {
822
+ const mrPrefix = mr.platform === 'github' ? '#' : '!';
823
+ const threadInfo = type === 'pending-fix'
824
+ ? `<span class="mr-threads has-open"><i data-lucide="message-circle"></i> ${mr.openThreads} ouvert${mr.openThreads > 1 ? 's' : ''}</span>`
825
+ : `<span class="mr-threads all-resolved"><i data-lucide="check-circle"></i> Résolus</span>`;
826
+
827
+ const openBtn = `<a href="${mr.url}" target="_blank" class="btn-action open"><i data-lucide="external-link"></i> Ouvrir</a>`;
828
+ const autoFollowupChecked = mr.autoFollowup !== false ? 'checked' : '';
829
+ const actions = type === 'pending-fix'
830
+ ? `<label class="auto-followup-toggle" onclick="event.stopPropagation()" title="Active/désactive le followup automatique après un push">
831
+ <input type="checkbox" ${autoFollowupChecked} onchange="toggleAutoFollowup('${mr.id}', this.checked)">
832
+ Auto follow-up
833
+ </label>
834
+ <button class="btn-action" onclick="triggerFollowup('${mr.id}')"><i data-lucide="refresh-cw"></i> Followup</button>${openBtn}`
835
+ : openBtn;
836
+
837
+ // Stats badges
838
+ const statsBadges = [];
839
+ if (mr.totalBlocking > 0) statsBadges.push(`<span class="stat-badge blocking"><i data-lucide="octagon-alert"></i> ${mr.totalBlocking}</span>`);
840
+ if (mr.totalWarnings > 0) statsBadges.push(`<span class="stat-badge warning"><i data-lucide="alert-triangle"></i> ${mr.totalWarnings}</span>`);
841
+ if (mr.totalFollowups > 0) statsBadges.push(`<span class="stat-badge followup"><i data-lucide="refresh-cw"></i> ${mr.totalFollowups}</span>`);
842
+ if (mr.averageScore !== null) statsBadges.push(`<span class="stat-badge score"><i data-lucide="star"></i> ${mr.averageScore.toFixed(1)}/10</span>`);
843
+
844
+ const durationFormatted = mr.totalDurationMs ? formatDuration(null, null, mr.totalDurationMs) : '';
845
+
846
+ // Assigner info with avatar
847
+ const assignerUsername = mr.assignment?.username || 'unknown';
848
+ const assignerDisplay = mr.assignment?.displayName || assignerUsername;
849
+ const assignerInitial = assignerDisplay.charAt(0).toUpperCase();
850
+ const assignedAt = mr.assignment?.assignedAt ? formatTime(mr.assignment.assignedAt) : '';
851
+
852
+ // Sanitize ID for accordion toggle
853
+ const accordionId = mr.id.replace(/[^a-zA-Z0-9-]/g, '-');
854
+
855
+ return `
856
+ <div class="mr-item-accordion" data-mr-id="${mr.id}">
857
+ <div class="mr-item-header" onclick="toggleMrAccordion('${accordionId}')">
858
+ <div class="review-status ${type === 'pending-fix' ? 'running' : 'completed'}"></div>
859
+ <div class="mr-info">
860
+ <div class="mr-title">
861
+ <a href="${mr.url}" target="_blank" onclick="event.stopPropagation()">${mrPrefix}${mr.mrNumber}</a> - ${mr.title}
862
+ </div>
863
+ <div class="mr-meta">
864
+ ${threadInfo}
865
+ ${statsBadges.join('')}
866
+ <span><i data-lucide="clock"></i> ${durationFormatted || '-'}</span>
867
+ </div>
868
+ </div>
869
+ <div class="mr-assigner">
870
+ <div class="mr-assigner-info">
871
+ <span class="mr-assigner-name">${assignerDisplay}</span>
872
+ <span class="mr-assigner-time">${assignedAt}</span>
873
+ </div>
874
+ <div class="mr-avatar" title="${assignerDisplay}">${assignerInitial}</div>
875
+ </div>
876
+ <div class="mr-toggle"><i data-lucide="chevron-down"></i></div>
877
+ </div>
878
+ <div class="mr-item-content" id="mr-content-${accordionId}">
879
+ <div class="mr-details">
880
+ <div class="mr-detail-row">
881
+ <span class="mr-detail-label"><i data-lucide="git-branch"></i> Source:</span>
882
+ <span class="mr-detail-value">${mr.sourceBranch}</span>
883
+ </div>
884
+ <div class="mr-detail-row">
885
+ <span class="mr-detail-label"><i data-lucide="git-merge"></i> Target:</span>
886
+ <span class="mr-detail-value">${mr.targetBranch}</span>
887
+ </div>
888
+ <div class="mr-detail-row">
889
+ <span class="mr-detail-label"><i data-lucide="calendar"></i> Créée:</span>
890
+ <span class="mr-detail-value">${formatTime(mr.createdAt)}</span>
891
+ </div>
892
+ ${mr.lastReviewAt ? `
893
+ <div class="mr-detail-row">
894
+ <span class="mr-detail-label"><i data-lucide="file-search"></i> Dernière review:</span>
895
+ <span class="mr-detail-value">${formatTime(mr.lastReviewAt)}</span>
896
+ </div>
897
+ ` : ''}
898
+ ${mr.reviews?.length ? `
899
+ <div class="mr-reviews-history">
900
+ <div class="mr-detail-label"><i data-lucide="history"></i> Historique (${mr.reviews.length}):</div>
901
+ <div class="mr-reviews-list">
902
+ ${mr.reviews.slice(-5).reverse().map(r => `
903
+ <div class="mr-review-event ${r.type}">
904
+ <span class="review-event-type">${r.type === 'review' ? 'Review' : 'Followup'}</span>
905
+ <span class="review-event-time">${formatTime(r.timestamp)}</span>
906
+ ${r.score !== null ? `<span class="review-event-score">${r.score}/10</span>` : ''}
907
+ ${r.blocking > 0 ? `<span class="review-event-blocking">${r.blocking} bloquant${r.blocking > 1 ? 's' : ''}</span>` : ''}
908
+ </div>
909
+ `).join('')}
910
+ </div>
911
+ </div>
912
+ ` : ''}
913
+ </div>
914
+ <div class="mr-item-actions" onclick="event.stopPropagation()">
915
+ ${actions}
916
+ </div>
917
+ </div>
918
+ </div>
919
+ `;
920
+ }
921
+
922
+ function toggleMrAccordion(accordionId) {
923
+ const content = document.getElementById(`mr-content-${accordionId}`);
924
+ const accordion = content?.closest('.mr-item-accordion');
925
+ if (!content || !accordion) return;
926
+
927
+ const isOpen = accordion.classList.contains('open');
928
+
929
+ // Close all other MR accordions
930
+ document.querySelectorAll('.mr-item-accordion.open').forEach(el => {
931
+ if (el !== accordion) {
932
+ el.classList.remove('open');
933
+ }
934
+ });
935
+
936
+ if (isOpen) {
937
+ accordion.classList.remove('open');
938
+ } else {
939
+ accordion.classList.add('open');
940
+ refreshIcons();
941
+ }
942
+ }
943
+
944
+ function updateMrTrackingUI() {
945
+ const pendingFixSection = document.getElementById('pending-fix-section');
946
+ const pendingFixEl = document.getElementById('pending-fix-reviews');
947
+ const pendingApprovalSection = document.getElementById('pending-approval-section');
948
+ const pendingApprovalEl = document.getElementById('pending-approval-reviews');
949
+ const pendingFixCount = document.getElementById('pending-fix-count');
950
+ const pendingApprovalCount = document.getElementById('pending-approval-count');
951
+ const mrLabel = getMrLabel();
952
+
953
+ // Pending fix - show/hide section dynamically
954
+ if (currentData.pendingFix.length === 0) {
955
+ pendingFixSection.classList.add('hidden');
956
+ pendingFixCount.classList.add('hidden');
957
+ } else {
958
+ pendingFixSection.classList.remove('hidden');
959
+ pendingFixEl.innerHTML = currentData.pendingFix.map(mr => renderMrItem(mr, 'pending-fix')).join('');
960
+ pendingFixCount.textContent = currentData.pendingFix.length;
961
+ pendingFixCount.classList.remove('hidden');
962
+ }
963
+
964
+ // Pending approval - show/hide section dynamically
965
+ if (currentData.pendingApproval.length === 0) {
966
+ pendingApprovalSection.classList.add('hidden');
967
+ pendingApprovalCount.classList.add('hidden');
968
+ } else {
969
+ pendingApprovalSection.classList.remove('hidden');
970
+ pendingApprovalEl.innerHTML = currentData.pendingApproval.map(mr => renderMrItem(mr, 'pending-approval')).join('');
971
+ pendingApprovalCount.textContent = currentData.pendingApproval.length;
972
+ pendingApprovalCount.classList.remove('hidden');
973
+ }
974
+
975
+ refreshIcons();
976
+ }
977
+
978
+ async function fetchMrTracking() {
979
+ if (!currentProjectPath) {
980
+ currentData.pendingFix = [];
981
+ currentData.pendingApproval = [];
982
+ // Hide sections when no project loaded
983
+ document.getElementById('pending-fix-section').classList.add('hidden');
984
+ document.getElementById('pending-approval-section').classList.add('hidden');
985
+ return;
986
+ }
987
+
988
+ try {
989
+ const response = await fetch(`${API_URL}/api/mr-tracking?path=${encodeURIComponent(currentProjectPath)}`);
990
+ const data = await response.json();
991
+ if (data.success) {
992
+ currentData.pendingFix = data.pendingFix || [];
993
+ currentData.pendingApproval = data.pendingApproval || [];
994
+ }
995
+ updateMrTrackingUI();
996
+ } catch (error) {
997
+ console.error('Error fetching MR tracking:', error);
998
+ }
999
+ }
1000
+
1001
+ async function triggerFollowup(mrId) {
1002
+ try {
1003
+ const response = await fetch(`${API_URL}/api/mr-tracking/followup`, {
1004
+ method: 'POST',
1005
+ headers: { 'Content-Type': 'application/json' },
1006
+ body: JSON.stringify({ mrId, projectPath: currentProjectPath })
1007
+ });
1008
+ const data = await response.json();
1009
+ if (data.success) {
1010
+ console.log('Followup triggered for MR:', mrId);
1011
+ } else {
1012
+ alert('Erreur: ' + data.error);
1013
+ }
1014
+ } catch (error) {
1015
+ console.error('Error triggering followup:', error);
1016
+ alert('Erreur lors du déclenchement du followup');
1017
+ }
1018
+ }
1019
+
1020
+ async function toggleAutoFollowup(mrId, enabled) {
1021
+ try {
1022
+ const response = await fetch(`${API_URL}/api/mr-tracking/auto-followup`, {
1023
+ method: 'POST',
1024
+ headers: { 'Content-Type': 'application/json' },
1025
+ body: JSON.stringify({ mrId, projectPath: currentProjectPath, enabled })
1026
+ });
1027
+ const data = await response.json();
1028
+ if (!data.success) {
1029
+ alert('Erreur: ' + data.error);
1030
+ }
1031
+ } catch (error) {
1032
+ console.error('Error toggling auto-followup:', error);
1033
+ alert('Erreur lors du changement de auto follow-up');
1034
+ }
1035
+ }
1036
+
1037
+ async function approveMr(mrId) {
1038
+ if (!confirm(`Marquer cette ${getMrLabel()} comme approuvée ?`)) return;
1039
+
1040
+ try {
1041
+ const response = await fetch(`${API_URL}/api/mr-tracking/approve`, {
1042
+ method: 'POST',
1043
+ headers: { 'Content-Type': 'application/json' },
1044
+ body: JSON.stringify({ mrId, projectPath: currentProjectPath })
1045
+ });
1046
+ const data = await response.json();
1047
+ if (data.success) {
1048
+ // Remove from pending approval list
1049
+ currentData.pendingApproval = currentData.pendingApproval.filter(mr => mr.id !== mrId);
1050
+ updateMrTrackingUI();
1051
+ } else {
1052
+ alert('Erreur: ' + data.error);
1053
+ }
1054
+ } catch (error) {
1055
+ console.error('Error approving MR:', error);
1056
+ alert('Erreur lors de l\'approbation');
1057
+ }
1058
+ }
1059
+
1060
+ async function syncGitLabThreads() {
1061
+ if (!currentProjectPath) {
1062
+ alert('Charger un projet d\'abord');
1063
+ return;
1064
+ }
1065
+
1066
+ const btn = document.getElementById('sync-threads-btn');
1067
+ const icon = btn.querySelector('i');
1068
+
1069
+ // Add spinning animation
1070
+ btn.disabled = true;
1071
+ icon.classList.add('spinning');
1072
+
1073
+ try {
1074
+ const response = await fetch(`${API_URL}/api/mr-tracking/sync`, {
1075
+ method: 'POST',
1076
+ headers: { 'Content-Type': 'application/json' },
1077
+ body: JSON.stringify({ projectPath: currentProjectPath })
1078
+ });
1079
+ const data = await response.json();
1080
+ if (data.success) {
1081
+ // Refresh MR tracking data
1082
+ await fetchMrTracking();
1083
+ console.log('Threads synchronized successfully');
1084
+ } else {
1085
+ alert('Erreur: ' + data.error);
1086
+ }
1087
+ } catch (error) {
1088
+ console.error('Error syncing threads:', error);
1089
+ alert('Erreur lors de la synchronisation des threads');
1090
+ } finally {
1091
+ btn.disabled = false;
1092
+ icon.classList.remove('spinning');
1093
+ }
1094
+ }
1095
+
1096
+ async function fetchLogs() {
1097
+ try {
1098
+ const response = await fetch(`${API_URL}/api/logs`);
1099
+ const data = await response.json();
1100
+ currentData.logs = data.logs || [];
1101
+ updateLogs();
1102
+ } catch (error) {
1103
+ console.error('Error fetching logs:', error);
1104
+ }
1105
+ }
1106
+
1107
+ function handleProgressUpdate(message) {
1108
+ const { jobId, progress } = message;
1109
+ const review = currentData.activeReviews.find(r => r.id === jobId);
1110
+ if (review) {
1111
+ review.progress = progress;
1112
+ updateUI();
1113
+ }
1114
+ }
1115
+
1116
+ function handleLogMessage(log) {
1117
+ currentData.logs.push(log);
1118
+ if (currentData.logs.length > 200) currentData.logs.shift();
1119
+ if (logsVisible) updateLogs();
1120
+ }
1121
+
1122
+ function connectWebSocket() {
1123
+ if (ws?.readyState === WebSocket.OPEN) return;
1124
+
1125
+ updateConnectionStatus('connecting', 'Connexion...');
1126
+
1127
+ try {
1128
+ ws = new WebSocket(WS_URL);
1129
+
1130
+ ws.onopen = () => {
1131
+ wsConnected = true;
1132
+ reconnectAttempts = 0;
1133
+ updateConnectionStatus('online', 'En ligne');
1134
+ };
1135
+
1136
+ ws.onmessage = (event) => {
1137
+ try {
1138
+ const message = JSON.parse(event.data);
1139
+ switch (message.type) {
1140
+ case 'init':
1141
+ case 'state':
1142
+ console.log(`[WS] ${message.type}: ${message.activeReviews?.length || 0} active reviews`, message.activeReviews);
1143
+ currentData.activeReviews = message.activeReviews || [];
1144
+ currentData.recentReviews = message.recentReviews || [];
1145
+ updateUI();
1146
+ // Also refresh MR tracking when state changes
1147
+ if (message.type === 'state') {
1148
+ fetchMrTracking();
1149
+ }
1150
+ break;
1151
+ case 'progress':
1152
+ handleProgressUpdate(message);
1153
+ break;
1154
+ case 'log':
1155
+ handleLogMessage(message.log);
1156
+ break;
1157
+ case 'pong':
1158
+ break;
1159
+ }
1160
+ } catch (e) {
1161
+ console.error('WebSocket message error:', e);
1162
+ }
1163
+ };
1164
+
1165
+ ws.onclose = () => {
1166
+ wsConnected = false;
1167
+ ws = null;
1168
+ updateConnectionStatus('offline', 'Hors ligne');
1169
+ if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
1170
+ reconnectAttempts++;
1171
+ setTimeout(connectWebSocket, RECONNECT_DELAY);
1172
+ }
1173
+ };
1174
+
1175
+ ws.onerror = (error) => console.error('WebSocket error:', error);
1176
+
1177
+ } catch (error) {
1178
+ console.error('WebSocket creation failed:', error);
1179
+ wsConnected = false;
1180
+ }
1181
+ }
1182
+
1183
+ setInterval(() => {
1184
+ if (ws?.readyState === WebSocket.OPEN) {
1185
+ ws.send(JSON.stringify({ type: 'ping' }));
1186
+ }
1187
+ }, 30000);
1188
+
1189
+ async function fetchStatus() {
1190
+ try {
1191
+ const response = await fetch(`${API_URL}/api/status`);
1192
+ const data = await response.json();
1193
+ currentData.activeReviews = data.jobs?.active || [];
1194
+ currentData.recentReviews = data.jobs?.recent || [];
1195
+ if (!wsConnected) updateConnectionStatus('online', 'En ligne (polling)');
1196
+ updateUI();
1197
+ } catch (error) {
1198
+ if (!wsConnected) {
1199
+ updateConnectionStatus('offline', 'Hors ligne');
1200
+ document.getElementById('running-count').textContent = '-';
1201
+ document.getElementById('queued-count').textContent = '-';
1202
+ document.getElementById('completed-count').textContent = '-';
1203
+ document.getElementById('active-reviews').innerHTML = '<div class="empty-state">Serveur non accessible</div>';
1204
+ document.getElementById('recent-reviews').innerHTML = '<div class="empty-state">Serveur non accessible</div>';
1205
+ }
1206
+ }
1207
+ }
1208
+
1209
+ async function loadModelSetting() {
1210
+ try {
1211
+ const response = await fetch(`${API_URL}/api/settings/model`);
1212
+ const data = await response.json();
1213
+ const select = document.getElementById('model-select');
1214
+ if (select && data.model) {
1215
+ select.value = data.model;
1216
+ }
1217
+ } catch (error) {
1218
+ console.error('Error loading model setting:', error);
1219
+ }
1220
+ }
1221
+
1222
+ async function changeModel(model) {
1223
+ try {
1224
+ const response = await fetch(`${API_URL}/api/settings/model`, {
1225
+ method: 'POST',
1226
+ headers: { 'Content-Type': 'application/json' },
1227
+ body: JSON.stringify({ model })
1228
+ });
1229
+ const data = await response.json();
1230
+ if (data.success) {
1231
+ console.log('Model changed to:', model);
1232
+ }
1233
+ } catch (error) {
1234
+ console.error('Error changing model:', error);
1235
+ }
1236
+ }
1237
+
1238
+ // Project config loader with persistence
1239
+ const STORAGE_KEY_PROJECTS = 'review-flow-projects';
1240
+ const STORAGE_KEY_CURRENT = 'review-flow-current-project';
1241
+ let currentProjectConfig = null;
1242
+ let currentProjectPath = null;
1243
+
1244
+ function getStoredProjects() {
1245
+ try {
1246
+ return JSON.parse(localStorage.getItem(STORAGE_KEY_PROJECTS) || '[]');
1247
+ } catch {
1248
+ return [];
1249
+ }
1250
+ }
1251
+
1252
+ function saveProjects(projects) {
1253
+ localStorage.setItem(STORAGE_KEY_PROJECTS, JSON.stringify(projects));
1254
+ }
1255
+
1256
+ function addProjectToHistory(path) {
1257
+ const projects = getStoredProjects();
1258
+ // Remove if already exists (to move to top)
1259
+ const filtered = projects.filter(p => p !== path);
1260
+ // Add to beginning
1261
+ filtered.unshift(path);
1262
+ // Keep max 10 projects
1263
+ saveProjects(filtered.slice(0, 10));
1264
+ updateProjectSelect();
1265
+ }
1266
+
1267
+ function removeProjectFromHistory(path) {
1268
+ const projects = getStoredProjects().filter(p => p !== path);
1269
+ saveProjects(projects);
1270
+ updateProjectSelect();
1271
+ }
1272
+
1273
+ function updateProjectSelect() {
1274
+ const select = document.getElementById('project-select');
1275
+ const projects = getStoredProjects();
1276
+ const current = localStorage.getItem(STORAGE_KEY_CURRENT) || '';
1277
+
1278
+ select.innerHTML = '<option value="">-- Sélectionner un projet --</option>';
1279
+ for (const path of projects) {
1280
+ const shortName = path.split('/').slice(-2).join('/');
1281
+ const option = document.createElement('option');
1282
+ option.value = path;
1283
+ option.textContent = shortName;
1284
+ option.title = path;
1285
+ if (path === current) option.selected = true;
1286
+ select.appendChild(option);
1287
+ }
1288
+ }
1289
+
1290
+ function onProjectSelect(path) {
1291
+ if (path) {
1292
+ document.getElementById('project-path-input').value = '';
1293
+ loadProjectConfigFromPath(path);
1294
+ }
1295
+ }
1296
+
1297
+ async function loadProjectConfig() {
1298
+ const input = document.getElementById('project-path-input');
1299
+ const select = document.getElementById('project-select');
1300
+ // Prioritize input field, fallback to select
1301
+ const projectPath = input.value.trim() || select.value;
1302
+
1303
+ if (!projectPath) {
1304
+ showConfigStatus('Sélectionnez ou entrez un chemin', 'error');
1305
+ return;
1306
+ }
1307
+
1308
+ await loadProjectConfigFromPath(projectPath);
1309
+ }
1310
+
1311
+ async function loadProjectConfigFromPath(projectPath) {
1312
+ const status = document.getElementById('config-status');
1313
+ const info = document.getElementById('config-info');
1314
+
1315
+ showConfigStatus('Chargement...', 'loading');
1316
+ info.classList.add('hidden');
1317
+
1318
+ try {
1319
+ const response = await fetch(`${API_URL}/api/project-config?path=${encodeURIComponent(projectPath)}`);
1320
+ const data = await response.json();
1321
+
1322
+ if (data.success) {
1323
+ currentProjectConfig = data.config;
1324
+ currentProjectPath = projectPath;
1325
+
1326
+ // Save to history and set as current
1327
+ addProjectToHistory(projectPath);
1328
+ localStorage.setItem(STORAGE_KEY_CURRENT, projectPath);
1329
+
1330
+ // Update select to show current project
1331
+ document.getElementById('project-select').value = projectPath;
1332
+ document.getElementById('project-path-input').value = '';
1333
+
1334
+ const shortName = projectPath.split('/').slice(-2).join('/');
1335
+ showConfigStatus(`<i data-lucide="check-circle"></i> ${shortName}`, 'success');
1336
+ refreshIcons();
1337
+
1338
+ // Update model selector if defaultModel is set
1339
+ if (data.config.defaultModel) {
1340
+ const modelSelect = document.getElementById('model-select');
1341
+ if (modelSelect) {
1342
+ modelSelect.value = data.config.defaultModel;
1343
+ changeModel(data.config.defaultModel);
1344
+ }
1345
+ }
1346
+
1347
+ // Update active platform and check CLI
1348
+ activePlatform = data.config.gitlab ? 'gitlab' : (data.config.github ? 'github' : null);
1349
+ updateGitCliUI();
1350
+
1351
+ // Reload reviews, stats, and MR tracking for this project
1352
+ fetchReviewFiles();
1353
+ fetchProjectStats();
1354
+ fetchMrTracking();
1355
+
1356
+ // Show stats section when project is loaded
1357
+ document.getElementById('stats-section').classList.remove('hidden');
1358
+
1359
+ // Display config info (only show active platform)
1360
+ const platformIcon = activePlatform === 'gitlab' ? '<i data-lucide="gitlab"></i> GitLab' : '<i data-lucide="github"></i> GitHub';
1361
+ info.innerHTML = `
1362
+ <span>${platformIcon}</span>
1363
+ <span><i data-lucide="bot"></i> ${data.config.defaultModel || 'non défini'}</span>
1364
+ <span><i data-lucide="file-text"></i> ${data.config.reviewSkill}</span>
1365
+ <span><i data-lucide="refresh-cw"></i> ${data.config.reviewFollowupSkill}</span>
1366
+ `;
1367
+ info.classList.remove('hidden');
1368
+ refreshIcons();
1369
+ } else {
1370
+ showConfigStatus('<i data-lucide="x-circle"></i> ' + data.error, 'error');
1371
+ refreshIcons();
1372
+ }
1373
+ } catch (error) {
1374
+ showConfigStatus('<i data-lucide="x-circle"></i> Erreur de chargement', 'error');
1375
+ refreshIcons();
1376
+ console.error('Error loading project config:', error);
1377
+ }
1378
+ }
1379
+
1380
+ function showConfigStatus(text, type) {
1381
+ const status = document.getElementById('config-status');
1382
+ status.innerHTML = text;
1383
+ status.className = `config-status ${type}`;
1384
+ status.classList.remove('hidden');
1385
+ refreshIcons();
1386
+ }
1387
+
1388
+ function removeCurrentProject() {
1389
+ const select = document.getElementById('project-select');
1390
+ const path = select.value;
1391
+ if (!path) {
1392
+ showConfigStatus('Aucun projet sélectionné', 'error');
1393
+ return;
1394
+ }
1395
+ if (confirm(`Retirer "${path.split('/').slice(-2).join('/')}" de la liste ?`)) {
1396
+ removeProjectFromHistory(path);
1397
+ localStorage.removeItem(STORAGE_KEY_CURRENT);
1398
+ currentProjectPath = null;
1399
+ currentProjectConfig = null;
1400
+ document.getElementById('config-info').classList.add('hidden');
1401
+ showConfigStatus('Projet retiré', 'success');
1402
+ }
1403
+ }
1404
+
1405
+ function initProjectLoader() {
1406
+ updateProjectSelect();
1407
+ // Auto-load last project
1408
+ const lastProject = localStorage.getItem(STORAGE_KEY_CURRENT);
1409
+ if (lastProject) {
1410
+ loadProjectConfigFromPath(lastProject);
1411
+ } else {
1412
+ // No project loaded - show empty state
1413
+ document.getElementById('recent-reviews').innerHTML =
1414
+ '<div class="empty-state">Charger un projet pour voir les reviews</div>';
1415
+ document.getElementById('project-stats').innerHTML =
1416
+ '<div class="empty-state">Charger un projet pour voir les stats</div>';
1417
+ }
1418
+ }
1419
+
1420
+ // Lucide icon helper - call after dynamic content is added
1421
+ function refreshIcons() {
1422
+ lucide.createIcons();
1423
+ }
1424
+
1425
+ // Icon helper for dynamic HTML
1426
+ function icon(name, className = '') {
1427
+ return `<i data-lucide="${name}" class="${className}"></i>`;
1428
+ }
1429
+
1430
+ // Platform-aware MR/PR label
1431
+ function getMrLabel(platform = activePlatform) {
1432
+ return platform === 'github' ? 'PR' : 'MR';
1433
+ }
1434
+
1435
+ // Cancel review modal state
1436
+ let cancelModalJobId = null;
1437
+
1438
+ function showCancelModal(jobId, mrNumber, jobType) {
1439
+ cancelModalJobId = jobId;
1440
+ const typeLabel = jobType === 'followup' ? 'followup' : 'review';
1441
+ document.getElementById('cancel-modal-title').textContent = `Annuler la ${typeLabel} de la ${getMrLabel()} !${mrNumber} (${typeLabel}) ?`;
1442
+ const modal = document.getElementById('cancel-modal');
1443
+ modal.classList.remove('hidden');
1444
+ requestAnimationFrame(() => modal.classList.add('visible'));
1445
+ }
1446
+
1447
+ function closeCancelModal(event) {
1448
+ if (event && event.target !== event.currentTarget) return;
1449
+ const modal = document.getElementById('cancel-modal');
1450
+ modal.classList.remove('visible');
1451
+ setTimeout(() => modal.classList.add('hidden'), 200);
1452
+ cancelModalJobId = null;
1453
+ }
1454
+
1455
+ async function confirmCancelReview() {
1456
+ if (!cancelModalJobId) return;
1457
+
1458
+ const jobId = cancelModalJobId;
1459
+ closeCancelModal();
1460
+
1461
+ try {
1462
+ const response = await fetch(`${API_URL}/api/reviews/cancel/${encodeURIComponent(jobId)}`, {
1463
+ method: 'POST',
1464
+ headers: { 'Content-Type': 'application/json' },
1465
+ body: JSON.stringify({
1466
+ projectPath: currentProjectPath || undefined,
1467
+ mrId: jobId,
1468
+ }),
1469
+ });
1470
+ const data = await response.json();
1471
+
1472
+ if (data.success) {
1473
+ const card = document.querySelector(`.review-item[data-job-id="${jobId}"]`);
1474
+ if (card) card.remove();
1475
+ showToast('Review annulée', 'success');
1476
+ fetchStatus();
1477
+ } else if (data.status === 'already-completed') {
1478
+ showToast('Cette review est déjà terminée', 'info');
1479
+ fetchStatus();
1480
+ } else {
1481
+ showToast(data.error || 'Erreur lors de l\'annulation', 'error');
1482
+ }
1483
+ } catch (error) {
1484
+ console.error('Error cancelling review:', error);
1485
+ showToast('Erreur lors de l\'annulation', 'error');
1486
+ }
1487
+ }
1488
+
1489
+ function showToast(message, type) {
1490
+ const container = document.getElementById('toast-container');
1491
+ const iconName = type === 'success' ? 'check-circle' : type === 'info' ? 'info' : 'alert-circle';
1492
+ const toast = document.createElement('div');
1493
+ toast.className = `toast ${type}`;
1494
+ toast.innerHTML = `<i data-lucide="${iconName}"></i> ${escapeHtml(message)}`;
1495
+ container.appendChild(toast);
1496
+ refreshIcons();
1497
+ requestAnimationFrame(() => toast.classList.add('visible'));
1498
+ setTimeout(() => {
1499
+ toast.classList.remove('visible');
1500
+ setTimeout(() => toast.remove(), 300);
1501
+ }, 3000);
1502
+ }
1503
+
1504
+ // Init
1505
+ connectWebSocket();
1506
+ fetchStatus();
1507
+ checkClaudeStatus();
1508
+ loadModelSetting();
1509
+ initProjectLoader(); // Will check git CLI and load reviews/stats after loading project config
1510
+
1511
+ // Initialize Lucide icons
1512
+ refreshIcons();
1513
+
1514
+ setInterval(fetchStatus, 5000);
1515
+ setInterval(() => {
1516
+ fetchReviewFiles();
1517
+ fetchProjectStats();
1518
+ fetchMrTracking();
1519
+ }, 30000); // Refresh review files, stats and MR tracking every 30s
1520
+
1521
+ setInterval(() => {
1522
+ document.querySelectorAll('.review-item').forEach(el => {
1523
+ const jobId = el.dataset.jobId;
1524
+ const review = currentData.activeReviews.find(r => r.id === jobId);
1525
+ if (review?.startedAt) {
1526
+ const metaEl = el.querySelector('.review-meta');
1527
+ if (metaEl) {
1528
+ const badge = metaEl.querySelector('.badge');
1529
+ metaEl.innerHTML = `${badge?.outerHTML || ''} ${icon('clock')} ${formatDuration(review.startedAt)}`;
1530
+ refreshIcons();
1531
+ }
1532
+ }
1533
+ });
1534
+ }, 1000);
1535
+ </script>
1536
+ </body>
1537
+ </html>