@jonit-dev/night-watch-cli 1.7.9 → 1.7.11

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 (350) hide show
  1. package/LICENSE +1 -1
  2. package/dist/cli.js +3 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/dashboard/tab-config.d.ts.map +1 -1
  5. package/dist/commands/dashboard/tab-config.js +9 -1
  6. package/dist/commands/dashboard/tab-config.js.map +1 -1
  7. package/dist/commands/doctor.d.ts.map +1 -1
  8. package/dist/commands/doctor.js +3 -0
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/init.d.ts.map +1 -1
  11. package/dist/commands/init.js +131 -19
  12. package/dist/commands/init.js.map +1 -1
  13. package/dist/commands/install.d.ts +4 -0
  14. package/dist/commands/install.d.ts.map +1 -1
  15. package/dist/commands/install.js +24 -0
  16. package/dist/commands/install.js.map +1 -1
  17. package/dist/commands/qa.d.ts +30 -0
  18. package/dist/commands/qa.d.ts.map +1 -0
  19. package/dist/commands/qa.js +159 -0
  20. package/dist/commands/qa.js.map +1 -0
  21. package/dist/commands/review.d.ts +5 -0
  22. package/dist/commands/review.d.ts.map +1 -1
  23. package/dist/commands/review.js +40 -0
  24. package/dist/commands/review.js.map +1 -1
  25. package/dist/commands/run.d.ts +11 -0
  26. package/dist/commands/run.d.ts.map +1 -1
  27. package/dist/commands/run.js +56 -1
  28. package/dist/commands/run.js.map +1 -1
  29. package/dist/commands/status.d.ts.map +1 -1
  30. package/dist/commands/status.js +3 -0
  31. package/dist/commands/status.js.map +1 -1
  32. package/dist/config.d.ts.map +1 -1
  33. package/dist/config.js +155 -1
  34. package/dist/config.js.map +1 -1
  35. package/dist/constants.d.ts +20 -1
  36. package/dist/constants.d.ts.map +1 -1
  37. package/dist/constants.js +40 -0
  38. package/dist/constants.js.map +1 -1
  39. package/dist/server/index.d.ts.map +1 -1
  40. package/dist/server/index.js +47 -5
  41. package/dist/server/index.js.map +1 -1
  42. package/dist/shared/types.d.ts +223 -0
  43. package/dist/shared/types.d.ts.map +1 -0
  44. package/dist/shared/types.js +7 -0
  45. package/dist/shared/types.js.map +1 -0
  46. package/dist/src/agents/soul-compiler.d.ts +11 -0
  47. package/dist/src/agents/soul-compiler.d.ts.map +1 -0
  48. package/dist/src/agents/soul-compiler.js +103 -0
  49. package/dist/src/agents/soul-compiler.js.map +1 -0
  50. package/dist/src/board/factory.d.ts +3 -0
  51. package/dist/src/board/factory.d.ts.map +1 -0
  52. package/dist/src/board/factory.js +10 -0
  53. package/dist/src/board/factory.js.map +1 -0
  54. package/dist/src/board/providers/github-graphql.d.ts +16 -0
  55. package/dist/src/board/providers/github-graphql.d.ts.map +1 -0
  56. package/dist/src/board/providers/github-graphql.js +43 -0
  57. package/dist/src/board/providers/github-graphql.js.map +1 -0
  58. package/dist/src/board/providers/github-projects.d.ts +51 -0
  59. package/dist/src/board/providers/github-projects.d.ts.map +1 -0
  60. package/dist/src/board/providers/github-projects.js +672 -0
  61. package/dist/src/board/providers/github-projects.js.map +1 -0
  62. package/dist/src/board/types.d.ts +60 -0
  63. package/dist/src/board/types.d.ts.map +1 -0
  64. package/dist/src/board/types.js +4 -0
  65. package/dist/src/board/types.js.map +1 -0
  66. package/dist/src/cli.d.ts +3 -0
  67. package/dist/src/cli.d.ts.map +1 -0
  68. package/dist/src/cli.js +80 -0
  69. package/dist/src/cli.js.map +1 -0
  70. package/dist/src/commands/board.d.ts +9 -0
  71. package/dist/src/commands/board.d.ts.map +1 -0
  72. package/dist/src/commands/board.js +294 -0
  73. package/dist/src/commands/board.js.map +1 -0
  74. package/dist/src/commands/cancel.d.ts +46 -0
  75. package/dist/src/commands/cancel.d.ts.map +1 -0
  76. package/dist/src/commands/cancel.js +241 -0
  77. package/dist/src/commands/cancel.js.map +1 -0
  78. package/dist/src/commands/dashboard/tab-actions.d.ts +10 -0
  79. package/dist/src/commands/dashboard/tab-actions.d.ts.map +1 -0
  80. package/dist/src/commands/dashboard/tab-actions.js +245 -0
  81. package/dist/src/commands/dashboard/tab-actions.js.map +1 -0
  82. package/dist/src/commands/dashboard/tab-config.d.ts +21 -0
  83. package/dist/src/commands/dashboard/tab-config.d.ts.map +1 -0
  84. package/dist/src/commands/dashboard/tab-config.js +829 -0
  85. package/dist/src/commands/dashboard/tab-config.js.map +1 -0
  86. package/dist/src/commands/dashboard/tab-logs.d.ts +10 -0
  87. package/dist/src/commands/dashboard/tab-logs.d.ts.map +1 -0
  88. package/dist/src/commands/dashboard/tab-logs.js +178 -0
  89. package/dist/src/commands/dashboard/tab-logs.js.map +1 -0
  90. package/dist/src/commands/dashboard/tab-schedules.d.ts +21 -0
  91. package/dist/src/commands/dashboard/tab-schedules.d.ts.map +1 -0
  92. package/dist/src/commands/dashboard/tab-schedules.js +304 -0
  93. package/dist/src/commands/dashboard/tab-schedules.js.map +1 -0
  94. package/dist/src/commands/dashboard/tab-status.d.ts +32 -0
  95. package/dist/src/commands/dashboard/tab-status.d.ts.map +1 -0
  96. package/dist/src/commands/dashboard/tab-status.js +421 -0
  97. package/dist/src/commands/dashboard/tab-status.js.map +1 -0
  98. package/dist/src/commands/dashboard/types.d.ts +43 -0
  99. package/dist/src/commands/dashboard/types.d.ts.map +1 -0
  100. package/dist/src/commands/dashboard/types.js +5 -0
  101. package/dist/src/commands/dashboard/types.js.map +1 -0
  102. package/dist/src/commands/dashboard.d.ts +11 -0
  103. package/dist/src/commands/dashboard.d.ts.map +1 -0
  104. package/dist/src/commands/dashboard.js +239 -0
  105. package/dist/src/commands/dashboard.js.map +1 -0
  106. package/dist/src/commands/doctor.d.ts +16 -0
  107. package/dist/src/commands/doctor.d.ts.map +1 -0
  108. package/dist/src/commands/doctor.js +202 -0
  109. package/dist/src/commands/doctor.js.map +1 -0
  110. package/dist/src/commands/history.d.ts +7 -0
  111. package/dist/src/commands/history.d.ts.map +1 -0
  112. package/dist/src/commands/history.js +56 -0
  113. package/dist/src/commands/history.js.map +1 -0
  114. package/dist/src/commands/init.d.ts +25 -0
  115. package/dist/src/commands/init.d.ts.map +1 -0
  116. package/dist/src/commands/init.js +543 -0
  117. package/dist/src/commands/init.js.map +1 -0
  118. package/dist/src/commands/install.d.ts +48 -0
  119. package/dist/src/commands/install.d.ts.map +1 -0
  120. package/dist/src/commands/install.js +303 -0
  121. package/dist/src/commands/install.js.map +1 -0
  122. package/dist/src/commands/logs.d.ts +15 -0
  123. package/dist/src/commands/logs.d.ts.map +1 -0
  124. package/dist/src/commands/logs.js +104 -0
  125. package/dist/src/commands/logs.js.map +1 -0
  126. package/dist/src/commands/prd-state.d.ts +12 -0
  127. package/dist/src/commands/prd-state.d.ts.map +1 -0
  128. package/dist/src/commands/prd-state.js +47 -0
  129. package/dist/src/commands/prd-state.js.map +1 -0
  130. package/dist/src/commands/prd.d.ts +24 -0
  131. package/dist/src/commands/prd.d.ts.map +1 -0
  132. package/dist/src/commands/prd.js +283 -0
  133. package/dist/src/commands/prd.js.map +1 -0
  134. package/dist/src/commands/prds.d.ts +13 -0
  135. package/dist/src/commands/prds.d.ts.map +1 -0
  136. package/dist/src/commands/prds.js +196 -0
  137. package/dist/src/commands/prds.js.map +1 -0
  138. package/dist/src/commands/prs.d.ts +14 -0
  139. package/dist/src/commands/prs.d.ts.map +1 -0
  140. package/dist/src/commands/prs.js +106 -0
  141. package/dist/src/commands/prs.js.map +1 -0
  142. package/dist/src/commands/qa.d.ts +30 -0
  143. package/dist/src/commands/qa.d.ts.map +1 -0
  144. package/dist/src/commands/qa.js +159 -0
  145. package/dist/src/commands/qa.js.map +1 -0
  146. package/dist/src/commands/retry.d.ts +9 -0
  147. package/dist/src/commands/retry.d.ts.map +1 -0
  148. package/dist/src/commands/retry.js +72 -0
  149. package/dist/src/commands/retry.js.map +1 -0
  150. package/dist/src/commands/review.d.ts +35 -0
  151. package/dist/src/commands/review.d.ts.map +1 -0
  152. package/dist/src/commands/review.js +252 -0
  153. package/dist/src/commands/review.js.map +1 -0
  154. package/dist/src/commands/run.d.ts +61 -0
  155. package/dist/src/commands/run.d.ts.map +1 -0
  156. package/dist/src/commands/run.js +364 -0
  157. package/dist/src/commands/run.js.map +1 -0
  158. package/dist/src/commands/serve.d.ts +7 -0
  159. package/dist/src/commands/serve.d.ts.map +1 -0
  160. package/dist/src/commands/serve.js +27 -0
  161. package/dist/src/commands/serve.js.map +1 -0
  162. package/dist/src/commands/slice.d.ts +26 -0
  163. package/dist/src/commands/slice.d.ts.map +1 -0
  164. package/dist/src/commands/slice.js +175 -0
  165. package/dist/src/commands/slice.js.map +1 -0
  166. package/dist/src/commands/state.d.ts +8 -0
  167. package/dist/src/commands/state.d.ts.map +1 -0
  168. package/dist/src/commands/state.js +56 -0
  169. package/dist/src/commands/state.js.map +1 -0
  170. package/dist/src/commands/status.d.ts +14 -0
  171. package/dist/src/commands/status.d.ts.map +1 -0
  172. package/dist/src/commands/status.js +147 -0
  173. package/dist/src/commands/status.js.map +1 -0
  174. package/dist/src/commands/uninstall.d.ts +25 -0
  175. package/dist/src/commands/uninstall.d.ts.map +1 -0
  176. package/dist/src/commands/uninstall.js +141 -0
  177. package/dist/src/commands/uninstall.js.map +1 -0
  178. package/dist/src/commands/update.d.ts +21 -0
  179. package/dist/src/commands/update.d.ts.map +1 -0
  180. package/dist/src/commands/update.js +87 -0
  181. package/dist/src/commands/update.js.map +1 -0
  182. package/dist/src/config.d.ts +23 -0
  183. package/dist/src/config.d.ts.map +1 -0
  184. package/dist/src/config.js +629 -0
  185. package/dist/src/config.js.map +1 -0
  186. package/dist/src/constants.d.ts +60 -0
  187. package/dist/src/constants.d.ts.map +1 -0
  188. package/dist/src/constants.js +118 -0
  189. package/dist/src/constants.js.map +1 -0
  190. package/dist/src/server/index.d.ts +23 -0
  191. package/dist/src/server/index.d.ts.map +1 -0
  192. package/dist/src/server/index.js +1642 -0
  193. package/dist/src/server/index.js.map +1 -0
  194. package/dist/src/slack/channel-manager.d.ts +32 -0
  195. package/dist/src/slack/channel-manager.d.ts.map +1 -0
  196. package/dist/src/slack/channel-manager.js +128 -0
  197. package/dist/src/slack/channel-manager.js.map +1 -0
  198. package/dist/src/slack/client.d.ts +63 -0
  199. package/dist/src/slack/client.d.ts.map +1 -0
  200. package/dist/src/slack/client.js +151 -0
  201. package/dist/src/slack/client.js.map +1 -0
  202. package/dist/src/slack/deliberation.d.ts +45 -0
  203. package/dist/src/slack/deliberation.d.ts.map +1 -0
  204. package/dist/src/slack/deliberation.js +539 -0
  205. package/dist/src/slack/deliberation.js.map +1 -0
  206. package/dist/src/slack/index.d.ts +6 -0
  207. package/dist/src/slack/index.d.ts.map +1 -0
  208. package/dist/src/slack/index.js +5 -0
  209. package/dist/src/slack/index.js.map +1 -0
  210. package/dist/src/slack/interaction-listener.d.ts +47 -0
  211. package/dist/src/slack/interaction-listener.d.ts.map +1 -0
  212. package/dist/src/slack/interaction-listener.js +216 -0
  213. package/dist/src/slack/interaction-listener.js.map +1 -0
  214. package/dist/src/storage/json-state-migrator.d.ts +24 -0
  215. package/dist/src/storage/json-state-migrator.d.ts.map +1 -0
  216. package/dist/src/storage/json-state-migrator.js +197 -0
  217. package/dist/src/storage/json-state-migrator.js.map +1 -0
  218. package/dist/src/storage/repositories/index.d.ts +25 -0
  219. package/dist/src/storage/repositories/index.d.ts.map +1 -0
  220. package/dist/src/storage/repositories/index.js +43 -0
  221. package/dist/src/storage/repositories/index.js.map +1 -0
  222. package/dist/src/storage/repositories/interfaces.d.ts +59 -0
  223. package/dist/src/storage/repositories/interfaces.d.ts.map +1 -0
  224. package/dist/src/storage/repositories/interfaces.js +6 -0
  225. package/dist/src/storage/repositories/interfaces.js.map +1 -0
  226. package/dist/src/storage/repositories/sqlite/agent-persona-repository.d.ts +27 -0
  227. package/dist/src/storage/repositories/sqlite/agent-persona-repository.d.ts.map +1 -0
  228. package/dist/src/storage/repositories/sqlite/agent-persona-repository.js +569 -0
  229. package/dist/src/storage/repositories/sqlite/agent-persona-repository.js.map +1 -0
  230. package/dist/src/storage/repositories/sqlite/execution-history-repository.d.ts +21 -0
  231. package/dist/src/storage/repositories/sqlite/execution-history-repository.d.ts.map +1 -0
  232. package/dist/src/storage/repositories/sqlite/execution-history-repository.js +94 -0
  233. package/dist/src/storage/repositories/sqlite/execution-history-repository.js.map +1 -0
  234. package/dist/src/storage/repositories/sqlite/prd-state-repository.d.ts +17 -0
  235. package/dist/src/storage/repositories/sqlite/prd-state-repository.d.ts.map +1 -0
  236. package/dist/src/storage/repositories/sqlite/prd-state-repository.js +74 -0
  237. package/dist/src/storage/repositories/sqlite/prd-state-repository.js.map +1 -0
  238. package/dist/src/storage/repositories/sqlite/project-registry-repository.d.ts +17 -0
  239. package/dist/src/storage/repositories/sqlite/project-registry-repository.d.ts.map +1 -0
  240. package/dist/src/storage/repositories/sqlite/project-registry-repository.js +43 -0
  241. package/dist/src/storage/repositories/sqlite/project-registry-repository.js.map +1 -0
  242. package/dist/src/storage/repositories/sqlite/roadmap-state-repository.d.ts +14 -0
  243. package/dist/src/storage/repositories/sqlite/roadmap-state-repository.d.ts.map +1 -0
  244. package/dist/src/storage/repositories/sqlite/roadmap-state-repository.js +47 -0
  245. package/dist/src/storage/repositories/sqlite/roadmap-state-repository.js.map +1 -0
  246. package/dist/src/storage/repositories/sqlite/slack-discussion-repository.d.ts +20 -0
  247. package/dist/src/storage/repositories/sqlite/slack-discussion-repository.d.ts.map +1 -0
  248. package/dist/src/storage/repositories/sqlite/slack-discussion-repository.js +88 -0
  249. package/dist/src/storage/repositories/sqlite/slack-discussion-repository.js.map +1 -0
  250. package/dist/src/storage/sqlite/client.d.ts +23 -0
  251. package/dist/src/storage/sqlite/client.d.ts.map +1 -0
  252. package/dist/src/storage/sqlite/client.js +47 -0
  253. package/dist/src/storage/sqlite/client.js.map +1 -0
  254. package/dist/src/storage/sqlite/migrations.d.ts +11 -0
  255. package/dist/src/storage/sqlite/migrations.d.ts.map +1 -0
  256. package/dist/src/storage/sqlite/migrations.js +94 -0
  257. package/dist/src/storage/sqlite/migrations.js.map +1 -0
  258. package/dist/src/templates/prd-template.d.ts +11 -0
  259. package/dist/src/templates/prd-template.d.ts.map +1 -0
  260. package/dist/src/templates/prd-template.js +166 -0
  261. package/dist/src/templates/prd-template.js.map +1 -0
  262. package/dist/src/templates/slicer-prompt.d.ts +54 -0
  263. package/dist/src/templates/slicer-prompt.d.ts.map +1 -0
  264. package/dist/src/templates/slicer-prompt.js +163 -0
  265. package/dist/src/templates/slicer-prompt.js.map +1 -0
  266. package/dist/src/types.d.ts +127 -0
  267. package/dist/src/types.d.ts.map +1 -0
  268. package/dist/src/types.js +5 -0
  269. package/dist/src/types.js.map +1 -0
  270. package/dist/src/utils/checks.d.ts +55 -0
  271. package/dist/src/utils/checks.d.ts.map +1 -0
  272. package/dist/src/utils/checks.js +246 -0
  273. package/dist/src/utils/checks.js.map +1 -0
  274. package/dist/src/utils/config-writer.d.ts +16 -0
  275. package/dist/src/utils/config-writer.d.ts.map +1 -0
  276. package/dist/src/utils/config-writer.js +45 -0
  277. package/dist/src/utils/config-writer.js.map +1 -0
  278. package/dist/src/utils/crontab.d.ts +62 -0
  279. package/dist/src/utils/crontab.d.ts.map +1 -0
  280. package/dist/src/utils/crontab.js +168 -0
  281. package/dist/src/utils/crontab.js.map +1 -0
  282. package/dist/src/utils/execution-history.d.ts +54 -0
  283. package/dist/src/utils/execution-history.d.ts.map +1 -0
  284. package/dist/src/utils/execution-history.js +80 -0
  285. package/dist/src/utils/execution-history.js.map +1 -0
  286. package/dist/src/utils/github.d.ts +40 -0
  287. package/dist/src/utils/github.d.ts.map +1 -0
  288. package/dist/src/utils/github.js +126 -0
  289. package/dist/src/utils/github.js.map +1 -0
  290. package/dist/src/utils/notify.d.ts +63 -0
  291. package/dist/src/utils/notify.d.ts.map +1 -0
  292. package/dist/src/utils/notify.js +389 -0
  293. package/dist/src/utils/notify.js.map +1 -0
  294. package/dist/src/utils/prd-states.d.ts +16 -0
  295. package/dist/src/utils/prd-states.d.ts.map +1 -0
  296. package/dist/src/utils/prd-states.js +28 -0
  297. package/dist/src/utils/prd-states.js.map +1 -0
  298. package/dist/src/utils/registry.d.ts +45 -0
  299. package/dist/src/utils/registry.d.ts.map +1 -0
  300. package/dist/src/utils/registry.js +86 -0
  301. package/dist/src/utils/registry.js.map +1 -0
  302. package/dist/src/utils/roadmap-parser.d.ts +45 -0
  303. package/dist/src/utils/roadmap-parser.d.ts.map +1 -0
  304. package/dist/src/utils/roadmap-parser.js +136 -0
  305. package/dist/src/utils/roadmap-parser.js.map +1 -0
  306. package/dist/src/utils/roadmap-scanner.d.ts +92 -0
  307. package/dist/src/utils/roadmap-scanner.d.ts.map +1 -0
  308. package/dist/src/utils/roadmap-scanner.js +349 -0
  309. package/dist/src/utils/roadmap-scanner.js.map +1 -0
  310. package/dist/src/utils/roadmap-state.d.ts +90 -0
  311. package/dist/src/utils/roadmap-state.d.ts.map +1 -0
  312. package/dist/src/utils/roadmap-state.js +154 -0
  313. package/dist/src/utils/roadmap-state.js.map +1 -0
  314. package/dist/src/utils/script-result.d.ts +12 -0
  315. package/dist/src/utils/script-result.d.ts.map +1 -0
  316. package/dist/src/utils/script-result.js +46 -0
  317. package/dist/src/utils/script-result.js.map +1 -0
  318. package/dist/src/utils/shell.d.ts +27 -0
  319. package/dist/src/utils/shell.d.ts.map +1 -0
  320. package/dist/src/utils/shell.js +64 -0
  321. package/dist/src/utils/shell.js.map +1 -0
  322. package/dist/src/utils/status-data.d.ts +148 -0
  323. package/dist/src/utils/status-data.d.ts.map +1 -0
  324. package/dist/src/utils/status-data.js +593 -0
  325. package/dist/src/utils/status-data.js.map +1 -0
  326. package/dist/src/utils/ui.d.ts +55 -0
  327. package/dist/src/utils/ui.d.ts.map +1 -0
  328. package/dist/src/utils/ui.js +121 -0
  329. package/dist/src/utils/ui.js.map +1 -0
  330. package/dist/types.d.ts +43 -1
  331. package/dist/types.d.ts.map +1 -1
  332. package/dist/utils/notify.d.ts.map +1 -1
  333. package/dist/utils/notify.js +18 -0
  334. package/dist/utils/notify.js.map +1 -1
  335. package/dist/utils/status-data.d.ts +4 -0
  336. package/dist/utils/status-data.d.ts.map +1 -1
  337. package/dist/utils/status-data.js +13 -3
  338. package/dist/utils/status-data.js.map +1 -1
  339. package/package.json +3 -1
  340. package/scripts/night-watch-cron.sh +50 -2
  341. package/scripts/night-watch-helpers.sh +54 -2
  342. package/scripts/night-watch-pr-reviewer-cron.sh +79 -1
  343. package/scripts/night-watch-qa-cron.sh +269 -0
  344. package/templates/night-watch-qa.md +157 -0
  345. package/templates/night-watch.config.json +14 -1
  346. package/web/dist/assets/index-BtxQU4oX.css +1 -0
  347. package/web/dist/assets/index-CsNIryJz.js +473 -0
  348. package/web/dist/index.html +2 -2
  349. package/web/dist/assets/index-C64sy08d.js +0 -360
  350. package/web/dist/assets/index-DzoZeo_Y.css +0 -1
@@ -10,6 +10,8 @@ set -euo pipefail
10
10
  # NW_REVIEWER_MAX_RUNTIME=3600 - Maximum runtime in seconds (1 hour)
11
11
  # NW_PROVIDER_CMD=claude - AI provider CLI to use (claude, codex, etc.)
12
12
  # NW_DRY_RUN=0 - Set to 1 for dry-run mode (prints diagnostics only)
13
+ # NW_AUTO_MERGE=0 - Set to 1 to enable auto-merge
14
+ # NW_AUTO_MERGE_METHOD=squash - Merge method: squash, merge, or rebase
13
15
 
14
16
  PROJECT_DIR="${1:?Usage: $0 /path/to/project}"
15
17
  PROJECT_NAME=$(basename "${PROJECT_DIR}")
@@ -20,6 +22,8 @@ MAX_LOG_SIZE="524288" # 512 KB
20
22
  PROVIDER_CMD="${NW_PROVIDER_CMD:-claude}"
21
23
  MIN_REVIEW_SCORE="${NW_MIN_REVIEW_SCORE:-80}"
22
24
  BRANCH_PATTERNS_RAW="${NW_BRANCH_PATTERNS:-feat/,night-watch/}"
25
+ AUTO_MERGE="${NW_AUTO_MERGE:-0}"
26
+ AUTO_MERGE_METHOD="${NW_AUTO_MERGE_METHOD:-squash}"
23
27
 
24
28
  # Ensure NVM / Node / Claude are on PATH
25
29
  export NVM_DIR="${HOME}/.nvm"
@@ -156,6 +160,10 @@ if [ "${NW_DRY_RUN:-0}" = "1" ]; then
156
160
  echo "Provider: ${PROVIDER_CMD}"
157
161
  echo "Branch Patterns: ${BRANCH_PATTERNS_RAW}"
158
162
  echo "Min Review Score: ${MIN_REVIEW_SCORE}"
163
+ echo "Auto-merge: ${AUTO_MERGE}"
164
+ if [ "${AUTO_MERGE}" = "1" ]; then
165
+ echo "Auto-merge Method: ${AUTO_MERGE_METHOD}"
166
+ fi
159
167
  echo "Open PRs needing work:${PRS_NEEDING_WORK}"
160
168
  echo "Default Branch: ${DEFAULT_BRANCH}"
161
169
  echo "Review Worktree: ${REVIEW_WORKTREE_DIR}"
@@ -204,9 +212,79 @@ esac
204
212
 
205
213
  cleanup_worktrees "${PROJECT_DIR}"
206
214
 
215
+ # ── Auto-merge eligible PRs ─────────────────────────────────────────────────────
216
+ # After the reviewer completes, check for PRs that are merge-ready and queue them
217
+ # for auto-merge if enabled. Uses gh pr merge --auto to respect GitHub branch protection.
218
+ AUTO_MERGED_PRS=""
219
+ AUTO_MERGE_FAILED_PRS=""
220
+
221
+ if [ "${AUTO_MERGE}" = "1" ] && [ ${EXIT_CODE} -eq 0 ]; then
222
+ log "AUTO-MERGE: Checking for merge-ready PRs..."
223
+
224
+ while IFS=$'\t' read -r pr_number pr_branch; do
225
+ if [ -z "${pr_number}" ] || [ -z "${pr_branch}" ]; then
226
+ continue
227
+ fi
228
+
229
+ # Only process PRs matching branch patterns
230
+ if ! printf '%s\n' "${pr_branch}" | grep -Eq "${BRANCH_REGEX}"; then
231
+ continue
232
+ fi
233
+
234
+ # Check CI status - must have no failures
235
+ FAILED_CHECKS=$(gh pr checks "${pr_number}" 2>/dev/null | grep -ci 'fail' || true)
236
+ if [ "${FAILED_CHECKS}" -gt 0 ]; then
237
+ continue
238
+ fi
239
+
240
+ # Check review score - must have score >= threshold
241
+ ALL_COMMENTS=$(
242
+ {
243
+ gh pr view "${pr_number}" --json comments --jq '.comments[].body' 2>/dev/null || true
244
+ if [ -n "${REPO}" ]; then
245
+ gh api "repos/${REPO}/issues/${pr_number}/comments" --jq '.[].body' 2>/dev/null || true
246
+ fi
247
+ } | sort -u
248
+ )
249
+ LATEST_SCORE=$(echo "${ALL_COMMENTS}" \
250
+ | grep -oP 'Overall Score:\*?\*?\s*(\d+)/100' \
251
+ | tail -1 \
252
+ | grep -oP '\d+(?=/100)' || echo "")
253
+
254
+ # Skip PRs without a score
255
+ if [ -z "${LATEST_SCORE}" ]; then
256
+ continue
257
+ fi
258
+
259
+ # Skip PRs with score below threshold
260
+ if [ "${LATEST_SCORE}" -lt "${MIN_REVIEW_SCORE}" ]; then
261
+ continue
262
+ fi
263
+
264
+ # PR is merge-ready - queue for auto-merge
265
+ log "AUTO-MERGE: PR #${pr_number} (${pr_branch}) — score ${LATEST_SCORE}/100, CI passing"
266
+
267
+ if gh pr merge "${pr_number}" --"${AUTO_MERGE_METHOD}" --auto --delete-branch 2>>"${LOG_FILE}"; then
268
+ log "AUTO-MERGE: Successfully queued merge for PR #${pr_number}"
269
+ if [ -z "${AUTO_MERGED_PRS}" ]; then
270
+ AUTO_MERGED_PRS="#${pr_number}"
271
+ else
272
+ AUTO_MERGED_PRS="${AUTO_MERGED_PRS},#${pr_number}"
273
+ fi
274
+ else
275
+ log "WARN: Auto-merge failed for PR #${pr_number}"
276
+ if [ -z "${AUTO_MERGE_FAILED_PRS}" ]; then
277
+ AUTO_MERGE_FAILED_PRS="#${pr_number}"
278
+ else
279
+ AUTO_MERGE_FAILED_PRS="${AUTO_MERGE_FAILED_PRS},#${pr_number}"
280
+ fi
281
+ fi
282
+ done < <(gh pr list --state open --json number,headRefName --jq '.[] | [.number, .headRefName] | @tsv' 2>/dev/null || true)
283
+ fi
284
+
207
285
  if [ ${EXIT_CODE} -eq 0 ]; then
208
286
  log "DONE: PR reviewer completed successfully"
209
- emit_result "success_reviewed" "prs=${PRS_NEEDING_WORK_CSV}"
287
+ emit_result "success_reviewed" "prs=${PRS_NEEDING_WORK_CSV}|auto_merged=${AUTO_MERGED_PRS}|auto_merge_failed=${AUTO_MERGE_FAILED_PRS}"
210
288
  elif [ ${EXIT_CODE} -eq 124 ]; then
211
289
  log "TIMEOUT: PR reviewer killed after ${MAX_RUNTIME}s"
212
290
  emit_result "timeout" "prs=${PRS_NEEDING_WORK_CSV}"
@@ -0,0 +1,269 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Night Watch QA Cron Runner (project-agnostic)
5
+ # Usage: night-watch-qa-cron.sh /path/to/project
6
+ #
7
+ # NOTE: This script expects environment variables to be set by the caller.
8
+ # The Node.js CLI will inject config values via environment variables.
9
+ # Required env vars (with defaults shown):
10
+ # NW_QA_MAX_RUNTIME=3600 - Maximum runtime in seconds (1 hour)
11
+ # NW_PROVIDER_CMD=claude - AI provider CLI to use (claude, codex, etc.)
12
+ # NW_BRANCH_PATTERNS=feat/,night-watch/ - Comma-separated branch prefixes to match
13
+ # NW_QA_SKIP_LABEL=skip-qa - Label to skip QA on a PR
14
+ # NW_QA_ARTIFACTS=both - Artifact mode (both, tests, report)
15
+ # NW_QA_AUTO_INSTALL_PLAYWRIGHT=1 - Auto-install Playwright browsers
16
+ # NW_DRY_RUN=0 - Set to 1 for dry-run mode (prints diagnostics only)
17
+
18
+ PROJECT_DIR="${1:?Usage: $0 /path/to/project}"
19
+ PROJECT_NAME=$(basename "${PROJECT_DIR}")
20
+ LOG_DIR="${PROJECT_DIR}/logs"
21
+ LOG_FILE="${LOG_DIR}/night-watch-qa.log"
22
+ MAX_RUNTIME="${NW_QA_MAX_RUNTIME:-3600}" # 1 hour
23
+ MAX_LOG_SIZE="524288" # 512 KB
24
+ PROVIDER_CMD="${NW_PROVIDER_CMD:-claude}"
25
+ BRANCH_PATTERNS_RAW="${NW_BRANCH_PATTERNS:-feat/,night-watch/}"
26
+ SKIP_LABEL="${NW_QA_SKIP_LABEL:-skip-qa}"
27
+ QA_ARTIFACTS="${NW_QA_ARTIFACTS:-both}"
28
+ QA_AUTO_INSTALL_PLAYWRIGHT="${NW_QA_AUTO_INSTALL_PLAYWRIGHT:-1}"
29
+
30
+ # Ensure NVM / Node / Claude are on PATH
31
+ export NVM_DIR="${HOME}/.nvm"
32
+ [ -s "${NVM_DIR}/nvm.sh" ] && . "${NVM_DIR}/nvm.sh"
33
+
34
+ # NOTE: Environment variables should be set by the caller (Node.js CLI).
35
+ # The .env.night-watch sourcing has been removed - config is now injected via env vars.
36
+
37
+ mkdir -p "${LOG_DIR}"
38
+
39
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
40
+ # shellcheck source=night-watch-helpers.sh
41
+ source "${SCRIPT_DIR}/night-watch-helpers.sh"
42
+ PROJECT_RUNTIME_KEY=$(project_runtime_key "${PROJECT_DIR}")
43
+ # NOTE: Lock file path must match qaLockPath() in src/utils/status-data.ts
44
+ LOCK_FILE="/tmp/night-watch-qa-${PROJECT_RUNTIME_KEY}.lock"
45
+
46
+ emit_result() {
47
+ local status="${1:?status required}"
48
+ local details="${2:-}"
49
+ if [ -n "${details}" ]; then
50
+ echo "NIGHT_WATCH_RESULT:${status}|${details}"
51
+ else
52
+ echo "NIGHT_WATCH_RESULT:${status}"
53
+ fi
54
+ }
55
+
56
+ # Validate provider
57
+ if ! validate_provider "${PROVIDER_CMD}"; then
58
+ echo "ERROR: Unknown provider: ${PROVIDER_CMD}" >&2
59
+ exit 1
60
+ fi
61
+
62
+ rotate_log
63
+
64
+ if ! acquire_lock "${LOCK_FILE}"; then
65
+ emit_result "skip_locked"
66
+ exit 0
67
+ fi
68
+
69
+ cd "${PROJECT_DIR}"
70
+
71
+ # Convert comma-separated branch prefixes into a regex that matches branch starts.
72
+ BRANCH_REGEX=""
73
+ IFS=',' read -r -a BRANCH_PATTERNS <<< "${BRANCH_PATTERNS_RAW}"
74
+ for pattern in "${BRANCH_PATTERNS[@]}"; do
75
+ trimmed_pattern=$(printf '%s' "${pattern}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
76
+ if [ -n "${trimmed_pattern}" ]; then
77
+ BRANCH_REGEX="${BRANCH_REGEX}${BRANCH_REGEX:+|}^${trimmed_pattern}"
78
+ fi
79
+ done
80
+
81
+ if [ -z "${BRANCH_REGEX}" ]; then
82
+ BRANCH_REGEX='^(feat/|night-watch/)'
83
+ fi
84
+
85
+ # List open PRs with their details for filtering
86
+ PR_JSON=$(gh pr list --state open --json number,headRefName,title,labels 2>/dev/null || echo "[]")
87
+
88
+ # Count PRs matching branch patterns
89
+ OPEN_PRS=$(
90
+ echo "${PR_JSON}" \
91
+ | jq -r '.[].headRefName' 2>/dev/null \
92
+ | { grep -E "${BRANCH_REGEX}" || true; } \
93
+ | wc -l \
94
+ | tr -d '[:space:]'
95
+ )
96
+
97
+ if [ "${OPEN_PRS}" -eq 0 ]; then
98
+ log "SKIP: No open PRs matching branch patterns (${BRANCH_PATTERNS_RAW})"
99
+ emit_result "skip_no_open_prs"
100
+ exit 0
101
+ fi
102
+
103
+ REPO=$(gh repo view --json nameWithOwner --jq '.nameWithOwner' 2>/dev/null || echo "")
104
+
105
+ # Collect PRs that need QA
106
+ PRS_NEEDING_QA=""
107
+ QA_NEEDED=0
108
+
109
+ while IFS=$'\t' read -r pr_number pr_branch pr_title pr_labels; do
110
+ if [ -z "${pr_number}" ] || [ -z "${pr_branch}" ]; then
111
+ continue
112
+ fi
113
+
114
+ # Filter by branch pattern
115
+ if ! printf '%s\n' "${pr_branch}" | grep -Eq "${BRANCH_REGEX}"; then
116
+ continue
117
+ fi
118
+
119
+ # Skip PRs with the skip label
120
+ if echo "${pr_labels}" | grep -q "${SKIP_LABEL}"; then
121
+ log "SKIP-QA: PR #${pr_number} (${pr_branch}) has '${SKIP_LABEL}' label"
122
+ continue
123
+ fi
124
+
125
+ # Skip PRs with [skip-qa] in their title
126
+ if echo "${pr_title}" | grep -qi '\[skip-qa\]'; then
127
+ log "SKIP-QA: PR #${pr_number} (${pr_branch}) has [skip-qa] in title"
128
+ continue
129
+ fi
130
+
131
+ # Skip PRs that already have a QA comment (idempotency)
132
+ ALL_COMMENTS=$(
133
+ {
134
+ gh pr view "${pr_number}" --json comments --jq '.comments[].body' 2>/dev/null || true
135
+ if [ -n "${REPO}" ]; then
136
+ gh api "repos/${REPO}/issues/${pr_number}/comments" --jq '.[].body' 2>/dev/null || true
137
+ fi
138
+ } | sort -u
139
+ )
140
+ if echo "${ALL_COMMENTS}" | grep -q '<!-- night-watch-qa-marker -->'; then
141
+ log "SKIP-QA: PR #${pr_number} (${pr_branch}) already has QA comment"
142
+ continue
143
+ fi
144
+
145
+ QA_NEEDED=1
146
+ PRS_NEEDING_QA="${PRS_NEEDING_QA} #${pr_number}"
147
+ done < <(
148
+ echo "${PR_JSON}" \
149
+ | jq -r '.[] | [.number, .headRefName, .title, ([.labels[].name] | join(","))] | @tsv' 2>/dev/null || true
150
+ )
151
+
152
+ if [ "${QA_NEEDED}" -eq 0 ]; then
153
+ log "SKIP: All ${OPEN_PRS} open PR(s) matching patterns already have QA comments"
154
+ emit_result "skip_all_qa_done"
155
+ exit 0
156
+ fi
157
+
158
+ PRS_NEEDING_QA=$(echo "${PRS_NEEDING_QA}" \
159
+ | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/[[:space:]]*$//')
160
+ PRS_NEEDING_QA_CSV="${PRS_NEEDING_QA// /,}"
161
+
162
+ if [ -n "${NW_DEFAULT_BRANCH:-}" ]; then
163
+ DEFAULT_BRANCH="${NW_DEFAULT_BRANCH}"
164
+ else
165
+ DEFAULT_BRANCH=$(detect_default_branch "${PROJECT_DIR}")
166
+ fi
167
+ QA_WORKTREE_DIR="$(dirname "${PROJECT_DIR}")/${PROJECT_NAME}-nw-qa-runner"
168
+
169
+ log "START: Found PR(s) needing QA:${PRS_NEEDING_QA}"
170
+
171
+ cleanup_worktrees "${PROJECT_DIR}"
172
+
173
+ # Dry-run mode: print diagnostics and exit
174
+ if [ "${NW_DRY_RUN:-0}" = "1" ]; then
175
+ echo "=== Dry Run: QA Runner ==="
176
+ echo "Provider: ${PROVIDER_CMD}"
177
+ echo "Branch Patterns: ${BRANCH_PATTERNS_RAW}"
178
+ echo "Skip Label: ${SKIP_LABEL}"
179
+ echo "QA Artifacts: ${QA_ARTIFACTS}"
180
+ echo "Auto-install Playwright: ${QA_AUTO_INSTALL_PLAYWRIGHT}"
181
+ echo "Open PRs needing QA:${PRS_NEEDING_QA}"
182
+ echo "Default Branch: ${DEFAULT_BRANCH}"
183
+ echo "QA Worktree: ${QA_WORKTREE_DIR}"
184
+ echo "Timeout: ${MAX_RUNTIME}s"
185
+ exit 0
186
+ fi
187
+
188
+ EXIT_CODE=0
189
+
190
+ # Process each PR that needs QA
191
+ for pr_ref in ${PRS_NEEDING_QA}; do
192
+ pr_num="${pr_ref#\#}"
193
+
194
+ cleanup_worktrees "${PROJECT_DIR}"
195
+ if ! prepare_detached_worktree "${PROJECT_DIR}" "${QA_WORKTREE_DIR}" "${DEFAULT_BRANCH}" "${LOG_FILE}"; then
196
+ log "FAIL: Unable to create isolated QA worktree ${QA_WORKTREE_DIR} for PR #${pr_num}"
197
+ EXIT_CODE=1
198
+ break
199
+ fi
200
+
201
+ log "QA: Checking out PR #${pr_num} in worktree"
202
+ if ! (cd "${QA_WORKTREE_DIR}" && gh pr checkout "${pr_num}" >> "${LOG_FILE}" 2>&1); then
203
+ log "WARN: Failed to checkout PR #${pr_num}, skipping"
204
+ EXIT_CODE=1
205
+ cleanup_worktrees "${PROJECT_DIR}"
206
+ continue
207
+ fi
208
+
209
+ case "${PROVIDER_CMD}" in
210
+ claude)
211
+ if (
212
+ cd "${QA_WORKTREE_DIR}" && timeout "${MAX_RUNTIME}" \
213
+ claude -p "/night-watch-qa" \
214
+ --dangerously-skip-permissions \
215
+ >> "${LOG_FILE}" 2>&1
216
+ ); then
217
+ log "QA: PR #${pr_num} — provider completed successfully"
218
+ else
219
+ local_exit=$?
220
+ log "QA: PR #${pr_num} — provider exited with code ${local_exit}"
221
+ if [ ${local_exit} -eq 124 ]; then
222
+ EXIT_CODE=124
223
+ break
224
+ fi
225
+ EXIT_CODE=${local_exit}
226
+ fi
227
+ ;;
228
+ codex)
229
+ if (
230
+ cd "${QA_WORKTREE_DIR}" && timeout "${MAX_RUNTIME}" \
231
+ codex --quiet \
232
+ --yolo \
233
+ --prompt "$(cat "${QA_WORKTREE_DIR}/.claude/commands/night-watch-qa.md")" \
234
+ >> "${LOG_FILE}" 2>&1
235
+ ); then
236
+ log "QA: PR #${pr_num} — provider completed successfully"
237
+ else
238
+ local_exit=$?
239
+ log "QA: PR #${pr_num} — provider exited with code ${local_exit}"
240
+ if [ ${local_exit} -eq 124 ]; then
241
+ EXIT_CODE=124
242
+ break
243
+ fi
244
+ EXIT_CODE=${local_exit}
245
+ fi
246
+ ;;
247
+ *)
248
+ log "ERROR: Unknown provider: ${PROVIDER_CMD}"
249
+ exit 1
250
+ ;;
251
+ esac
252
+
253
+ cleanup_worktrees "${PROJECT_DIR}"
254
+ done
255
+
256
+ cleanup_worktrees "${PROJECT_DIR}"
257
+
258
+ if [ ${EXIT_CODE} -eq 0 ]; then
259
+ log "DONE: QA runner completed successfully"
260
+ emit_result "success_qa" "prs=${PRS_NEEDING_QA_CSV}"
261
+ elif [ ${EXIT_CODE} -eq 124 ]; then
262
+ log "TIMEOUT: QA runner killed after ${MAX_RUNTIME}s"
263
+ emit_result "timeout" "prs=${PRS_NEEDING_QA_CSV}"
264
+ else
265
+ log "FAIL: QA runner exited with code ${EXIT_CODE}"
266
+ emit_result "failure" "prs=${PRS_NEEDING_QA_CSV}"
267
+ fi
268
+
269
+ exit "${EXIT_CODE}"
@@ -0,0 +1,157 @@
1
+ You are the Night Watch QA agent. Your job is to analyze open PRs, generate appropriate tests for the changes, run them, and report results with visual evidence.
2
+
3
+ ## Context
4
+
5
+ You are running inside a worktree checked out to a PR branch. Your goal is to:
6
+ 1. Analyze what changed in this PR compared to the base branch
7
+ 2. Determine if the changes are UI-related, API-related, or both
8
+ 3. Generate appropriate tests (Playwright e2e for UI, integration tests for API)
9
+ 4. Run the tests and capture artifacts (screenshots, videos for UI)
10
+ 5. Commit the tests and artifacts, then comment on the PR with results
11
+
12
+ ## Environment Variables Available
13
+ - `NW_QA_ARTIFACTS` — What to capture: "screenshot", "video", or "both" (default: "both")
14
+ - `NW_QA_AUTO_INSTALL_PLAYWRIGHT` — "1" to auto-install Playwright if missing
15
+
16
+ ## Instructions
17
+
18
+ ### Step 1: Analyze the PR diff
19
+
20
+ Get the diff against the base branch:
21
+ ```
22
+ git diff origin/${DEFAULT_BRANCH}...HEAD --name-only
23
+ git diff origin/${DEFAULT_BRANCH}...HEAD --stat
24
+ ```
25
+
26
+ Read the changed files to understand what the PR introduces.
27
+
28
+ ### Step 2: Classify and Decide
29
+
30
+ Based on the diff, determine:
31
+ - **UI changes**: New/modified components, pages, layouts, styles, client-side logic
32
+ - **API changes**: New/modified endpoints, controllers, services, middleware, database queries
33
+ - **Both**: PR touches both UI and API code
34
+ - **No tests needed**: Trivial changes (docs, config, comments only) — in this case, post a comment saying "QA: No tests needed for this PR" and stop
35
+
36
+ ### Step 3: Prepare Test Infrastructure
37
+
38
+ **For UI tests (Playwright):**
39
+ 1. Check if Playwright is available: `npx playwright --version`
40
+ 2. If not available and `NW_QA_AUTO_INSTALL_PLAYWRIGHT=1`:
41
+ - Run `npm install -D @playwright/test` (or yarn/pnpm equivalent based on lockfile)
42
+ - Run `npx playwright install chromium`
43
+ 3. If not available and auto-install is disabled, skip UI tests and note in the report
44
+
45
+ **For API tests:**
46
+ - Use the project's existing test framework (vitest, jest, or mocha — detect from package.json)
47
+ - If no test framework exists, use vitest
48
+
49
+ ### Step 4: Generate Tests
50
+
51
+ **UI Tests (Playwright):**
52
+ - Create test files in `tests/e2e/qa/` (or the project's existing e2e directory)
53
+ - Test the specific feature/page changed in the PR
54
+ - Configure Playwright for artifacts based on `NW_QA_ARTIFACTS`:
55
+ - `"screenshot"`: `screenshot: 'on'` only
56
+ - `"video"`: `video: { mode: 'on', size: { width: 1280, height: 720 } }` only
57
+ - `"both"`: Both screenshot and video enabled
58
+ - Name test files with a `qa-` prefix: `qa-<feature-name>.spec.ts`
59
+ - Include at minimum: navigation to the feature, interaction with key elements, visual assertions
60
+
61
+ **API Tests:**
62
+ - Create test files in `tests/integration/qa/` (or the project's existing test directory)
63
+ - Test the specific endpoints changed in the PR
64
+ - Include: happy path, error cases, validation checks
65
+ - Name test files with a `qa-` prefix: `qa-<endpoint-name>.test.ts`
66
+
67
+ ### Step 5: Run Tests
68
+
69
+ **UI Tests:**
70
+ ```bash
71
+ npx playwright test tests/e2e/qa/ --reporter=list
72
+ ```
73
+
74
+ **API Tests:**
75
+ ```bash
76
+ npx vitest run tests/integration/qa/ --reporter=verbose
77
+ # (or equivalent for the project's test runner)
78
+ ```
79
+
80
+ Capture the test output for the report.
81
+
82
+ ### Step 6: Collect Artifacts
83
+
84
+ Move Playwright artifacts (screenshots, videos) to `qa-artifacts/` in the project root:
85
+ ```bash
86
+ mkdir -p qa-artifacts
87
+ # Copy from playwright-report/ or test-results/ to qa-artifacts/
88
+ ```
89
+
90
+ ### Step 7: Commit and Push
91
+
92
+ ```bash
93
+ git add tests/e2e/qa/ tests/integration/qa/ qa-artifacts/ || true
94
+ git add -A tests/*/qa/ qa-artifacts/ || true
95
+ git commit -m "test(qa): add automated QA tests for PR changes
96
+
97
+ - Generated by Night Watch QA agent
98
+ - <UI tests: X passing, Y failing | No UI tests>
99
+ - <API tests: X passing, Y failing | No API tests>
100
+ - Artifacts: <screenshots, videos | screenshots | videos | none>
101
+
102
+ Co-Authored-By: Claude <noreply@anthropic.com>"
103
+ git push origin HEAD
104
+ ```
105
+
106
+ ### Step 8: Comment on PR
107
+
108
+ Post a comment on the PR with results. Use the `<!-- night-watch-qa-marker -->` HTML comment for idempotency detection.
109
+
110
+ ```bash
111
+ gh pr comment <PR_NUMBER> --body "<!-- night-watch-qa-marker -->
112
+ ## Night Watch QA Report
113
+
114
+ ### Changes Classification
115
+ - **Type**: <UI | API | UI + API>
116
+ - **Files changed**: <count>
117
+
118
+ ### Test Results
119
+
120
+ <If UI tests>
121
+ #### UI Tests (Playwright)
122
+ - **Status**: <All passing | X of Y failing>
123
+ - **Tests**: <count> test(s) in <count> file(s)
124
+
125
+ <If screenshots captured>
126
+ #### Screenshots
127
+ <For each screenshot>
128
+ ![<description>](../blob/<branch>/qa-artifacts/<filename>)
129
+ </For>
130
+ </If>
131
+
132
+ <If video captured>
133
+ #### Video Recording
134
+ Video artifact committed to \`qa-artifacts/\` — view in the PR's file changes.
135
+ </If>
136
+ </If>
137
+
138
+ <If API tests>
139
+ #### API Tests
140
+ - **Status**: <All passing | X of Y failing>
141
+ - **Tests**: <count> test(s) in <count> file(s)
142
+ </If>
143
+
144
+ <If no tests generated>
145
+ **QA: No tests needed for this PR** — changes are trivial (docs, config, comments).
146
+ </If>
147
+
148
+ ---
149
+ *Night Watch QA Agent*"
150
+ ```
151
+
152
+ ### Important Rules
153
+ - Process each PR **once** per run. Do NOT loop or retry after pushing.
154
+ - Do NOT modify existing project tests — only add new files in `qa/` subdirectories.
155
+ - If tests fail, still commit and report — the failures are useful information.
156
+ - Keep test files self-contained and independent from each other.
157
+ - Follow the project's existing code style and conventions (check CLAUDE.md, package.json scripts, tsconfig).
@@ -13,5 +13,18 @@
13
13
  "minReviewScore": 80,
14
14
  "maxLogSize": 524288,
15
15
  "cronSchedule": "0 0-21 * * *",
16
- "reviewerSchedule": "0 0,3,6,9,12,15,18,21 * * *"
16
+ "reviewerSchedule": "0 0,3,6,9,12,15,18,21 * * *",
17
+ "autoMerge": false,
18
+ "autoMergeMethod": "squash",
19
+ "fallbackOnRateLimit": false,
20
+ "claudeModel": "sonnet",
21
+ "qa": {
22
+ "enabled": true,
23
+ "schedule": "30 1,7,13,19 * * *",
24
+ "maxRuntime": 3600,
25
+ "branchPatterns": [],
26
+ "artifacts": "both",
27
+ "skipLabel": "skip-qa",
28
+ "autoInstallPlaywright": true
29
+ }
17
30
  }