factory-factory 0.4.1 → 0.4.3

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 (839) hide show
  1. package/README.md +1 -1
  2. package/dist/client/assets/abnfDiagram-VRR7QNED-Bu9-2m-t.js +1 -0
  3. package/dist/client/assets/arc-Dh_ay4bc.js +1 -0
  4. package/dist/client/assets/architectureDiagram-ZJ3FMSHR-V4AJKU23.js +36 -0
  5. package/dist/client/assets/blockDiagram-677ZJIJ3-unJzynY2.js +132 -0
  6. package/dist/client/assets/{c4Diagram-AAUBKEIU-CT8hJB-h.js → c4Diagram-LMCZKHZV-De_-3fVv.js} +1 -1
  7. package/dist/client/assets/channel-8o5vp5Nl.js +1 -0
  8. package/dist/client/assets/{chunk-QZHKN3VN-Ce3Q_vrs.js → chunk-2Q5K7J3B-CdZ0ANE_.js} +1 -1
  9. package/dist/client/assets/{chunk-ND2GUHAM-Qhi4WqzZ.js → chunk-32BRIVSS-BzFpxDmT.js} +1 -1
  10. package/dist/client/assets/{chunk-FMBD7UC4-B4C3KvLe.js → chunk-5VM5RSS4-8_Qj_VeY.js} +1 -1
  11. package/dist/client/assets/chunk-EX3LRPZG-Chc6HGsz.js +231 -0
  12. package/dist/client/assets/{chunk-4BX2VUAB-km6NpEMz.js → chunk-JWPE2WC7-CFeGNH2a.js} +1 -1
  13. package/dist/client/assets/chunk-MOJQB5TN-DY39i_O8.js +88 -0
  14. package/dist/client/assets/chunk-RYQCIY6F-C3bbEdeB.js +1 -0
  15. package/dist/client/assets/{chunk-727SXJPM-Bp-ts2at.js → chunk-V7JOEXUC-BpNgC7Ah.js} +5 -5
  16. package/dist/client/assets/{chunk-2J33WTMH-B0h8q8fD.js → chunk-VR4S4FIN-BKsk7moo.js} +1 -1
  17. package/dist/client/assets/{chunk-55IACEB6-COUWt3oA.js → chunk-XXDRQBXY-D7Pgr1uy.js} +1 -1
  18. package/dist/client/assets/classDiagram-OUVF2IWQ-BNBqP_D4.js +1 -0
  19. package/dist/client/assets/classDiagram-v2-EOCWNBFH-BNBqP_D4.js +1 -0
  20. package/dist/client/assets/{cose-bilkent-S5V4N54A-D6QofwFq.js → cose-bilkent-JH36ORCC-DvmyUiBK.js} +1 -1
  21. package/dist/client/assets/cynefin-VYW2F7L2-DyPz67uy.js +166 -0
  22. package/dist/client/assets/cynefinDiagram-TSTJHNR4-CxZzWly_.js +62 -0
  23. package/dist/client/assets/cytoscape.esm-D3_iZ_3b.js +321 -0
  24. package/dist/client/assets/dagre-VKFMJZFB-BkNT_0vs.js +4 -0
  25. package/dist/client/assets/{diagram-KO2AKTUF-B9ABz-Wk.js → diagram-FQU43EPY-C9c41Tpz.js} +3 -3
  26. package/dist/client/assets/diagram-G47NLZAW-CogAwMLq.js +24 -0
  27. package/dist/client/assets/diagram-NH7WQ7WH-jtYr2rjE.js +24 -0
  28. package/dist/client/assets/diagram-OA4YK3LP-CfCfCJfY.js +30 -0
  29. package/dist/client/assets/diagram-WEI45ONY-C3m0dfDy.js +41 -0
  30. package/dist/client/assets/ebnfDiagram-CCIWWBDH-Dr4BkxJz.js +1 -0
  31. package/dist/client/assets/erDiagram-Q63AITRT-BbDab_v6.js +85 -0
  32. package/dist/client/assets/flowDiagram-23GEKE2U-DOeJX8aU.js +156 -0
  33. package/dist/client/assets/ganttDiagram-NO4QXBWP-BpgtL3Q5.js +292 -0
  34. package/dist/client/assets/gitGraphDiagram-IHSO6WYX-DTDPlnSN.js +106 -0
  35. package/dist/client/assets/{graph--OzhPTMs.js → graph-DOmOIIwC.js} +1 -1
  36. package/dist/client/assets/index-DuSjh2zd.js +689 -0
  37. package/dist/client/assets/index-dP7LJD2L.css +1 -0
  38. package/dist/client/assets/infoDiagram-FWYZ7A6U-CHKlHAG9.js +2 -0
  39. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BLrvV5ke.js → ishikawaDiagram-FXEZZL3T-B7EQbtqY.js} +5 -5
  40. package/dist/client/assets/{journeyDiagram-JHISSGLW-B2-TMwJI.js → journeyDiagram-5HDEW3XC-DTUiiqrL.js} +3 -3
  41. package/dist/client/assets/{kanban-definition-UN3LZRKU-B5mGKgYF.js → kanban-definition-HUTT4EX6-eObIHBDx.js} +20 -20
  42. package/dist/client/assets/katex-HP8lGamR.js +257 -0
  43. package/dist/client/assets/layout-D-LzfAck.js +1 -0
  44. package/dist/client/assets/{linear-ConE9euY.js → linear-DQu4w17X.js} +1 -1
  45. package/dist/client/assets/map-DxJ2ADlA.js +1 -0
  46. package/dist/client/assets/{mindmap-definition-RKZ34NQL-B0BaMk8D.js → mindmap-definition-LN4V7U3C-XqlKfmJa.js} +3 -3
  47. package/dist/client/assets/{mobile-baseline-DWCt7ZGJ.js → mobile-baseline-v5lnTluf.js} +1 -1
  48. package/dist/client/assets/pegDiagram-2B236MQR-By2J0vHR.js +1 -0
  49. package/dist/client/assets/pieDiagram-ENE6RG2P-DWliRlHi.js +39 -0
  50. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-DDbeggF4.js → quadrantDiagram-ABIIQ3AL-DxxsQgGe.js} +3 -3
  51. package/dist/client/assets/railroadDiagram-RFXS5EU6-CRjYLslW.js +1 -0
  52. package/dist/client/assets/{requirementDiagram-4Y6WPE33-Cc3ozz7U.js → requirementDiagram-TGXJPOKE-CuZgujay.js} +1 -1
  53. package/dist/client/assets/sankeyDiagram-HTMAVEWB-DhxT75Go.js +40 -0
  54. package/dist/client/assets/sequenceDiagram-DBY2YBRQ-Tz8RVPsp.js +162 -0
  55. package/dist/client/assets/sizeCapture-X5ZJPWSS-BME47q1I.js +1 -0
  56. package/dist/client/assets/stateDiagram-2N3HPSRC-DQoKLjSj.js +1 -0
  57. package/dist/client/assets/stateDiagram-v2-6OUMAXLB-BnQzcOjM.js +1 -0
  58. package/dist/client/assets/swimlanes-5IMT3BWC-DZ78RZi9.js +2 -0
  59. package/dist/client/assets/swimlanesDiagram-G3AALYLV-mI62K_37.js +8 -0
  60. package/dist/client/assets/{terminal-instance-CDKJdDaO.js → terminal-instance-CbXOfRoa.js} +1 -1
  61. package/dist/client/assets/{timeline-definition-PNZ67QCA-CyxBqgqv.js → timeline-definition-FHXFAJF6-DS_K1N-M.js} +3 -3
  62. package/dist/client/assets/vennDiagram-L72KCM5P-D9evf7U9.js +34 -0
  63. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CjJBpd3P.js → wardleyDiagram-EHGQE667-8-WkkQfu.js} +4 -4
  64. package/dist/client/assets/xychartDiagram-FW5EYKEG-gEXjpSMB.js +7 -0
  65. package/dist/client/index.html +2 -2
  66. package/dist/client/logo.png +0 -0
  67. package/dist/client/logo.sips.png +0 -0
  68. package/dist/prisma/generated/browser.d.ts +4 -0
  69. package/dist/prisma/generated/browser.d.ts.map +1 -1
  70. package/dist/prisma/generated/client.d.ts +4 -0
  71. package/dist/prisma/generated/client.d.ts.map +1 -1
  72. package/dist/prisma/generated/commonInputTypes.d.ts +88 -148
  73. package/dist/prisma/generated/commonInputTypes.d.ts.map +1 -1
  74. package/dist/prisma/generated/enums.d.ts +0 -6
  75. package/dist/prisma/generated/enums.d.ts.map +1 -1
  76. package/dist/prisma/generated/enums.js +0 -5
  77. package/dist/prisma/generated/enums.js.map +1 -1
  78. package/dist/prisma/generated/internal/class.d.ts +16 -2
  79. package/dist/prisma/generated/internal/class.d.ts.map +1 -1
  80. package/dist/prisma/generated/internal/class.js +6 -6
  81. package/dist/prisma/generated/internal/class.js.map +1 -1
  82. package/dist/prisma/generated/internal/prismaNamespace.d.ts +371 -47
  83. package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
  84. package/dist/prisma/generated/internal/prismaNamespace.js +52 -37
  85. package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
  86. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +53 -34
  87. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
  88. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +50 -35
  89. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  90. package/dist/prisma/generated/models/Workspace.d.ts +1017 -2537
  91. package/dist/prisma/generated/models/Workspace.d.ts.map +1 -1
  92. package/dist/prisma/generated/models/WorkspaceAutoIteration.d.ts +524 -0
  93. package/dist/prisma/generated/models/WorkspaceAutoIteration.d.ts.map +1 -0
  94. package/dist/prisma/generated/models/WorkspaceAutoIteration.js +2 -0
  95. package/dist/prisma/generated/models/WorkspaceAutoIteration.js.map +1 -0
  96. package/dist/prisma/generated/models/WorkspacePR.d.ts +858 -0
  97. package/dist/prisma/generated/models/WorkspacePR.d.ts.map +1 -0
  98. package/dist/prisma/generated/models/WorkspacePR.js +2 -0
  99. package/dist/prisma/generated/models/WorkspacePR.js.map +1 -0
  100. package/dist/prisma/generated/models/WorkspaceRatchet.d.ts +625 -0
  101. package/dist/prisma/generated/models/WorkspaceRatchet.d.ts.map +1 -0
  102. package/dist/prisma/generated/models/WorkspaceRatchet.js +2 -0
  103. package/dist/prisma/generated/models/WorkspaceRatchet.js.map +1 -0
  104. package/dist/prisma/generated/models/WorkspaceRunScript.d.ts +631 -0
  105. package/dist/prisma/generated/models/WorkspaceRunScript.d.ts.map +1 -0
  106. package/dist/prisma/generated/models/WorkspaceRunScript.js +2 -0
  107. package/dist/prisma/generated/models/WorkspaceRunScript.js.map +1 -0
  108. package/dist/prisma/generated/models.d.ts +4 -0
  109. package/dist/prisma/generated/models.d.ts.map +1 -1
  110. package/dist/scripts/check-fk-indexes.d.ts +2 -0
  111. package/dist/scripts/check-fk-indexes.d.ts.map +1 -0
  112. package/dist/scripts/check-fk-indexes.js +143 -0
  113. package/dist/scripts/check-fk-indexes.js.map +1 -0
  114. package/dist/src/backend/app-context.d.ts +4 -1
  115. package/dist/src/backend/app-context.d.ts.map +1 -1
  116. package/dist/src/backend/app-context.js +8 -6
  117. package/dist/src/backend/app-context.js.map +1 -1
  118. package/dist/src/backend/interceptors/auto-branch-rename.d.ts +19 -0
  119. package/dist/src/backend/interceptors/auto-branch-rename.d.ts.map +1 -0
  120. package/dist/src/backend/interceptors/auto-branch-rename.js +76 -0
  121. package/dist/src/backend/interceptors/auto-branch-rename.js.map +1 -0
  122. package/dist/src/backend/interceptors/branch-naming.interceptor.d.ts +4 -0
  123. package/dist/src/backend/interceptors/branch-naming.interceptor.d.ts.map +1 -0
  124. package/dist/src/backend/interceptors/branch-naming.interceptor.js +391 -0
  125. package/dist/src/backend/interceptors/branch-naming.interceptor.js.map +1 -0
  126. package/dist/src/backend/interceptors/branch-naming.interceptor.test.d.ts +2 -0
  127. package/dist/src/backend/interceptors/branch-naming.interceptor.test.d.ts.map +1 -0
  128. package/dist/src/backend/interceptors/branch-naming.interceptor.test.js +780 -0
  129. package/dist/src/backend/interceptors/branch-naming.interceptor.test.js.map +1 -0
  130. package/dist/src/backend/interceptors/branch-rename.utils.d.ts +1 -1
  131. package/dist/src/backend/interceptors/branch-rename.utils.d.ts.map +1 -1
  132. package/dist/src/backend/interceptors/branch-rename.utils.js +10 -14
  133. package/dist/src/backend/interceptors/branch-rename.utils.js.map +1 -1
  134. package/dist/src/backend/interceptors/index.d.ts.map +1 -1
  135. package/dist/src/backend/interceptors/index.js +2 -6
  136. package/dist/src/backend/interceptors/index.js.map +1 -1
  137. package/dist/src/backend/lib/application-error.d.ts +6 -1
  138. package/dist/src/backend/lib/application-error.d.ts.map +1 -1
  139. package/dist/src/backend/lib/application-error.js +2 -0
  140. package/dist/src/backend/lib/application-error.js.map +1 -1
  141. package/dist/src/backend/lib/application-error.test.js +10 -0
  142. package/dist/src/backend/lib/application-error.test.js.map +1 -1
  143. package/dist/src/backend/lib/workspace-derived-state.d.ts +7 -16
  144. package/dist/src/backend/lib/workspace-derived-state.d.ts.map +1 -1
  145. package/dist/src/backend/lib/workspace-derived-state.js +21 -24
  146. package/dist/src/backend/lib/workspace-derived-state.js.map +1 -1
  147. package/dist/src/backend/lib/workspace-derived-state.test.js +37 -50
  148. package/dist/src/backend/lib/workspace-derived-state.test.js.map +1 -1
  149. package/dist/src/backend/orchestration/data-backup.service.d.ts.map +1 -1
  150. package/dist/src/backend/orchestration/data-backup.service.js +103 -53
  151. package/dist/src/backend/orchestration/data-backup.service.js.map +1 -1
  152. package/dist/src/backend/orchestration/data-backup.service.test.js +187 -47
  153. package/dist/src/backend/orchestration/data-backup.service.test.js.map +1 -1
  154. package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts +7 -5
  155. package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts.map +1 -1
  156. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js +118 -62
  157. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js.map +1 -1
  158. package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js +262 -104
  159. package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js.map +1 -1
  160. package/dist/src/backend/orchestration/event-coalescer.integration.test.js +7 -16
  161. package/dist/src/backend/orchestration/event-coalescer.integration.test.js.map +1 -1
  162. package/dist/src/backend/orchestration/event-collector-lifecycle.integration.test.js +2 -2
  163. package/dist/src/backend/orchestration/event-collector-lifecycle.integration.test.js.map +1 -1
  164. package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts +6 -6
  165. package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts.map +1 -1
  166. package/dist/src/backend/orchestration/event-collector.orchestrator.js +20 -36
  167. package/dist/src/backend/orchestration/event-collector.orchestrator.js.map +1 -1
  168. package/dist/src/backend/orchestration/event-collector.orchestrator.test.js +80 -27
  169. package/dist/src/backend/orchestration/event-collector.orchestrator.test.js.map +1 -1
  170. package/dist/src/backend/orchestration/reconciliation.service.d.ts +4 -3
  171. package/dist/src/backend/orchestration/reconciliation.service.d.ts.map +1 -1
  172. package/dist/src/backend/orchestration/reconciliation.service.js +26 -38
  173. package/dist/src/backend/orchestration/reconciliation.service.js.map +1 -1
  174. package/dist/src/backend/orchestration/reconciliation.service.test.js +3 -3
  175. package/dist/src/backend/orchestration/reconciliation.service.test.js.map +1 -1
  176. package/dist/src/backend/orchestration/scheduler.service.d.ts +4 -3
  177. package/dist/src/backend/orchestration/scheduler.service.d.ts.map +1 -1
  178. package/dist/src/backend/orchestration/scheduler.service.js +40 -43
  179. package/dist/src/backend/orchestration/scheduler.service.js.map +1 -1
  180. package/dist/src/backend/orchestration/scheduler.service.test.js +52 -10
  181. package/dist/src/backend/orchestration/scheduler.service.test.js.map +1 -1
  182. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts +5 -5
  183. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts.map +1 -1
  184. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js +24 -61
  185. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js.map +1 -1
  186. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.test.js +36 -5
  187. package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.test.js.map +1 -1
  188. package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts +7 -41
  189. package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts.map +1 -1
  190. package/dist/src/backend/orchestration/workspace-archive.orchestrator.js +3 -3
  191. package/dist/src/backend/orchestration/workspace-archive.orchestrator.js.map +1 -1
  192. package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js +14 -16
  193. package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js.map +1 -1
  194. package/dist/src/backend/orchestration/workspace-init.orchestrator.js +3 -3
  195. package/dist/src/backend/orchestration/workspace-init.orchestrator.js.map +1 -1
  196. package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js +18 -18
  197. package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js.map +1 -1
  198. package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.d.ts.map +1 -1
  199. package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.js +8 -1
  200. package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.js.map +1 -1
  201. package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.test.js +23 -0
  202. package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.test.js.map +1 -1
  203. package/dist/src/backend/routers/websocket/chat.handler.d.ts.map +1 -1
  204. package/dist/src/backend/routers/websocket/chat.handler.js +10 -6
  205. package/dist/src/backend/routers/websocket/chat.handler.js.map +1 -1
  206. package/dist/src/backend/routers/websocket/chat.handler.test.js +37 -11
  207. package/dist/src/backend/routers/websocket/chat.handler.test.js.map +1 -1
  208. package/dist/src/backend/routers/websocket/index.d.ts +1 -2
  209. package/dist/src/backend/routers/websocket/index.d.ts.map +1 -1
  210. package/dist/src/backend/routers/websocket/index.js +1 -2
  211. package/dist/src/backend/routers/websocket/index.js.map +1 -1
  212. package/dist/src/backend/routers/websocket/log-stream-dev.handler.test.d.ts +2 -0
  213. package/dist/src/backend/routers/websocket/log-stream-dev.handler.test.d.ts.map +1 -0
  214. package/dist/src/backend/routers/websocket/{dev-logs.handler.test.js → log-stream-dev.handler.test.js} +2 -2
  215. package/dist/src/backend/routers/websocket/log-stream-dev.handler.test.js.map +1 -0
  216. package/dist/src/backend/routers/websocket/log-stream-post-run.handler.test.d.ts +2 -0
  217. package/dist/src/backend/routers/websocket/log-stream-post-run.handler.test.d.ts.map +1 -0
  218. package/dist/src/backend/routers/websocket/{post-run-logs.handler.test.js → log-stream-post-run.handler.test.js} +2 -2
  219. package/dist/src/backend/routers/websocket/log-stream-post-run.handler.test.js.map +1 -0
  220. package/dist/src/backend/routers/websocket/log-stream.handler.d.ts +8 -0
  221. package/dist/src/backend/routers/websocket/log-stream.handler.d.ts.map +1 -0
  222. package/dist/src/backend/routers/websocket/log-stream.handler.js +35 -0
  223. package/dist/src/backend/routers/websocket/log-stream.handler.js.map +1 -0
  224. package/dist/src/backend/routers/websocket/terminal.handler.d.ts.map +1 -1
  225. package/dist/src/backend/routers/websocket/terminal.handler.js +4 -2
  226. package/dist/src/backend/routers/websocket/terminal.handler.js.map +1 -1
  227. package/dist/src/backend/routers/websocket/terminal.handler.test.js +37 -0
  228. package/dist/src/backend/routers/websocket/terminal.handler.test.js.map +1 -1
  229. package/dist/src/backend/routers/websocket/websocket.integration.test.js +6 -10
  230. package/dist/src/backend/routers/websocket/websocket.integration.test.js.map +1 -1
  231. package/dist/src/backend/server.d.ts.map +1 -1
  232. package/dist/src/backend/server.js +12 -3
  233. package/dist/src/backend/server.js.map +1 -1
  234. package/dist/src/backend/server.upgrade.test.js +35 -6
  235. package/dist/src/backend/server.upgrade.test.js.map +1 -1
  236. package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.test.js +15 -0
  237. package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.test.js.map +1 -1
  238. package/dist/src/backend/services/auto-iteration/service/git-ops.d.ts.map +1 -1
  239. package/dist/src/backend/services/auto-iteration/service/git-ops.integration.test.d.ts +2 -0
  240. package/dist/src/backend/services/auto-iteration/service/git-ops.integration.test.d.ts.map +1 -0
  241. package/dist/src/backend/services/auto-iteration/service/git-ops.integration.test.js +86 -0
  242. package/dist/src/backend/services/auto-iteration/service/git-ops.integration.test.js.map +1 -0
  243. package/dist/src/backend/services/auto-iteration/service/git-ops.js +37 -2
  244. package/dist/src/backend/services/auto-iteration/service/git-ops.js.map +1 -1
  245. package/dist/src/backend/services/auto-iteration/service/test-runner.service.d.ts.map +1 -1
  246. package/dist/src/backend/services/auto-iteration/service/test-runner.service.js +9 -8
  247. package/dist/src/backend/services/auto-iteration/service/test-runner.service.js.map +1 -1
  248. package/dist/src/backend/services/auto-iteration/service/test-runner.service.test.d.ts +2 -0
  249. package/dist/src/backend/services/auto-iteration/service/test-runner.service.test.d.ts.map +1 -0
  250. package/dist/src/backend/services/auto-iteration/service/test-runner.service.test.js +80 -0
  251. package/dist/src/backend/services/auto-iteration/service/test-runner.service.test.js.map +1 -0
  252. package/dist/src/backend/services/check-single-writer.test.js +303 -32
  253. package/dist/src/backend/services/check-single-writer.test.js.map +1 -1
  254. package/dist/src/backend/services/constants.d.ts +1 -0
  255. package/dist/src/backend/services/constants.d.ts.map +1 -1
  256. package/dist/src/backend/services/constants.js +1 -0
  257. package/dist/src/backend/services/constants.js.map +1 -1
  258. package/dist/src/backend/services/env-schemas.d.ts +46 -46
  259. package/dist/src/backend/services/github/service/bridges.d.ts +6 -5
  260. package/dist/src/backend/services/github/service/bridges.d.ts.map +1 -1
  261. package/dist/src/backend/services/github/service/github-cli/mappers.d.ts +5 -2
  262. package/dist/src/backend/services/github/service/github-cli/mappers.d.ts.map +1 -1
  263. package/dist/src/backend/services/github/service/github-cli/mappers.js.map +1 -1
  264. package/dist/src/backend/services/github/service/github-cli/schemas.d.ts +4 -4
  265. package/dist/src/backend/services/github/service/github-cli.service.d.ts +5 -1
  266. package/dist/src/backend/services/github/service/github-cli.service.d.ts.map +1 -1
  267. package/dist/src/backend/services/github/service/github-cli.service.js.map +1 -1
  268. package/dist/src/backend/services/github/service/index.d.ts +2 -3
  269. package/dist/src/backend/services/github/service/index.d.ts.map +1 -1
  270. package/dist/src/backend/services/github/service/index.js +2 -2
  271. package/dist/src/backend/services/github/service/index.js.map +1 -1
  272. package/dist/src/backend/services/github/service/pr-fetch-coordinator.d.ts +33 -0
  273. package/dist/src/backend/services/github/service/pr-fetch-coordinator.d.ts.map +1 -0
  274. package/dist/src/backend/services/github/service/{pr-fetch-registry.js → pr-fetch-coordinator.js} +80 -69
  275. package/dist/src/backend/services/github/service/pr-fetch-coordinator.js.map +1 -0
  276. package/dist/src/backend/services/github/service/pr-fetch-coordinator.test.d.ts +2 -0
  277. package/dist/src/backend/services/github/service/pr-fetch-coordinator.test.d.ts.map +1 -0
  278. package/dist/src/backend/services/github/service/pr-fetch-coordinator.test.js +222 -0
  279. package/dist/src/backend/services/github/service/pr-fetch-coordinator.test.js.map +1 -0
  280. package/dist/src/backend/services/github/service/pr-snapshot.service.d.ts +12 -11
  281. package/dist/src/backend/services/github/service/pr-snapshot.service.d.ts.map +1 -1
  282. package/dist/src/backend/services/github/service/pr-snapshot.service.js +23 -22
  283. package/dist/src/backend/services/github/service/pr-snapshot.service.js.map +1 -1
  284. package/dist/src/backend/services/github/service/pr-snapshot.service.test.js +134 -75
  285. package/dist/src/backend/services/github/service/pr-snapshot.service.test.js.map +1 -1
  286. package/dist/src/backend/services/job-runner.service.d.ts +24 -0
  287. package/dist/src/backend/services/job-runner.service.d.ts.map +1 -0
  288. package/dist/src/backend/services/job-runner.service.js +168 -0
  289. package/dist/src/backend/services/job-runner.service.js.map +1 -0
  290. package/dist/src/backend/services/job-runner.service.test.d.ts +2 -0
  291. package/dist/src/backend/services/job-runner.service.test.d.ts.map +1 -0
  292. package/dist/src/backend/services/job-runner.service.test.js +498 -0
  293. package/dist/src/backend/services/job-runner.service.test.js.map +1 -0
  294. package/dist/src/backend/services/periodic-task/service/periodic-task.service.d.ts +8 -11
  295. package/dist/src/backend/services/periodic-task/service/periodic-task.service.d.ts.map +1 -1
  296. package/dist/src/backend/services/periodic-task/service/periodic-task.service.js +28 -50
  297. package/dist/src/backend/services/periodic-task/service/periodic-task.service.js.map +1 -1
  298. package/dist/src/backend/services/port.service.d.ts.map +1 -1
  299. package/dist/src/backend/services/port.service.js +4 -0
  300. package/dist/src/backend/services/port.service.js.map +1 -1
  301. package/dist/src/backend/services/port.service.test.js +9 -0
  302. package/dist/src/backend/services/port.service.test.js.map +1 -1
  303. package/dist/src/backend/services/ratchet/service/bridges.d.ts +25 -7
  304. package/dist/src/backend/services/ratchet/service/bridges.d.ts.map +1 -1
  305. package/dist/src/backend/services/ratchet/service/fixer-session.service.test.js +1 -0
  306. package/dist/src/backend/services/ratchet/service/fixer-session.service.test.js.map +1 -1
  307. package/dist/src/backend/services/ratchet/service/ratchet-active-session.helpers.d.ts.map +1 -1
  308. package/dist/src/backend/services/ratchet/service/ratchet-active-session.helpers.js +11 -10
  309. package/dist/src/backend/services/ratchet/service/ratchet-active-session.helpers.js.map +1 -1
  310. package/dist/src/backend/services/ratchet/service/ratchet-decision-logging.helpers.d.ts +1 -1
  311. package/dist/src/backend/services/ratchet/service/ratchet-decision-logging.helpers.js +1 -1
  312. package/dist/src/backend/services/ratchet/service/ratchet-decision-logging.helpers.js.map +1 -1
  313. package/dist/src/backend/services/ratchet/service/ratchet-fixer-dispatch.helpers.d.ts.map +1 -1
  314. package/dist/src/backend/services/ratchet/service/ratchet-fixer-dispatch.helpers.js +8 -3
  315. package/dist/src/backend/services/ratchet/service/ratchet-fixer-dispatch.helpers.js.map +1 -1
  316. package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.d.ts +1 -1
  317. package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.d.ts.map +1 -1
  318. package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.js +103 -95
  319. package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.js.map +1 -1
  320. package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.test.js +36 -22
  321. package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.test.js.map +1 -1
  322. package/dist/src/backend/services/ratchet/service/ratchet.service.d.ts +8 -8
  323. package/dist/src/backend/services/ratchet/service/ratchet.service.d.ts.map +1 -1
  324. package/dist/src/backend/services/ratchet/service/ratchet.service.js +87 -136
  325. package/dist/src/backend/services/ratchet/service/ratchet.service.js.map +1 -1
  326. package/dist/src/backend/services/ratchet/service/ratchet.service.test.js +571 -272
  327. package/dist/src/backend/services/ratchet/service/ratchet.service.test.js.map +1 -1
  328. package/dist/src/backend/services/ratchet/service/ratchet.types.d.ts +3 -1
  329. package/dist/src/backend/services/ratchet/service/ratchet.types.d.ts.map +1 -1
  330. package/dist/src/backend/services/registry.d.ts +6 -2
  331. package/dist/src/backend/services/registry.d.ts.map +1 -1
  332. package/dist/src/backend/services/registry.js +17 -1
  333. package/dist/src/backend/services/registry.js.map +1 -1
  334. package/dist/src/backend/services/resources.integration.test.js +73 -45
  335. package/dist/src/backend/services/resources.integration.test.js.map +1 -1
  336. package/dist/src/backend/services/run-script/service/run-script-proxy.service.d.ts +1 -0
  337. package/dist/src/backend/services/run-script/service/run-script-proxy.service.d.ts.map +1 -1
  338. package/dist/src/backend/services/run-script/service/run-script-proxy.service.js +25 -2
  339. package/dist/src/backend/services/run-script/service/run-script-proxy.service.js.map +1 -1
  340. package/dist/src/backend/services/run-script/service/run-script-proxy.service.test.js +124 -6
  341. package/dist/src/backend/services/run-script/service/run-script-proxy.service.test.js.map +1 -1
  342. package/dist/src/backend/services/run-script/service/run-script-state-machine.service.d.ts.map +1 -1
  343. package/dist/src/backend/services/run-script/service/run-script-state-machine.service.js.map +1 -1
  344. package/dist/src/backend/services/run-script/service/run-script-state-machine.service.test.js +125 -125
  345. package/dist/src/backend/services/run-script/service/run-script-state-machine.service.test.js.map +1 -1
  346. package/dist/src/backend/services/run-script/service/startup-script.service.d.ts.map +1 -1
  347. package/dist/src/backend/services/run-script/service/startup-script.service.js +20 -5
  348. package/dist/src/backend/services/run-script/service/startup-script.service.js.map +1 -1
  349. package/dist/src/backend/services/run-script/service/startup-script.service.test.js +95 -1
  350. package/dist/src/backend/services/run-script/service/startup-script.service.test.js.map +1 -1
  351. package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.d.ts.map +1 -1
  352. package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.js +5 -0
  353. package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.js.map +1 -1
  354. package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.test.js +39 -6
  355. package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.test.js.map +1 -1
  356. package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.d.ts +0 -3
  357. package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.d.ts.map +1 -1
  358. package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.js +66 -26
  359. package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.js.map +1 -1
  360. package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.test.js +194 -6
  361. package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.test.js.map +1 -1
  362. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.d.ts.map +1 -1
  363. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.js +4 -4
  364. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.js.map +1 -1
  365. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.test.js +4 -2
  366. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.test.js.map +1 -1
  367. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/permission-response.handler.d.ts +2 -2
  368. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/permission-response.handler.d.ts.map +1 -1
  369. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/permission-response.handler.js +2 -2
  370. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/permission-response.handler.js.map +1 -1
  371. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/permission-response.handler.test.js +10 -25
  372. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/permission-response.handler.test.js.map +1 -1
  373. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-config-option.handler.d.ts.map +1 -1
  374. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-config-option.handler.js +10 -2
  375. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-config-option.handler.js.map +1 -1
  376. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-config-option.handler.test.js +41 -2
  377. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-config-option.handler.test.js.map +1 -1
  378. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-model.handler.d.ts +2 -2
  379. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-model.handler.d.ts.map +1 -1
  380. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-model.handler.js +4 -4
  381. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-model.handler.js.map +1 -1
  382. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-model.handler.test.js +1 -4
  383. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-model.handler.test.js.map +1 -1
  384. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-thinking-budget.handler.js +2 -2
  385. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-thinking-budget.handler.js.map +1 -1
  386. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-thinking-budget.handler.test.js +2 -2
  387. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/set-thinking-budget.handler.test.js.map +1 -1
  388. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/start.handler.js +2 -2
  389. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/start.handler.js.map +1 -1
  390. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/start.handler.test.js +2 -2
  391. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/start.handler.test.js.map +1 -1
  392. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.js +2 -2
  393. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.js.map +1 -1
  394. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.test.js +2 -2
  395. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.test.js.map +1 -1
  396. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/user-input.handler.d.ts +3 -2
  397. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/user-input.handler.d.ts.map +1 -1
  398. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/user-input.handler.js +2 -2
  399. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/user-input.handler.js.map +1 -1
  400. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/user-input.handler.test.js +17 -20
  401. package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/user-input.handler.test.js.map +1 -1
  402. package/dist/src/backend/services/session/service/chat/chat-message-handlers/image-format-validation.d.ts +7 -0
  403. package/dist/src/backend/services/session/service/chat/chat-message-handlers/image-format-validation.d.ts.map +1 -0
  404. package/dist/src/backend/services/session/service/chat/chat-message-handlers/image-format-validation.js +466 -0
  405. package/dist/src/backend/services/session/service/chat/chat-message-handlers/image-format-validation.js.map +1 -0
  406. package/dist/src/backend/services/session/service/chat/chat-message-handlers/registry.d.ts.map +1 -1
  407. package/dist/src/backend/services/session/service/chat/chat-message-handlers/registry.js +15 -6
  408. package/dist/src/backend/services/session/service/chat/chat-message-handlers/registry.js.map +1 -1
  409. package/dist/src/backend/services/session/service/chat/chat-message-handlers/types.d.ts +12 -3
  410. package/dist/src/backend/services/session/service/chat/chat-message-handlers/types.d.ts.map +1 -1
  411. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.d.ts.map +1 -1
  412. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js +24 -18
  413. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js.map +1 -1
  414. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.test.js +59 -16
  415. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.test.js.map +1 -1
  416. package/dist/src/backend/services/session/service/data/session-provider-resolver.service.test.js +1 -3
  417. package/dist/src/backend/services/session/service/data/session-provider-resolver.service.test.js.map +1 -1
  418. package/dist/src/backend/services/session/service/index.d.ts +6 -1
  419. package/dist/src/backend/services/session/service/index.d.ts.map +1 -1
  420. package/dist/src/backend/services/session/service/index.js +5 -1
  421. package/dist/src/backend/services/session/service/index.js.map +1 -1
  422. package/dist/src/backend/services/session/service/interceptor.bridge.d.ts.map +1 -1
  423. package/dist/src/backend/services/session/service/interceptor.bridge.js +47 -3
  424. package/dist/src/backend/services/session/service/interceptor.bridge.js.map +1 -1
  425. package/dist/src/backend/services/session/service/interceptor.bridge.test.d.ts +2 -0
  426. package/dist/src/backend/services/session/service/interceptor.bridge.test.d.ts.map +1 -0
  427. package/dist/src/backend/services/session/service/interceptor.bridge.test.js +83 -0
  428. package/dist/src/backend/services/session/service/interceptor.bridge.test.js.map +1 -0
  429. package/dist/src/backend/services/session/service/lifecycle/session-services.d.ts +16 -0
  430. package/dist/src/backend/services/session/service/lifecycle/session-services.d.ts.map +1 -0
  431. package/dist/src/backend/services/session/service/lifecycle/session-services.js +79 -0
  432. package/dist/src/backend/services/session/service/lifecycle/session-services.js.map +1 -0
  433. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.d.ts +4 -2
  434. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.d.ts.map +1 -1
  435. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js +6 -4
  436. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js.map +1 -1
  437. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.test.js +10 -11
  438. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.test.js.map +1 -1
  439. package/dist/src/backend/services/session/service/lifecycle/session.prompt.service.test.d.ts +2 -0
  440. package/dist/src/backend/services/session/service/lifecycle/session.prompt.service.test.d.ts.map +1 -0
  441. package/dist/src/backend/services/session/service/lifecycle/session.prompt.service.test.js +142 -0
  442. package/dist/src/backend/services/session/service/lifecycle/session.prompt.service.test.js.map +1 -0
  443. package/dist/src/backend/services/session/service/lifecycle/session.repository.d.ts +5 -2
  444. package/dist/src/backend/services/session/service/lifecycle/session.repository.d.ts.map +1 -1
  445. package/dist/src/backend/services/session/service/lifecycle/session.repository.js.map +1 -1
  446. package/dist/src/backend/services/session/service/lifecycle/session.repository.test.js.map +1 -1
  447. package/dist/src/backend/services/session/service/lifecycle/session.service.d.ts +16 -76
  448. package/dist/src/backend/services/session/service/lifecycle/session.service.d.ts.map +1 -1
  449. package/dist/src/backend/services/session/service/lifecycle/session.service.js +21 -215
  450. package/dist/src/backend/services/session/service/lifecycle/session.service.js.map +1 -1
  451. package/dist/src/backend/services/session/service/lifecycle/session.service.test.js +159 -66
  452. package/dist/src/backend/services/session/service/lifecycle/session.service.test.js.map +1 -1
  453. package/dist/src/backend/services/session/service/session-domain.service.d.ts +2 -0
  454. package/dist/src/backend/services/session/service/session-domain.service.d.ts.map +1 -1
  455. package/dist/src/backend/services/session/service/session-domain.service.js +25 -6
  456. package/dist/src/backend/services/session/service/session-domain.service.js.map +1 -1
  457. package/dist/src/backend/services/session/service/session-domain.service.test.js +47 -0
  458. package/dist/src/backend/services/session/service/session-domain.service.test.js.map +1 -1
  459. package/dist/src/backend/services/session/service/store/session-replay-builder.d.ts.map +1 -1
  460. package/dist/src/backend/services/session/service/store/session-replay-builder.js +2 -1
  461. package/dist/src/backend/services/session/service/store/session-replay-builder.js.map +1 -1
  462. package/dist/src/backend/services/session/service/store/session-store.types.d.ts +5 -1
  463. package/dist/src/backend/services/session/service/store/session-store.types.d.ts.map +1 -1
  464. package/dist/src/backend/services/settings/resources/data-backup.accessor.d.ts +10 -2
  465. package/dist/src/backend/services/settings/resources/data-backup.accessor.d.ts.map +1 -1
  466. package/dist/src/backend/services/settings/resources/data-backup.accessor.js +4 -1
  467. package/dist/src/backend/services/settings/resources/data-backup.accessor.js.map +1 -1
  468. package/dist/src/backend/services/settings/resources/user-settings.accessor.d.ts.map +1 -1
  469. package/dist/src/backend/services/settings/resources/user-settings.accessor.js +1 -0
  470. package/dist/src/backend/services/settings/resources/user-settings.accessor.js.map +1 -1
  471. package/dist/src/backend/services/settings/resources/user-settings.accessor.test.d.ts +2 -0
  472. package/dist/src/backend/services/settings/resources/user-settings.accessor.test.d.ts.map +1 -0
  473. package/dist/src/backend/services/settings/resources/user-settings.accessor.test.js +24 -0
  474. package/dist/src/backend/services/settings/resources/user-settings.accessor.test.js.map +1 -0
  475. package/dist/src/backend/services/terminal/service/terminal-session.service.d.ts +3 -37
  476. package/dist/src/backend/services/terminal/service/terminal-session.service.d.ts.map +1 -1
  477. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.d.ts +31 -0
  478. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.d.ts.map +1 -0
  479. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.js +80 -0
  480. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.js.map +1 -0
  481. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.test.d.ts +2 -0
  482. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.test.d.ts.map +1 -0
  483. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.test.js +171 -0
  484. package/dist/src/backend/services/workspace/resources/workspace-auto-iteration.accessor.test.js.map +1 -0
  485. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.d.ts +61 -0
  486. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.d.ts.map +1 -0
  487. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.js +265 -0
  488. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.js.map +1 -0
  489. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.test.d.ts +2 -0
  490. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.test.d.ts.map +1 -0
  491. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.test.js +398 -0
  492. package/dist/src/backend/services/workspace/resources/workspace-pr.accessor.test.js.map +1 -0
  493. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.d.ts +53 -0
  494. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.d.ts.map +1 -0
  495. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.js +197 -0
  496. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.js.map +1 -0
  497. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.test.d.ts +2 -0
  498. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.test.d.ts.map +1 -0
  499. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.test.js +345 -0
  500. package/dist/src/backend/services/workspace/resources/workspace-ratchet.accessor.test.js.map +1 -0
  501. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.d.ts +33 -0
  502. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.d.ts.map +1 -0
  503. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.js +110 -0
  504. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.js.map +1 -0
  505. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.test.d.ts +2 -0
  506. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.test.d.ts.map +1 -0
  507. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.test.js +192 -0
  508. package/dist/src/backend/services/workspace/resources/workspace-run-script.accessor.test.js.map +1 -0
  509. package/dist/src/backend/services/workspace/resources/workspace.accessor.d.ts +68 -119
  510. package/dist/src/backend/services/workspace/resources/workspace.accessor.d.ts.map +1 -1
  511. package/dist/src/backend/services/workspace/resources/workspace.accessor.js +186 -426
  512. package/dist/src/backend/services/workspace/resources/workspace.accessor.js.map +1 -1
  513. package/dist/src/backend/services/workspace/resources/workspace.accessor.test.js +286 -623
  514. package/dist/src/backend/services/workspace/resources/workspace.accessor.test.js.map +1 -1
  515. package/dist/src/backend/services/workspace/service/bridges.d.ts +0 -1
  516. package/dist/src/backend/services/workspace/service/bridges.d.ts.map +1 -1
  517. package/dist/src/backend/services/workspace/service/index.d.ts +3 -4
  518. package/dist/src/backend/services/workspace/service/index.d.ts.map +1 -1
  519. package/dist/src/backend/services/workspace/service/index.js +2 -3
  520. package/dist/src/backend/services/workspace/service/index.js.map +1 -1
  521. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.d.ts +3 -2
  522. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.d.ts.map +1 -1
  523. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js +1 -1
  524. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js.map +1 -1
  525. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js +3 -3
  526. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js.map +1 -1
  527. package/dist/src/backend/services/workspace/service/lifecycle/data.service.d.ts +119 -387
  528. package/dist/src/backend/services/workspace/service/lifecycle/data.service.d.ts.map +1 -1
  529. package/dist/src/backend/services/workspace/service/lifecycle/data.service.js +7 -11
  530. package/dist/src/backend/services/workspace/service/lifecycle/data.service.js.map +1 -1
  531. package/dist/src/backend/services/workspace/service/lifecycle/data.service.test.js +13 -13
  532. package/dist/src/backend/services/workspace/service/lifecycle/data.service.test.js.map +1 -1
  533. package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.d.ts.map +1 -1
  534. package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.js +13 -30
  535. package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.js.map +1 -1
  536. package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.test.js +99 -29
  537. package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.test.js.map +1 -1
  538. package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.d.ts +13 -194
  539. package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.d.ts.map +1 -1
  540. package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.js +21 -7
  541. package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.js.map +1 -1
  542. package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.d.ts +6 -66
  543. package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.d.ts.map +1 -1
  544. package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.js +10 -17
  545. package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.js.map +1 -1
  546. package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.test.js +16 -4
  547. package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.test.js.map +1 -1
  548. package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.d.ts +7 -230
  549. package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.d.ts.map +1 -1
  550. package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.js +15 -22
  551. package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.js.map +1 -1
  552. package/dist/src/backend/services/workspace/service/lifecycle/workspace-relationships.service.d.ts +79 -75
  553. package/dist/src/backend/services/workspace/service/lifecycle/workspace-relationships.service.d.ts.map +1 -1
  554. package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.d.ts +5 -132
  555. package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.d.ts.map +1 -1
  556. package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.js +3 -6
  557. package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.js.map +1 -1
  558. package/dist/src/backend/services/workspace/service/lifecycle/workspace-state-capabilities.test.js +65 -7
  559. package/dist/src/backend/services/workspace/service/lifecycle/workspace-state-capabilities.test.js.map +1 -1
  560. package/dist/src/backend/services/workspace/service/query/project-management.service.d.ts +2 -70
  561. package/dist/src/backend/services/workspace/service/query/project-management.service.d.ts.map +1 -1
  562. package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.d.ts +111 -280
  563. package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.d.ts.map +1 -1
  564. package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.js +4 -3
  565. package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.js.map +1 -1
  566. package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.test.js +7 -4
  567. package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.test.js.map +1 -1
  568. package/dist/src/backend/services/workspace/service/query/workspace-notification.service.d.ts +4 -4
  569. package/dist/src/backend/services/workspace/service/query/workspace-query.service.d.ts +31 -216
  570. package/dist/src/backend/services/workspace/service/query/workspace-query.service.d.ts.map +1 -1
  571. package/dist/src/backend/services/workspace/service/query/workspace-query.service.js +110 -144
  572. package/dist/src/backend/services/workspace/service/query/workspace-query.service.js.map +1 -1
  573. package/dist/src/backend/services/workspace/service/query/workspace-query.service.test.js +213 -111
  574. package/dist/src/backend/services/workspace/service/query/workspace-query.service.test.js.map +1 -1
  575. package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.d.ts +6 -12
  576. package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.d.ts.map +1 -1
  577. package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.js +24 -10
  578. package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.js.map +1 -1
  579. package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.test.js +28 -18
  580. package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.test.js.map +1 -1
  581. package/dist/src/backend/services/workspace/service/state/flow-state.d.ts.map +1 -1
  582. package/dist/src/backend/services/workspace/service/state/flow-state.js +1 -9
  583. package/dist/src/backend/services/workspace/service/state/flow-state.js.map +1 -1
  584. package/dist/src/backend/services/workspace/service/state/flow-state.test.js +10 -27
  585. package/dist/src/backend/services/workspace/service/state/flow-state.test.js.map +1 -1
  586. package/dist/src/backend/services/workspace/service/workspace-domain-exports.test.js +1 -7
  587. package/dist/src/backend/services/workspace/service/workspace-domain-exports.test.js.map +1 -1
  588. package/dist/src/backend/services/workspace/service/worktree/git-ops.service.d.ts +8 -1
  589. package/dist/src/backend/services/workspace/service/worktree/git-ops.service.d.ts.map +1 -1
  590. package/dist/src/backend/services/workspace/service/worktree/git-ops.service.js +45 -8
  591. package/dist/src/backend/services/workspace/service/worktree/git-ops.service.js.map +1 -1
  592. package/dist/src/backend/services/workspace/service/worktree/git-ops.service.test.js +108 -13
  593. package/dist/src/backend/services/workspace/service/worktree/git-ops.service.test.js.map +1 -1
  594. package/dist/src/backend/services/workspace/service/worktree/worktree-init.test.js +1 -1
  595. package/dist/src/backend/services/workspace/service/worktree/worktree-init.test.js.map +1 -1
  596. package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.d.ts +3 -3
  597. package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.d.ts.map +1 -1
  598. package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.js +8 -1
  599. package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.js.map +1 -1
  600. package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.test.js +29 -12
  601. package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.test.js.map +1 -1
  602. package/dist/src/backend/services/workspace-depth-triggers.integration.test.d.ts +2 -0
  603. package/dist/src/backend/services/workspace-depth-triggers.integration.test.d.ts.map +1 -0
  604. package/dist/src/backend/services/workspace-depth-triggers.integration.test.js +68 -0
  605. package/dist/src/backend/services/workspace-depth-triggers.integration.test.js.map +1 -0
  606. package/dist/src/backend/services/workspace-git-state.service.d.ts +1 -0
  607. package/dist/src/backend/services/workspace-git-state.service.d.ts.map +1 -1
  608. package/dist/src/backend/services/workspace-git-state.service.js +14 -0
  609. package/dist/src/backend/services/workspace-git-state.service.js.map +1 -1
  610. package/dist/src/backend/services/workspace-git-state.service.test.js +37 -0
  611. package/dist/src/backend/services/workspace-git-state.service.test.js.map +1 -1
  612. package/dist/src/backend/testing/check-fk-indexes-script.test.d.ts +2 -0
  613. package/dist/src/backend/testing/check-fk-indexes-script.test.d.ts.map +1 -0
  614. package/dist/src/backend/testing/check-fk-indexes-script.test.js +46 -0
  615. package/dist/src/backend/testing/check-fk-indexes-script.test.js.map +1 -0
  616. package/dist/src/backend/testing/check-prisma-versions-script.test.d.ts +2 -0
  617. package/dist/src/backend/testing/check-prisma-versions-script.test.d.ts.map +1 -0
  618. package/dist/src/backend/testing/check-prisma-versions-script.test.js +52 -0
  619. package/dist/src/backend/testing/check-prisma-versions-script.test.js.map +1 -0
  620. package/dist/src/backend/trpc/admin.router.test.js +7 -7
  621. package/dist/src/backend/trpc/admin.router.test.js.map +1 -1
  622. package/dist/src/backend/trpc/admin.trpc.d.ts +13 -5
  623. package/dist/src/backend/trpc/admin.trpc.d.ts.map +1 -1
  624. package/dist/src/backend/trpc/admin.trpc.js +3 -3
  625. package/dist/src/backend/trpc/admin.trpc.js.map +1 -1
  626. package/dist/src/backend/trpc/auto-iteration.trpc.d.ts +11 -1
  627. package/dist/src/backend/trpc/auto-iteration.trpc.d.ts.map +1 -1
  628. package/dist/src/backend/trpc/closed-sessions.trpc.d.ts +12 -2
  629. package/dist/src/backend/trpc/closed-sessions.trpc.d.ts.map +1 -1
  630. package/dist/src/backend/trpc/context-dependencies.test.js +0 -1
  631. package/dist/src/backend/trpc/context-dependencies.test.js.map +1 -1
  632. package/dist/src/backend/trpc/decision-log.trpc.d.ts +11 -1
  633. package/dist/src/backend/trpc/decision-log.trpc.d.ts.map +1 -1
  634. package/dist/src/backend/trpc/github.trpc.d.ts +11 -1
  635. package/dist/src/backend/trpc/github.trpc.d.ts.map +1 -1
  636. package/dist/src/backend/trpc/index.d.ts +378 -820
  637. package/dist/src/backend/trpc/index.d.ts.map +1 -1
  638. package/dist/src/backend/trpc/linear.trpc.d.ts +11 -1
  639. package/dist/src/backend/trpc/linear.trpc.d.ts.map +1 -1
  640. package/dist/src/backend/trpc/periodic-task.trpc.d.ts +15 -5
  641. package/dist/src/backend/trpc/periodic-task.trpc.d.ts.map +1 -1
  642. package/dist/src/backend/trpc/pr-review.trpc.d.ts +11 -1
  643. package/dist/src/backend/trpc/pr-review.trpc.d.ts.map +1 -1
  644. package/dist/src/backend/trpc/project.trpc.d.ts +13 -71
  645. package/dist/src/backend/trpc/project.trpc.d.ts.map +1 -1
  646. package/dist/src/backend/trpc/session.router.test.js +22 -16
  647. package/dist/src/backend/trpc/session.router.test.js.map +1 -1
  648. package/dist/src/backend/trpc/session.trpc.d.ts +22 -46
  649. package/dist/src/backend/trpc/session.trpc.d.ts.map +1 -1
  650. package/dist/src/backend/trpc/session.trpc.js +13 -13
  651. package/dist/src/backend/trpc/session.trpc.js.map +1 -1
  652. package/dist/src/backend/trpc/trpc.d.ts +11 -1
  653. package/dist/src/backend/trpc/trpc.d.ts.map +1 -1
  654. package/dist/src/backend/trpc/trpc.js +10 -0
  655. package/dist/src/backend/trpc/trpc.js.map +1 -1
  656. package/dist/src/backend/trpc/user-settings.trpc.d.ts +11 -1
  657. package/dist/src/backend/trpc/user-settings.trpc.d.ts.map +1 -1
  658. package/dist/src/backend/trpc/workspace/children.router.test.js +49 -3
  659. package/dist/src/backend/trpc/workspace/children.router.test.js.map +1 -1
  660. package/dist/src/backend/trpc/workspace/children.trpc.d.ts +15 -39
  661. package/dist/src/backend/trpc/workspace/children.trpc.d.ts.map +1 -1
  662. package/dist/src/backend/trpc/workspace/children.trpc.js +43 -16
  663. package/dist/src/backend/trpc/workspace/children.trpc.js.map +1 -1
  664. package/dist/src/backend/trpc/workspace/composition.test.js +8 -5
  665. package/dist/src/backend/trpc/workspace/composition.test.js.map +1 -1
  666. package/dist/src/backend/trpc/workspace/files.trpc.d.ts +11 -1
  667. package/dist/src/backend/trpc/workspace/files.trpc.d.ts.map +1 -1
  668. package/dist/src/backend/trpc/workspace/git.trpc.d.ts +11 -1
  669. package/dist/src/backend/trpc/workspace/git.trpc.d.ts.map +1 -1
  670. package/dist/src/backend/trpc/workspace/ide.trpc.d.ts +11 -1
  671. package/dist/src/backend/trpc/workspace/ide.trpc.d.ts.map +1 -1
  672. package/dist/src/backend/trpc/workspace/init.trpc.d.ts +64 -41
  673. package/dist/src/backend/trpc/workspace/init.trpc.d.ts.map +1 -1
  674. package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts +11 -1
  675. package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts.map +1 -1
  676. package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts +81 -77
  677. package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts.map +1 -1
  678. package/dist/src/backend/trpc/workspace.router.test.js +33 -32
  679. package/dist/src/backend/trpc/workspace.router.test.js.map +1 -1
  680. package/dist/src/backend/trpc/workspace.trpc.d.ts +587 -1482
  681. package/dist/src/backend/trpc/workspace.trpc.d.ts.map +1 -1
  682. package/dist/src/backend/trpc/workspace.trpc.js +35 -56
  683. package/dist/src/backend/trpc/workspace.trpc.js.map +1 -1
  684. package/dist/src/cli/runtime-utils.d.ts.map +1 -1
  685. package/dist/src/cli/runtime-utils.js +4 -0
  686. package/dist/src/cli/runtime-utils.js.map +1 -1
  687. package/dist/src/cli/runtime-utils.test.d.ts +2 -0
  688. package/dist/src/cli/runtime-utils.test.d.ts.map +1 -0
  689. package/dist/src/cli/runtime-utils.test.js +28 -0
  690. package/dist/src/cli/runtime-utils.test.js.map +1 -0
  691. package/dist/src/shared/acp-protocol/protocol/renderer-window.d.ts +1 -0
  692. package/dist/src/shared/acp-protocol/protocol/renderer-window.d.ts.map +1 -1
  693. package/dist/src/shared/acp-protocol/protocol/renderer-window.js +13 -2
  694. package/dist/src/shared/acp-protocol/protocol/renderer-window.js.map +1 -1
  695. package/dist/src/shared/acp-protocol/protocol/websocket.d.ts +1 -0
  696. package/dist/src/shared/acp-protocol/protocol/websocket.d.ts.map +1 -1
  697. package/dist/src/shared/acp-protocol/protocol/websocket.js.map +1 -1
  698. package/dist/src/shared/attachment-limits.d.ts +2 -0
  699. package/dist/src/shared/attachment-limits.d.ts.map +1 -0
  700. package/dist/src/shared/attachment-limits.js +2 -0
  701. package/dist/src/shared/attachment-limits.js.map +1 -0
  702. package/dist/src/shared/core/index.d.ts +1 -0
  703. package/dist/src/shared/core/index.d.ts.map +1 -1
  704. package/dist/src/shared/core/index.js +1 -0
  705. package/dist/src/shared/core/index.js.map +1 -1
  706. package/dist/src/shared/core/ratchet-state.d.ts +10 -0
  707. package/dist/src/shared/core/ratchet-state.d.ts.map +1 -0
  708. package/dist/src/shared/core/ratchet-state.js +32 -0
  709. package/dist/src/shared/core/ratchet-state.js.map +1 -0
  710. package/dist/src/shared/kanban-column-projection.d.ts +5 -0
  711. package/dist/src/shared/kanban-column-projection.d.ts.map +1 -0
  712. package/dist/src/shared/kanban-column-projection.js +31 -0
  713. package/dist/src/shared/kanban-column-projection.js.map +1 -0
  714. package/dist/src/shared/schemas/export-data.schema.d.ts +2 -12
  715. package/dist/src/shared/schemas/export-data.schema.d.ts.map +1 -1
  716. package/dist/src/shared/schemas/export-data.schema.js +2 -4
  717. package/dist/src/shared/schemas/export-data.schema.js.map +1 -1
  718. package/dist/src/shared/session-runtime.d.ts +1 -0
  719. package/dist/src/shared/session-runtime.d.ts.map +1 -1
  720. package/dist/src/shared/session-runtime.js +3 -0
  721. package/dist/src/shared/session-runtime.js.map +1 -1
  722. package/dist/src/shared/workspace-snapshot.d.ts +101 -6
  723. package/dist/src/shared/workspace-snapshot.d.ts.map +1 -1
  724. package/dist/src/shared/workspace-snapshot.js +5 -1
  725. package/dist/src/shared/workspace-snapshot.js.map +1 -1
  726. package/dist/src/shared/workspace-status-reason.d.ts +8 -3
  727. package/dist/src/shared/workspace-status-reason.d.ts.map +1 -1
  728. package/dist/src/shared/workspace-status-reason.js +50 -20
  729. package/dist/src/shared/workspace-status-reason.js.map +1 -1
  730. package/dist/src/test-utils/application-graph.d.ts +0 -1
  731. package/dist/src/test-utils/application-graph.d.ts.map +1 -1
  732. package/dist/src/test-utils/application-graph.js +16 -11
  733. package/dist/src/test-utils/application-graph.js.map +1 -1
  734. package/dist/tsconfig.backend.tsbuildinfo +1 -1
  735. package/package.json +92 -151
  736. package/prisma/migrations/20260726112950_drop_cached_kanban_column/migration.sql +132 -0
  737. package/prisma/migrations/20260726135402_split_workspace_ratchet/migration.sql +149 -0
  738. package/prisma/migrations/20260726181500_split_workspace_pr/migration.sql +142 -0
  739. package/prisma/migrations/20260726200000_derive_ratchet_state/migration.sql +101 -0
  740. package/prisma/migrations/20260726220000_split_workspace_run_script/migration.sql +131 -0
  741. package/prisma/migrations/20260726230000_split_workspace_auto_iteration/migration.sql +123 -0
  742. package/prisma/migrations/20260728000000_add_workspace_periodic_task_id_index/migration.sql +2 -0
  743. package/prisma/migrations/20260728232525_add_ratchet_dispatch_stalled/migration.sql +20 -0
  744. package/prisma/schema.prisma +227 -62
  745. package/dist/client/assets/arc-lK3Ig9GV.js +0 -1
  746. package/dist/client/assets/architectureDiagram-3BPJPVTR-CeUbfBqe.js +0 -36
  747. package/dist/client/assets/blockDiagram-GPEHLZMM-DiVGPkq2.js +0 -132
  748. package/dist/client/assets/channel-CvY1mvIl.js +0 -1
  749. package/dist/client/assets/chunk-AQP2D5EJ-dyo9i4xa.js +0 -231
  750. package/dist/client/assets/classDiagram-4FO5ZUOK-Db7ZXJ6w.js +0 -1
  751. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Db7ZXJ6w.js +0 -1
  752. package/dist/client/assets/cytoscape.esm-DkOyvmE4.js +0 -321
  753. package/dist/client/assets/dagre-BM42HDAG-CDzpFdgD.js +0 -4
  754. package/dist/client/assets/diagram-2AECGRRQ-dl1_7lyq.js +0 -43
  755. package/dist/client/assets/diagram-5GNKFQAL-B0ynMwBY.js +0 -10
  756. package/dist/client/assets/diagram-LMA3HP47-DZxXcfiX.js +0 -24
  757. package/dist/client/assets/diagram-OG6HWLK6-BncGM9Gv.js +0 -24
  758. package/dist/client/assets/erDiagram-TEJ5UH35-B9hxScvO.js +0 -85
  759. package/dist/client/assets/flowDiagram-I6XJVG4X-DgZ2jwJQ.js +0 -162
  760. package/dist/client/assets/ganttDiagram-6RSMTGT7-BrnNMNRY.js +0 -292
  761. package/dist/client/assets/gitGraphDiagram-PVQCEYII-BJmed6oD.js +0 -106
  762. package/dist/client/assets/index-Btlruz7h.css +0 -1
  763. package/dist/client/assets/index-DEKuJM5_.js +0 -674
  764. package/dist/client/assets/infoDiagram-5YYISTIA-CtLzR4ip.js +0 -2
  765. package/dist/client/assets/katex-DHMw6HUq.js +0 -257
  766. package/dist/client/assets/layout-SsrduOYp.js +0 -1
  767. package/dist/client/assets/pieDiagram-4H26LBE5-DgPu3GTs.js +0 -30
  768. package/dist/client/assets/sankeyDiagram-5OEKKPKP-DmYoq588.js +0 -40
  769. package/dist/client/assets/sequenceDiagram-3UESZ5HK-EVqdDzgf.js +0 -162
  770. package/dist/client/assets/stateDiagram-AJRCARHV-BRd6IxSa.js +0 -1
  771. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DR2vMoX5.js +0 -1
  772. package/dist/client/assets/vennDiagram-CIIHVFJN-CLslQYVi.js +0 -34
  773. package/dist/client/assets/wardley-L42UT6IY-DyEDLg3x.js +0 -161
  774. package/dist/client/assets/xychartDiagram-2RQKCTM6-DwzoT5Dl.js +0 -7
  775. package/dist/src/backend/interceptors/branch-rename.interceptor.d.ts +0 -3
  776. package/dist/src/backend/interceptors/branch-rename.interceptor.d.ts.map +0 -1
  777. package/dist/src/backend/interceptors/branch-rename.interceptor.js +0 -117
  778. package/dist/src/backend/interceptors/branch-rename.interceptor.js.map +0 -1
  779. package/dist/src/backend/interceptors/branch-rename.interceptor.test.d.ts +0 -2
  780. package/dist/src/backend/interceptors/branch-rename.interceptor.test.d.ts.map +0 -1
  781. package/dist/src/backend/interceptors/branch-rename.interceptor.test.js +0 -184
  782. package/dist/src/backend/interceptors/branch-rename.interceptor.test.js.map +0 -1
  783. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.d.ts +0 -6
  784. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.d.ts.map +0 -1
  785. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js +0 -225
  786. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js.map +0 -1
  787. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.d.ts +0 -2
  788. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.d.ts.map +0 -1
  789. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js +0 -348
  790. package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js.map +0 -1
  791. package/dist/src/backend/interceptors/pre-push-rename.interceptor.d.ts +0 -4
  792. package/dist/src/backend/interceptors/pre-push-rename.interceptor.d.ts.map +0 -1
  793. package/dist/src/backend/interceptors/pre-push-rename.interceptor.js +0 -136
  794. package/dist/src/backend/interceptors/pre-push-rename.interceptor.js.map +0 -1
  795. package/dist/src/backend/interceptors/pre-push-rename.interceptor.test.d.ts +0 -2
  796. package/dist/src/backend/interceptors/pre-push-rename.interceptor.test.d.ts.map +0 -1
  797. package/dist/src/backend/interceptors/pre-push-rename.interceptor.test.js +0 -260
  798. package/dist/src/backend/interceptors/pre-push-rename.interceptor.test.js.map +0 -1
  799. package/dist/src/backend/routers/websocket/dev-logs.handler.d.ts +0 -5
  800. package/dist/src/backend/routers/websocket/dev-logs.handler.d.ts.map +0 -1
  801. package/dist/src/backend/routers/websocket/dev-logs.handler.js +0 -28
  802. package/dist/src/backend/routers/websocket/dev-logs.handler.js.map +0 -1
  803. package/dist/src/backend/routers/websocket/dev-logs.handler.test.d.ts +0 -2
  804. package/dist/src/backend/routers/websocket/dev-logs.handler.test.d.ts.map +0 -1
  805. package/dist/src/backend/routers/websocket/dev-logs.handler.test.js.map +0 -1
  806. package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts +0 -5
  807. package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts.map +0 -1
  808. package/dist/src/backend/routers/websocket/post-run-logs.handler.js +0 -18
  809. package/dist/src/backend/routers/websocket/post-run-logs.handler.js.map +0 -1
  810. package/dist/src/backend/routers/websocket/post-run-logs.handler.test.d.ts +0 -2
  811. package/dist/src/backend/routers/websocket/post-run-logs.handler.test.d.ts.map +0 -1
  812. package/dist/src/backend/routers/websocket/post-run-logs.handler.test.js.map +0 -1
  813. package/dist/src/backend/services/github/service/pr-fetch-registry.d.ts +0 -20
  814. package/dist/src/backend/services/github/service/pr-fetch-registry.d.ts.map +0 -1
  815. package/dist/src/backend/services/github/service/pr-fetch-registry.js.map +0 -1
  816. package/dist/src/backend/services/github/service/pr-fetch-registry.test.d.ts +0 -2
  817. package/dist/src/backend/services/github/service/pr-fetch-registry.test.d.ts.map +0 -1
  818. package/dist/src/backend/services/github/service/pr-fetch-registry.test.js +0 -112
  819. package/dist/src/backend/services/github/service/pr-fetch-registry.test.js.map +0 -1
  820. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.d.ts +0 -11
  821. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.d.ts.map +0 -1
  822. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.js +0 -77
  823. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.js.map +0 -1
  824. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.test.d.ts +0 -2
  825. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.test.d.ts.map +0 -1
  826. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.test.js +0 -66
  827. package/dist/src/backend/services/ratchet/service/ratchet-state-machine.test.js.map +0 -1
  828. package/dist/src/backend/services/session/service/lifecycle/session.service.coverage.test.d.ts +0 -2
  829. package/dist/src/backend/services/session/service/lifecycle/session.service.coverage.test.d.ts.map +0 -1
  830. package/dist/src/backend/services/session/service/lifecycle/session.service.coverage.test.js +0 -279
  831. package/dist/src/backend/services/session/service/lifecycle/session.service.coverage.test.js.map +0 -1
  832. package/dist/src/backend/services/workspace/service/state/kanban-state.d.ts +0 -44
  833. package/dist/src/backend/services/workspace/service/state/kanban-state.d.ts.map +0 -1
  834. package/dist/src/backend/services/workspace/service/state/kanban-state.js +0 -220
  835. package/dist/src/backend/services/workspace/service/state/kanban-state.js.map +0 -1
  836. package/dist/src/backend/services/workspace/service/state/kanban-state.test.d.ts +0 -2
  837. package/dist/src/backend/services/workspace/service/state/kanban-state.test.d.ts.map +0 -1
  838. package/dist/src/backend/services/workspace/service/state/kanban-state.test.js +0 -468
  839. package/dist/src/backend/services/workspace/service/state/kanban-state.test.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
- import { SERVICE_TIMEOUT_MS } from '../../../../backend/services/constants.js';
2
+ import { SERVICE_THRESHOLDS, SERVICE_TIMEOUT_MS } from '../../../../backend/services/constants.js';
3
3
  import { CIStatus, RatchetState, SessionStatus } from '../../../../shared/core/index.js';
4
4
  import { unsafeCoerce } from '../../../../test-utils/unsafe-coerce.js';
5
5
  vi.mock('@/backend/services/workspace', () => ({
@@ -12,8 +12,7 @@ vi.mock('@/backend/services/workspace', () => ({
12
12
  clearActiveSession: vi.fn(),
13
13
  enable: vi.fn(),
14
14
  disable: vi.fn(),
15
- transitionStateIfEnabled: vi.fn(),
16
- settleIdleWhileDisabled: vi.fn(),
15
+ recordCheckIfEnabled: vi.fn(),
17
16
  recordDispatchIfEnabled: vi.fn(),
18
17
  adoptActiveSessionIfEnabled: vi.fn(),
19
18
  recordSessionEnd: vi.fn(),
@@ -65,30 +64,49 @@ const mockSessionBridge = {
65
64
  const mockWorkspaceBridge = {
66
65
  findFixerContext: vi.fn(),
67
66
  recordSessionEnd: vi.fn(),
67
+ markDispatchStalled: vi.fn().mockResolvedValue(true),
68
68
  };
69
+ const fakeCoordinator = { cooldownActive: false, inFlightSkips: 0 };
69
70
  const mockGitHubBridge = {
70
71
  extractPRInfo: vi.fn(),
71
72
  getPRFullDetails: vi.fn(),
72
73
  getReviewComments: vi.fn(),
73
74
  getResolvedReviewCommentIds: vi.fn(),
74
75
  computeCIStatus: vi.fn(),
76
+ computePRState: vi.fn(() => 'OPEN'),
75
77
  getAuthenticatedUsername: vi.fn(),
76
78
  fetchAndComputePRState: vi.fn(),
77
- isRecentlyFetched: vi.fn(),
78
- isFetchInFlight: vi.fn(),
79
- startFetch: vi.fn(() => 41),
80
- registerFetch: vi.fn(),
81
- cancelFetch: vi.fn(),
79
+ coordinatePrFetch: vi.fn(async (_workspaceId, fetch, options) => {
80
+ if (fakeCoordinator.inFlightSkips > 0) {
81
+ fakeCoordinator.inFlightSkips -= 1;
82
+ return { status: 'skipped', reason: 'recently_fetched' };
83
+ }
84
+ if (fakeCoordinator.cooldownActive && !options?.ignoreCooldown) {
85
+ return { status: 'skipped', reason: 'recently_fetched' };
86
+ }
87
+ return { status: 'fetched', value: await fetch() };
88
+ }),
82
89
  };
83
90
  const mockSnapshotBridge = {
84
- recordCIObservation: vi.fn(),
91
+ recordPrObservation: vi.fn(),
85
92
  recordCINotification: vi.fn(),
86
93
  recordReviewCheck: vi.fn(),
87
94
  };
95
+ function setRatchetShuttingDown(shuttingDown) {
96
+ const controller = new AbortController();
97
+ if (shuttingDown) {
98
+ controller.abort();
99
+ }
100
+ const internals = unsafeCoerce(ratchetService);
101
+ internals.runSignal = controller.signal;
102
+ internals.stopped = shuttingDown;
103
+ }
88
104
  describe('ratchet service (state-change + idle dispatch)', () => {
89
105
  beforeEach(() => {
90
106
  vi.clearAllMocks();
91
- unsafeCoerce(ratchetService).isShuttingDown = false;
107
+ fakeCoordinator.cooldownActive = false;
108
+ fakeCoordinator.inFlightSkips = 0;
109
+ setRatchetShuttingDown(false);
92
110
  unsafeCoerce(ratchetService).workspaceCheckTimeoutMs =
93
111
  SERVICE_TIMEOUT_MS.ratchetWorkspaceCheck;
94
112
  ratchetService.configure({
@@ -97,8 +115,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
97
115
  snapshot: mockSnapshotBridge,
98
116
  workspace: mockWorkspaceBridge,
99
117
  });
100
- vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(true);
101
- vi.mocked(workspaceRatchetService.settleIdleWhileDisabled).mockResolvedValue(true);
118
+ vi.mocked(workspaceRatchetService.recordCheckIfEnabled).mockResolvedValue(true);
102
119
  vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockResolvedValue(true);
103
120
  vi.mocked(workspaceRatchetService.adoptActiveSessionIfEnabled).mockResolvedValue(true);
104
121
  vi.mocked(workspaceRatchetService.recordSessionEnd).mockResolvedValue(true);
@@ -147,16 +164,20 @@ describe('ratchet service (state-change + idle dispatch)', () => {
147
164
  prUrl: 'https://github.com/example/repo/pull/1',
148
165
  prNumber: 1,
149
166
  prState: 'OPEN',
167
+ prReviewState: null,
168
+ prHasMergeConflict: false,
150
169
  prCiStatus: CIStatus.UNKNOWN,
151
170
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
152
171
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
153
172
  ratchetEnabled: true,
154
173
  ratchetState: RatchetState.IDLE,
174
+ ratchetLastCheckedAt: null,
155
175
  ratchetActiveSessionId: null,
156
- ratchetLastCiRunId: null,
176
+ ratchetDispatchSnapshotKey: null,
157
177
  prReviewLastCheckedAt: null,
158
178
  ratchetDispatchOutcome: null,
159
179
  ratchetDispatchRetryCount: 0,
180
+ ratchetDispatchStalled: false,
160
181
  },
161
182
  ]);
162
183
  vi.spyOn(unsafeCoerce(ratchetService), 'processWorkspace').mockResolvedValue({
@@ -174,11 +195,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
174
195
  prUrl: 'https://github.com/example/repo/pull/2',
175
196
  prNumber: 2,
176
197
  prState: 'OPEN',
198
+ prReviewState: null,
199
+ prHasMergeConflict: false,
177
200
  prCiStatus: CIStatus.UNKNOWN,
178
201
  ratchetEnabled: false,
179
202
  ratchetState: RatchetState.IDLE,
180
203
  ratchetActiveSessionId: null,
181
- ratchetLastCiRunId: null,
204
+ ratchetDispatchSnapshotKey: null,
182
205
  prReviewLastCheckedAt: null,
183
206
  ratchetDispatchOutcome: null,
184
207
  ratchetDispatchRetryCount: 0,
@@ -192,70 +215,37 @@ describe('ratchet service (state-change + idle dispatch)', () => {
192
215
  action: { type: 'DISABLED', reason: 'Workspace ratcheting disabled' },
193
216
  newState: RatchetState.IDLE,
194
217
  });
195
- expect(workspaceRatchetService.settleIdleWhileDisabled).toHaveBeenCalledWith('ws-disabled', RatchetState.IDLE);
218
+ expect(workspaceRatchetService.recordCheckIfEnabled).not.toHaveBeenCalled();
196
219
  });
197
- it('settles a disabled workspace to IDLE via CAS and emits an accurate fromState', async () => {
220
+ it('reports a disabled workspace as IDLE without writing anything', async () => {
198
221
  const workspace = {
199
222
  id: 'ws-disabled-settle',
200
223
  prUrl: 'https://github.com/example/repo/pull/2',
201
224
  prNumber: 2,
202
225
  prState: 'OPEN',
226
+ prReviewState: null,
227
+ prHasMergeConflict: false,
203
228
  prCiStatus: CIStatus.UNKNOWN,
204
229
  ratchetEnabled: false,
205
- ratchetState: RatchetState.CI_FAILED,
230
+ ratchetState: RatchetState.IDLE,
206
231
  ratchetActiveSessionId: null,
207
- ratchetLastCiRunId: null,
232
+ ratchetDispatchSnapshotKey: null,
208
233
  prReviewLastCheckedAt: null,
209
234
  ratchetDispatchOutcome: null,
210
235
  ratchetDispatchRetryCount: 0,
211
236
  };
212
- vi.mocked(workspaceRatchetService.settleIdleWhileDisabled).mockResolvedValue(true);
213
237
  const events = [];
214
238
  ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
215
239
  events.push(event);
216
240
  });
217
241
  const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
218
- expect(workspaceRatchetService.settleIdleWhileDisabled).toHaveBeenCalledWith('ws-disabled-settle', RatchetState.CI_FAILED);
219
242
  expect(result).toMatchObject({
220
- previousState: RatchetState.CI_FAILED,
243
+ previousState: RatchetState.IDLE,
221
244
  newState: RatchetState.IDLE,
222
245
  action: { type: 'DISABLED' },
223
246
  });
224
- expect(events).toEqual([
225
- {
226
- workspaceId: 'ws-disabled-settle',
227
- fromState: RatchetState.CI_FAILED,
228
- toState: RatchetState.IDLE,
229
- },
230
- ]);
231
- });
232
- it('does not emit for a disabled workspace when the settle CAS loses', async () => {
233
- const workspace = {
234
- id: 'ws-disabled-settle-race',
235
- prUrl: 'https://github.com/example/repo/pull/2',
236
- prNumber: 2,
237
- prState: 'OPEN',
238
- prCiStatus: CIStatus.UNKNOWN,
239
- ratchetEnabled: false,
240
- ratchetState: RatchetState.CI_FAILED,
241
- ratchetActiveSessionId: null,
242
- ratchetLastCiRunId: null,
243
- prReviewLastCheckedAt: null,
244
- ratchetDispatchOutcome: null,
245
- ratchetDispatchRetryCount: 0,
246
- };
247
- vi.mocked(workspaceRatchetService.settleIdleWhileDisabled).mockResolvedValue(false);
248
- const events = [];
249
- ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
250
- events.push(event);
251
- });
252
- const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
253
- expect(result).toMatchObject({
254
- previousState: RatchetState.CI_FAILED,
255
- newState: RatchetState.CI_FAILED,
256
- action: { type: 'DISABLED' },
257
- });
258
247
  expect(events).toEqual([]);
248
+ expect(workspaceRatchetService.recordCheckIfEnabled).not.toHaveBeenCalled();
259
249
  });
260
250
  it('does not dispatch when workspace is not idle', async () => {
261
251
  const workspace = {
@@ -263,11 +253,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
263
253
  prUrl: 'https://github.com/example/repo/pull/3',
264
254
  prNumber: 3,
265
255
  prState: 'OPEN',
256
+ prReviewState: null,
257
+ prHasMergeConflict: false,
266
258
  prCiStatus: CIStatus.UNKNOWN,
267
259
  ratchetEnabled: true,
268
260
  ratchetState: RatchetState.IDLE,
269
261
  ratchetActiveSessionId: null,
270
- ratchetLastCiRunId: null,
262
+ ratchetDispatchSnapshotKey: null,
271
263
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
272
264
  ratchetDispatchOutcome: null,
273
265
  ratchetDispatchRetryCount: 0,
@@ -313,11 +305,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
313
305
  prUrl: 'https://github.com/example/repo/pull/4',
314
306
  prNumber: 4,
315
307
  prState: 'OPEN',
308
+ prReviewState: null,
309
+ prHasMergeConflict: false,
316
310
  prCiStatus: CIStatus.UNKNOWN,
317
311
  ratchetEnabled: true,
318
312
  ratchetState: RatchetState.IDLE,
319
313
  ratchetActiveSessionId: null,
320
- ratchetLastCiRunId: '2026-01-01T00:00:00Z',
314
+ ratchetDispatchSnapshotKey: '2026-01-01T00:00:00Z',
321
315
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
322
316
  ratchetDispatchOutcome: null,
323
317
  ratchetDispatchRetryCount: 0,
@@ -346,11 +340,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
346
340
  snapshotKey: '2026-01-02T00:00:00Z',
347
341
  retryCount: 0,
348
342
  });
349
- const finalUpdatePayload = vi
350
- .mocked(workspaceRatchetService.transitionStateIfEnabled)
351
- .mock.calls.at(-1)?.[2];
352
- expect(finalUpdatePayload).not.toHaveProperty('ratchetLastCiRunId');
353
- expect(finalUpdatePayload).not.toHaveProperty('prReviewLastCheckedAt');
343
+ expect(workspaceRatchetService.recordCheckIfEnabled).toHaveBeenLastCalledWith('ws-change', expect.any(Date));
354
344
  expect(mockSnapshotBridge.recordReviewCheck).toHaveBeenCalledWith('ws-change', expect.any(Date));
355
345
  });
356
346
  it('stops fixer and returns disabled when active-session recording loses disable race', async () => {
@@ -359,11 +349,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
359
349
  prUrl: 'https://github.com/example/repo/pull/40',
360
350
  prNumber: 40,
361
351
  prState: 'OPEN',
352
+ prReviewState: null,
353
+ prHasMergeConflict: false,
362
354
  prCiStatus: CIStatus.UNKNOWN,
363
355
  ratchetEnabled: true,
364
356
  ratchetState: RatchetState.IDLE,
365
357
  ratchetActiveSessionId: null,
366
- ratchetLastCiRunId: 'old-snapshot',
358
+ ratchetDispatchSnapshotKey: 'old-snapshot',
367
359
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
368
360
  ratchetDispatchOutcome: null,
369
361
  ratchetDispatchRetryCount: 0,
@@ -384,7 +376,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
384
376
  promptSent: true,
385
377
  });
386
378
  vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockResolvedValue(false);
387
- vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
379
+ vi.mocked(workspaceRatchetService.recordCheckIfEnabled).mockResolvedValue(false);
388
380
  vi.mocked(workspaceDataService.findById).mockResolvedValue({
389
381
  id: 'ws-disable-race-dispatch',
390
382
  ratchetEnabled: false,
@@ -410,11 +402,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
410
402
  prUrl: 'https://github.com/example/repo/pull/44',
411
403
  prNumber: 44,
412
404
  prState: 'OPEN',
405
+ prReviewState: null,
406
+ prHasMergeConflict: false,
413
407
  prCiStatus: CIStatus.UNKNOWN,
414
408
  ratchetEnabled: true,
415
409
  ratchetState: RatchetState.IDLE,
416
410
  ratchetActiveSessionId: null,
417
- ratchetLastCiRunId: '2026-01-01T00:00:00Z',
411
+ ratchetDispatchSnapshotKey: '2026-01-01T00:00:00Z',
418
412
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
419
413
  ratchetDispatchOutcome: null,
420
414
  ratchetDispatchRetryCount: 0,
@@ -455,11 +449,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
455
449
  prUrl: 'https://github.com/example/repo/pull/5',
456
450
  prNumber: 5,
457
451
  prState: 'OPEN',
452
+ prReviewState: null,
453
+ prHasMergeConflict: false,
458
454
  prCiStatus: CIStatus.UNKNOWN,
459
455
  ratchetEnabled: true,
460
456
  ratchetState: RatchetState.READY,
461
457
  ratchetActiveSessionId: null,
462
- ratchetLastCiRunId: '2026-01-02T00:00:00Z',
458
+ ratchetDispatchSnapshotKey: '2026-01-02T00:00:00Z',
463
459
  prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
464
460
  ratchetDispatchOutcome: null,
465
461
  ratchetDispatchRetryCount: 0,
@@ -484,17 +480,188 @@ describe('ratchet service (state-change + idle dispatch)', () => {
484
480
  expect(mockSessionBridge.findSessionsByWorkspaceId).not.toHaveBeenCalled();
485
481
  expect(mockSnapshotBridge.recordReviewCheck).not.toHaveBeenCalled();
486
482
  });
483
+ it('marks the dispatch stalled when a settled dispatch achieved nothing', async () => {
484
+ const workspace = {
485
+ id: 'ws-1',
486
+ prUrl: 'https://github.com/example/repo/pull/5',
487
+ prNumber: 5,
488
+ prState: 'OPEN',
489
+ prReviewState: null,
490
+ prHasMergeConflict: false,
491
+ prCiStatus: CIStatus.UNKNOWN,
492
+ ratchetEnabled: true,
493
+ ratchetState: RatchetState.READY,
494
+ ratchetActiveSessionId: null,
495
+ ratchetDispatchSnapshotKey: '2026-01-02T00:00:00Z',
496
+ prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
497
+ ratchetDispatchOutcome: 'COMPLETED',
498
+ ratchetDispatchRetryCount: 0,
499
+ };
500
+ vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
501
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
502
+ ciStatus: CIStatus.FAILURE,
503
+ snapshotKey: '2026-01-02T00:00:00Z',
504
+ hasChangesRequested: false,
505
+ latestReviewActivityAtMs: null,
506
+ statusCheckRollup: null,
507
+ prState: 'OPEN',
508
+ prNumber: 5,
509
+ });
510
+ vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
511
+ await ratchetService.checkWorkspaceById('ws-1');
512
+ expect(mockWorkspaceBridge.markDispatchStalled).toHaveBeenCalledWith('ws-1', '2026-01-02T00:00:00Z');
513
+ });
514
+ it('marks the dispatch stalled when a DIED fixer exhausts its retries', async () => {
515
+ const workspace = {
516
+ id: 'ws-1',
517
+ prUrl: 'https://github.com/example/repo/pull/15',
518
+ prNumber: 15,
519
+ prState: 'OPEN',
520
+ prReviewState: null,
521
+ prHasMergeConflict: false,
522
+ prCiStatus: CIStatus.FAILURE,
523
+ ratchetEnabled: true,
524
+ ratchetState: RatchetState.CI_FAILED,
525
+ ratchetActiveSessionId: null,
526
+ ratchetDispatchSnapshotKey: 'same-snapshot',
527
+ prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
528
+ ratchetDispatchOutcome: 'DIED',
529
+ ratchetDispatchRetryCount: SERVICE_THRESHOLDS.ratchetDispatchMaxRetries,
530
+ };
531
+ vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
532
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
533
+ ciStatus: CIStatus.FAILURE,
534
+ snapshotKey: 'same-snapshot',
535
+ hasChangesRequested: false,
536
+ latestReviewActivityAtMs: null,
537
+ statusCheckRollup: null,
538
+ prState: 'OPEN',
539
+ prNumber: 15,
540
+ });
541
+ await ratchetService.checkWorkspaceById('ws-1');
542
+ expect(mockWorkspaceBridge.markDispatchStalled).toHaveBeenCalledWith('ws-1', 'same-snapshot');
543
+ });
544
+ it('publishes a dispatch-changed event when the stall flag actually flips', async () => {
545
+ const workspace = {
546
+ id: 'ws-1',
547
+ prUrl: 'https://github.com/example/repo/pull/5',
548
+ prNumber: 5,
549
+ prState: 'OPEN',
550
+ prReviewState: null,
551
+ prHasMergeConflict: false,
552
+ prCiStatus: CIStatus.FAILURE,
553
+ ratchetEnabled: true,
554
+ ratchetState: RatchetState.CI_FAILED,
555
+ ratchetActiveSessionId: null,
556
+ ratchetDispatchSnapshotKey: 'stalled-key',
557
+ prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
558
+ ratchetDispatchOutcome: 'COMPLETED',
559
+ ratchetDispatchRetryCount: 0,
560
+ };
561
+ vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
562
+ vi.mocked(mockWorkspaceBridge.markDispatchStalled).mockResolvedValue(true);
563
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
564
+ ciStatus: CIStatus.FAILURE,
565
+ snapshotKey: 'stalled-key',
566
+ hasChangesRequested: false,
567
+ latestReviewActivityAtMs: null,
568
+ statusCheckRollup: null,
569
+ prState: 'OPEN',
570
+ prNumber: 5,
571
+ });
572
+ vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
573
+ const events = [];
574
+ ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
575
+ events.push(event);
576
+ });
577
+ await ratchetService.checkWorkspaceById('ws-1');
578
+ expect(events).toEqual([{ workspaceId: 'ws-1' }]);
579
+ });
580
+ it('publishes nothing when the stall flag was already set', async () => {
581
+ const workspace = {
582
+ id: 'ws-1',
583
+ prUrl: 'https://github.com/example/repo/pull/5',
584
+ prNumber: 5,
585
+ prState: 'OPEN',
586
+ prReviewState: null,
587
+ prHasMergeConflict: false,
588
+ prCiStatus: CIStatus.FAILURE,
589
+ ratchetEnabled: true,
590
+ ratchetState: RatchetState.CI_FAILED,
591
+ ratchetActiveSessionId: null,
592
+ ratchetDispatchSnapshotKey: 'stalled-key',
593
+ prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
594
+ ratchetDispatchOutcome: 'COMPLETED',
595
+ ratchetDispatchRetryCount: 0,
596
+ };
597
+ vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
598
+ vi.mocked(mockWorkspaceBridge.markDispatchStalled).mockResolvedValue(false);
599
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
600
+ ciStatus: CIStatus.FAILURE,
601
+ snapshotKey: 'stalled-key',
602
+ hasChangesRequested: false,
603
+ latestReviewActivityAtMs: null,
604
+ statusCheckRollup: null,
605
+ prState: 'OPEN',
606
+ prNumber: 5,
607
+ });
608
+ vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
609
+ const events = [];
610
+ ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
611
+ events.push(event);
612
+ });
613
+ await ratchetService.checkWorkspaceById('ws-1');
614
+ expect(events).toEqual([]);
615
+ });
616
+ it('does not mark the dispatch stalled when the PR state has changed', async () => {
617
+ const workspace = {
618
+ id: 'ws-1',
619
+ prUrl: 'https://github.com/example/repo/pull/5',
620
+ prNumber: 5,
621
+ prState: 'OPEN',
622
+ prReviewState: null,
623
+ prHasMergeConflict: false,
624
+ prCiStatus: CIStatus.UNKNOWN,
625
+ ratchetEnabled: true,
626
+ ratchetState: RatchetState.READY,
627
+ ratchetActiveSessionId: null,
628
+ ratchetDispatchSnapshotKey: 'old-snapshot',
629
+ prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
630
+ ratchetDispatchOutcome: null,
631
+ ratchetDispatchRetryCount: 0,
632
+ };
633
+ vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
634
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
635
+ ciStatus: CIStatus.FAILURE,
636
+ snapshotKey: '2026-01-02T00:00:00Z',
637
+ hasChangesRequested: false,
638
+ latestReviewActivityAtMs: null,
639
+ statusCheckRollup: null,
640
+ prState: 'OPEN',
641
+ prNumber: 5,
642
+ });
643
+ vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
644
+ vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
645
+ status: 'started',
646
+ sessionId: 'fresh-session',
647
+ promptSent: true,
648
+ });
649
+ await ratchetService.checkWorkspaceById('ws-1');
650
+ expect(mockWorkspaceBridge.markDispatchStalled).not.toHaveBeenCalled();
651
+ });
487
652
  it('does not dispatch repeatedly for unchanged CHANGES_REQUESTED state', async () => {
488
653
  const workspace = {
489
654
  id: 'ws-review-unchanged',
490
655
  prUrl: 'https://github.com/example/repo/pull/55',
491
656
  prNumber: 55,
492
657
  prState: 'OPEN',
658
+ prReviewState: null,
659
+ prHasMergeConflict: false,
493
660
  prCiStatus: CIStatus.UNKNOWN,
494
661
  ratchetEnabled: true,
495
662
  ratchetState: RatchetState.REVIEW_PENDING,
496
663
  ratchetActiveSessionId: null,
497
- ratchetLastCiRunId: 'ci:SUCCESS|changes-requested:1735776000000',
664
+ ratchetDispatchSnapshotKey: 'ci:SUCCESS|changes-requested:1735776000000',
498
665
  prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
499
666
  ratchetDispatchOutcome: null,
500
667
  ratchetDispatchRetryCount: 0,
@@ -535,11 +702,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
535
702
  prUrl: 'https://github.com/example/repo/pull/56',
536
703
  prNumber: 56,
537
704
  prState: 'OPEN',
705
+ prReviewState: null,
706
+ prHasMergeConflict: false,
538
707
  prCiStatus: CIStatus.UNKNOWN,
539
708
  ratchetEnabled: true,
540
709
  ratchetState: RatchetState.REVIEW_PENDING,
541
710
  ratchetActiveSessionId: null,
542
- ratchetLastCiRunId: 'ci:SUCCESS|changes-requested:old',
711
+ ratchetDispatchSnapshotKey: 'ci:SUCCESS|changes-requested:old',
543
712
  prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
544
713
  ratchetDispatchOutcome: null,
545
714
  ratchetDispatchRetryCount: 0,
@@ -573,11 +742,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
573
742
  prUrl: 'https://github.com/example/repo/pull/57',
574
743
  prNumber: 57,
575
744
  prState: 'OPEN',
745
+ prReviewState: null,
746
+ prHasMergeConflict: false,
576
747
  prCiStatus: CIStatus.UNKNOWN,
577
748
  ratchetEnabled: true,
578
749
  ratchetState: RatchetState.READY,
579
750
  ratchetActiveSessionId: null,
580
- ratchetLastCiRunId: 'ci:SUCCESS|no-changes-requested:old|merge:clean',
751
+ ratchetDispatchSnapshotKey: 'ci:SUCCESS|no-changes-requested:old|merge:clean',
581
752
  prReviewLastCheckedAt: new Date('2026-01-02T00:00:00Z'),
582
753
  ratchetDispatchOutcome: null,
583
754
  ratchetDispatchRetryCount: 0,
@@ -639,11 +810,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
639
810
  prUrl: 'https://github.com/example/repo/pull/7',
640
811
  prNumber: 7,
641
812
  prState: 'OPEN',
813
+ prReviewState: null,
814
+ prHasMergeConflict: false,
642
815
  prCiStatus: CIStatus.UNKNOWN,
643
816
  ratchetEnabled: true,
644
817
  ratchetState: RatchetState.IDLE,
645
818
  ratchetActiveSessionId: null,
646
- ratchetLastCiRunId: null,
819
+ ratchetDispatchSnapshotKey: null,
647
820
  prReviewLastCheckedAt: null,
648
821
  ratchetDispatchOutcome: null,
649
822
  ratchetDispatchRetryCount: 0,
@@ -678,7 +851,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
678
851
  expect(result).toMatchObject({
679
852
  action: { type: 'ERROR', error: 'Failed to deliver initial ratchet prompt' },
680
853
  });
681
- expect(workspaceRatchetService.clearActiveSession).toHaveBeenCalledWith(workspace.id);
854
+ expect(workspaceRatchetService.clearActiveSession).toHaveBeenCalledWith(workspace.id, 'ratchet-session');
682
855
  expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('ratchet-session');
683
856
  });
684
857
  it('routes an aborted prompt-failure path through orphan cleanup', async () => {
@@ -735,11 +908,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
735
908
  prUrl: 'https://github.com/example/repo/pull/8',
736
909
  prNumber: 8,
737
910
  prState: 'OPEN',
911
+ prReviewState: null,
912
+ prHasMergeConflict: false,
738
913
  prCiStatus: CIStatus.UNKNOWN,
739
914
  ratchetEnabled: true,
740
915
  ratchetState: RatchetState.READY,
741
916
  ratchetActiveSessionId: null,
742
- ratchetLastCiRunId: '2026-01-01T00:00:00Z',
917
+ ratchetDispatchSnapshotKey: '2026-01-01T00:00:00Z',
743
918
  prReviewLastCheckedAt: recentCheck,
744
919
  ratchetDispatchOutcome: null,
745
920
  ratchetDispatchRetryCount: 0,
@@ -771,11 +946,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
771
946
  prUrl: 'https://github.com/example/repo/pull/43',
772
947
  prNumber: 43,
773
948
  prState: 'OPEN',
949
+ prReviewState: null,
950
+ prHasMergeConflict: false,
774
951
  prCiStatus: CIStatus.FAILURE,
775
952
  ratchetEnabled: true,
776
953
  ratchetState: RatchetState.CI_FAILED,
777
954
  ratchetActiveSessionId: null,
778
- ratchetLastCiRunId: 'failed-snapshot',
955
+ ratchetDispatchSnapshotKey: 'failed-snapshot',
779
956
  prReviewLastCheckedAt: recentCheck,
780
957
  ratchetDispatchOutcome: 'COMPLETED',
781
958
  ratchetDispatchRetryCount: 0,
@@ -821,11 +998,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
821
998
  prUrl: 'https://github.com/example/repo/pull/41',
822
999
  prNumber: 41,
823
1000
  prState: 'OPEN',
1001
+ prReviewState: null,
1002
+ prHasMergeConflict: false,
824
1003
  prCiStatus: CIStatus.UNKNOWN,
825
1004
  ratchetEnabled: true,
826
1005
  ratchetState: RatchetState.READY,
827
1006
  ratchetActiveSessionId: null,
828
- ratchetLastCiRunId: 'old-snapshot',
1007
+ ratchetDispatchSnapshotKey: 'old-snapshot',
829
1008
  prReviewLastCheckedAt: recentCheck,
830
1009
  ratchetDispatchOutcome: null,
831
1010
  ratchetDispatchRetryCount: 0,
@@ -839,7 +1018,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
839
1018
  prState: 'OPEN',
840
1019
  prNumber: 41,
841
1020
  });
842
- vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
1021
+ vi.mocked(workspaceRatchetService.recordCheckIfEnabled).mockResolvedValue(false);
843
1022
  vi.mocked(workspaceDataService.findById).mockResolvedValue({
844
1023
  id: 'ws-disable-race-state',
845
1024
  ratchetEnabled: false,
@@ -857,55 +1036,195 @@ describe('ratchet service (state-change + idle dispatch)', () => {
857
1036
  expect(events).toHaveLength(0);
858
1037
  ratchetService.removeAllListeners();
859
1038
  });
860
- it('reports a concurrent state change without emitting when the check loses the CAS while still enabled', async () => {
861
- const recentCheck = new Date();
1039
+ it('persists PR state and review decision the check observed, not just CI', async () => {
862
1040
  const workspace = {
863
- id: 'ws-superseded',
864
- prUrl: 'https://github.com/example/repo/pull/42',
865
- prNumber: 42,
1041
+ id: 'ws-observation',
1042
+ prUrl: 'https://github.com/example/repo/pull/44',
1043
+ prNumber: 44,
866
1044
  prState: 'OPEN',
867
- prCiStatus: CIStatus.UNKNOWN,
1045
+ prReviewState: null,
1046
+ prHasMergeConflict: false,
1047
+ prCiStatus: CIStatus.SUCCESS,
868
1048
  ratchetEnabled: true,
869
- ratchetState: RatchetState.CI_RUNNING,
1049
+ ratchetState: RatchetState.READY,
870
1050
  ratchetActiveSessionId: null,
871
- ratchetLastCiRunId: 'old-snapshot',
872
- prReviewLastCheckedAt: recentCheck,
1051
+ ratchetDispatchSnapshotKey: 'observation-snapshot',
1052
+ prReviewLastCheckedAt: null,
873
1053
  ratchetDispatchOutcome: null,
874
1054
  ratchetDispatchRetryCount: 0,
875
1055
  };
876
1056
  vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
877
1057
  ciStatus: CIStatus.SUCCESS,
878
- snapshotKey: 'new-snapshot',
879
- hasChangesRequested: false,
880
- latestReviewActivityAtMs: recentCheck.getTime() - 1000,
1058
+ snapshotKey: 'observation-snapshot',
1059
+ hasChangesRequested: true,
1060
+ hasMergeConflict: false,
1061
+ latestReviewActivityAtMs: null,
881
1062
  statusCheckRollup: null,
882
1063
  prState: 'OPEN',
883
- prNumber: 42,
884
- });
885
- vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
886
- vi.mocked(workspaceDataService.findById).mockResolvedValue({
887
- id: 'ws-superseded',
888
- ratchetEnabled: true,
889
- ratchetState: RatchetState.IDLE,
1064
+ cachedPrState: 'CHANGES_REQUESTED',
1065
+ reviewDecision: 'CHANGES_REQUESTED',
1066
+ prNumber: 44,
1067
+ reviewComments: [],
890
1068
  });
891
1069
  vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
892
- const events = [];
893
- ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
894
- events.push(event);
1070
+ await unsafeCoerce(ratchetService).processWorkspace(workspace);
1071
+ expect(mockSnapshotBridge.recordPrObservation).toHaveBeenCalledWith(expect.objectContaining({
1072
+ workspaceId: 'ws-observation',
1073
+ prState: 'CHANGES_REQUESTED',
1074
+ reviewState: 'CHANGES_REQUESTED',
1075
+ ciStatus: CIStatus.SUCCESS,
1076
+ hasMergeConflict: false,
1077
+ }));
1078
+ });
1079
+ it('stops live ratchet sessions before persisting a merged PR', async () => {
1080
+ const workspace = {
1081
+ id: 'ws-merged',
1082
+ prUrl: 'https://github.com/example/repo/pull/45',
1083
+ prNumber: 45,
1084
+ prState: 'OPEN',
1085
+ prReviewState: null,
1086
+ prHasMergeConflict: false,
1087
+ prCiStatus: CIStatus.SUCCESS,
1088
+ ratchetEnabled: true,
1089
+ ratchetState: RatchetState.READY,
1090
+ ratchetActiveSessionId: null,
1091
+ ratchetDispatchSnapshotKey: 'merged-snapshot',
1092
+ prReviewLastCheckedAt: null,
1093
+ ratchetDispatchOutcome: null,
1094
+ ratchetDispatchRetryCount: 0,
1095
+ };
1096
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
1097
+ ciStatus: CIStatus.SUCCESS,
1098
+ snapshotKey: 'merged-snapshot',
1099
+ hasChangesRequested: false,
1100
+ hasMergeConflict: false,
1101
+ latestReviewActivityAtMs: null,
1102
+ statusCheckRollup: null,
1103
+ prState: 'MERGED',
1104
+ cachedPrState: 'MERGED',
1105
+ reviewDecision: null,
1106
+ prNumber: 45,
1107
+ reviewComments: [],
895
1108
  });
1109
+ vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([
1110
+ {
1111
+ id: 'ratchet-running',
1112
+ workflow: 'ratchet',
1113
+ status: SessionStatus.RUNNING,
1114
+ },
1115
+ {
1116
+ id: 'ratchet-idle',
1117
+ workflow: 'ratchet',
1118
+ status: SessionStatus.IDLE,
1119
+ },
1120
+ {
1121
+ id: 'ratchet-completed',
1122
+ workflow: 'ratchet',
1123
+ status: SessionStatus.COMPLETED,
1124
+ },
1125
+ {
1126
+ id: 'manual-running',
1127
+ workflow: 'default',
1128
+ status: SessionStatus.RUNNING,
1129
+ },
1130
+ ]);
1131
+ vi.mocked(mockSessionBridge.isSessionRunning).mockImplementation((sessionId) => ['ratchet-running', 'ratchet-idle', 'manual-running'].includes(sessionId));
896
1132
  const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
897
- expect(workspaceRatchetService.transitionStateIfEnabled).toHaveBeenCalledWith('ws-superseded', RatchetState.CI_RUNNING, expect.objectContaining({ ratchetState: RatchetState.READY }));
1133
+ expect(mockSessionBridge.stopSession).toHaveBeenCalledTimes(2);
1134
+ expect(mockSessionBridge.stopSession).toHaveBeenNthCalledWith(1, 'ratchet-running');
1135
+ expect(mockSessionBridge.stopSession).toHaveBeenNthCalledWith(2, 'ratchet-idle');
1136
+ expect(mockSnapshotBridge.recordPrObservation).toHaveBeenCalledWith(expect.objectContaining({ workspaceId: 'ws-merged', prState: 'MERGED' }));
1137
+ expect(vi.mocked(mockSessionBridge.stopSession).mock.invocationCallOrder.at(-1)).toBeLessThan(vi.mocked(mockSnapshotBridge.recordPrObservation).mock.invocationCallOrder[0] ?? 0);
898
1138
  expect(result).toMatchObject({
899
- previousState: RatchetState.CI_RUNNING,
900
- newState: RatchetState.CI_RUNNING,
901
- action: {
902
- type: 'WAITING',
903
- reason: 'Ratchet state changed concurrently during this check; re-evaluating next cycle',
1139
+ newState: RatchetState.MERGED,
1140
+ action: { type: 'COMPLETED' },
1141
+ });
1142
+ });
1143
+ it('does not persist a merged PR when stopping a ratchet session fails', async () => {
1144
+ const workspace = {
1145
+ id: 'ws-merged-stop-failure',
1146
+ prUrl: 'https://github.com/example/repo/pull/46',
1147
+ prNumber: 46,
1148
+ prState: 'OPEN',
1149
+ prReviewState: null,
1150
+ prHasMergeConflict: false,
1151
+ prCiStatus: CIStatus.SUCCESS,
1152
+ ratchetEnabled: true,
1153
+ ratchetState: RatchetState.READY,
1154
+ ratchetActiveSessionId: 'ratchet-running',
1155
+ ratchetDispatchSnapshotKey: 'merged-stop-failure-snapshot',
1156
+ prReviewLastCheckedAt: null,
1157
+ ratchetDispatchOutcome: 'RUNNING',
1158
+ ratchetDispatchRetryCount: 0,
1159
+ };
1160
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
1161
+ ciStatus: CIStatus.SUCCESS,
1162
+ snapshotKey: 'merged-stop-failure-snapshot',
1163
+ hasChangesRequested: false,
1164
+ hasMergeConflict: false,
1165
+ latestReviewActivityAtMs: null,
1166
+ statusCheckRollup: null,
1167
+ prState: 'MERGED',
1168
+ cachedPrState: 'MERGED',
1169
+ reviewDecision: null,
1170
+ prNumber: 46,
1171
+ reviewComments: [],
1172
+ });
1173
+ vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([
1174
+ {
1175
+ id: 'ratchet-running',
1176
+ workflow: 'ratchet',
1177
+ status: SessionStatus.RUNNING,
904
1178
  },
1179
+ ]);
1180
+ vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
1181
+ vi.mocked(mockSessionBridge.stopSession).mockRejectedValue(new Error('stop failed'));
1182
+ const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
1183
+ expect(result).toMatchObject({
1184
+ previousState: RatchetState.READY,
1185
+ newState: RatchetState.READY,
1186
+ action: { type: 'ERROR', error: 'stop failed' },
905
1187
  });
906
- expect(events).toHaveLength(0);
907
- expect(mockSnapshotBridge.recordCIObservation).not.toHaveBeenCalled();
908
- expect(mockSnapshotBridge.recordReviewCheck).not.toHaveBeenCalled();
1188
+ expect(workspaceRatchetService.recordCheckIfEnabled).not.toHaveBeenCalled();
1189
+ expect(mockSnapshotBridge.recordPrObservation).not.toHaveBeenCalled();
1190
+ });
1191
+ it('persists a newly observed merge conflict even when CI status is unchanged', async () => {
1192
+ const workspace = {
1193
+ id: 'ws-conflict',
1194
+ prUrl: 'https://github.com/example/repo/pull/43',
1195
+ prNumber: 43,
1196
+ prState: 'OPEN',
1197
+ prReviewState: null,
1198
+ prHasMergeConflict: false,
1199
+ prCiStatus: CIStatus.SUCCESS,
1200
+ ratchetEnabled: true,
1201
+ ratchetState: RatchetState.READY,
1202
+ ratchetActiveSessionId: null,
1203
+ ratchetDispatchSnapshotKey: 'conflict-snapshot',
1204
+ prReviewLastCheckedAt: null,
1205
+ ratchetDispatchOutcome: null,
1206
+ ratchetDispatchRetryCount: 0,
1207
+ };
1208
+ vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
1209
+ ciStatus: CIStatus.SUCCESS,
1210
+ snapshotKey: 'conflict-snapshot',
1211
+ hasChangesRequested: false,
1212
+ hasMergeConflict: true,
1213
+ latestReviewActivityAtMs: null,
1214
+ statusCheckRollup: null,
1215
+ prState: 'OPEN',
1216
+ cachedPrState: 'OPEN',
1217
+ reviewDecision: null,
1218
+ prNumber: 43,
1219
+ reviewComments: [],
1220
+ });
1221
+ vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
1222
+ await unsafeCoerce(ratchetService).processWorkspace(workspace);
1223
+ expect(mockSnapshotBridge.recordPrObservation).toHaveBeenCalledWith(expect.objectContaining({
1224
+ workspaceId: 'ws-conflict',
1225
+ ciStatus: CIStatus.SUCCESS,
1226
+ hasMergeConflict: true,
1227
+ }));
909
1228
  });
910
1229
  it('redispatches with an incremented retry count when the previous fixer died', async () => {
911
1230
  const workspace = {
@@ -913,11 +1232,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
913
1232
  prUrl: 'https://github.com/example/repo/pull/13',
914
1233
  prNumber: 13,
915
1234
  prState: 'OPEN',
1235
+ prReviewState: null,
1236
+ prHasMergeConflict: false,
916
1237
  prCiStatus: CIStatus.FAILURE,
917
1238
  ratchetEnabled: true,
918
1239
  ratchetState: RatchetState.CI_FAILED,
919
1240
  ratchetActiveSessionId: null,
920
- ratchetLastCiRunId: 'same-snapshot',
1241
+ ratchetDispatchSnapshotKey: 'same-snapshot',
921
1242
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
922
1243
  ratchetDispatchOutcome: 'DIED',
923
1244
  ratchetDispatchRetryCount: 1,
@@ -954,11 +1275,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
954
1275
  prUrl: 'https://github.com/example/repo/pull/14',
955
1276
  prNumber: 14,
956
1277
  prState: 'OPEN',
1278
+ prReviewState: null,
1279
+ prHasMergeConflict: false,
957
1280
  prCiStatus: CIStatus.SUCCESS,
958
1281
  ratchetEnabled: true,
959
1282
  ratchetState: RatchetState.READY,
960
1283
  ratchetActiveSessionId: null,
961
- ratchetLastCiRunId: 'clean-snapshot',
1284
+ ratchetDispatchSnapshotKey: 'clean-snapshot',
962
1285
  prReviewLastCheckedAt: checkedAt,
963
1286
  ratchetDispatchOutcome: 'DIED',
964
1287
  ratchetDispatchRetryCount: 0,
@@ -1000,11 +1323,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1000
1323
  prUrl: 'https://github.com/example/repo/pull/15',
1001
1324
  prNumber: 15,
1002
1325
  prState: 'OPEN',
1326
+ prReviewState: null,
1327
+ prHasMergeConflict: false,
1003
1328
  prCiStatus: CIStatus.FAILURE,
1004
1329
  ratchetEnabled: true,
1005
1330
  ratchetState: RatchetState.CI_FAILED,
1006
1331
  ratchetActiveSessionId: null,
1007
- ratchetLastCiRunId: 'same-snapshot',
1332
+ ratchetDispatchSnapshotKey: 'same-snapshot',
1008
1333
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1009
1334
  ratchetDispatchOutcome: 'DIED',
1010
1335
  ratchetDispatchRetryCount: 3,
@@ -1033,11 +1358,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1033
1358
  prUrl: 'https://github.com/example/repo/pull/16',
1034
1359
  prNumber: 16,
1035
1360
  prState: 'OPEN',
1361
+ prReviewState: null,
1362
+ prHasMergeConflict: false,
1036
1363
  prCiStatus: CIStatus.FAILURE,
1037
1364
  ratchetEnabled: true,
1038
1365
  ratchetState: RatchetState.CI_FAILED,
1039
1366
  ratchetActiveSessionId: null,
1040
- ratchetLastCiRunId: 'old-snapshot',
1367
+ ratchetDispatchSnapshotKey: 'old-snapshot',
1041
1368
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1042
1369
  ratchetDispatchOutcome: 'DIED',
1043
1370
  ratchetDispatchRetryCount: 3,
@@ -1069,11 +1396,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1069
1396
  prUrl: 'https://github.com/example/repo/pull/17',
1070
1397
  prNumber: 17,
1071
1398
  prState: 'OPEN',
1399
+ prReviewState: null,
1400
+ prHasMergeConflict: false,
1072
1401
  prCiStatus: CIStatus.FAILURE,
1073
1402
  ratchetEnabled: true,
1074
1403
  ratchetState: RatchetState.CI_FAILED,
1075
1404
  ratchetActiveSessionId: null,
1076
- ratchetLastCiRunId: 'same-snapshot',
1405
+ ratchetDispatchSnapshotKey: 'same-snapshot',
1077
1406
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1078
1407
  ratchetDispatchOutcome: 'COMPLETED',
1079
1408
  ratchetDispatchRetryCount: 2,
@@ -1106,11 +1435,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1106
1435
  prUrl: 'https://github.com/example/repo/pull/456',
1107
1436
  prNumber: 456,
1108
1437
  prState: 'OPEN',
1438
+ prReviewState: null,
1439
+ prHasMergeConflict: false,
1109
1440
  prCiStatus: CIStatus.SUCCESS,
1110
1441
  ratchetEnabled: true,
1111
1442
  ratchetState: RatchetState.MERGE_CONFLICT,
1112
1443
  ratchetActiveSessionId: null,
1113
- ratchetLastCiRunId: previousSnapshotKey,
1444
+ ratchetDispatchSnapshotKey: previousSnapshotKey,
1114
1445
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1115
1446
  ratchetDispatchOutcome: 'COMPLETED',
1116
1447
  ratchetDispatchRetryCount: 2,
@@ -1147,11 +1478,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1147
1478
  prUrl: 'https://github.com/example/repo/pull/9',
1148
1479
  prNumber: 9,
1149
1480
  prState: 'OPEN',
1481
+ prReviewState: null,
1482
+ prHasMergeConflict: false,
1150
1483
  prCiStatus: CIStatus.UNKNOWN,
1151
1484
  ratchetEnabled: true,
1152
1485
  ratchetState: RatchetState.CI_FAILED,
1153
1486
  ratchetActiveSessionId: 'ratchet-session',
1154
- ratchetLastCiRunId: 'previous-snapshot-key',
1487
+ ratchetDispatchSnapshotKey: 'previous-snapshot-key',
1155
1488
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1156
1489
  ratchetDispatchOutcome: 'RUNNING',
1157
1490
  ratchetDispatchRetryCount: 0,
@@ -1172,11 +1505,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1172
1505
  prUrl: 'https://github.com/example/repo/pull/12',
1173
1506
  prNumber: 12,
1174
1507
  prState: 'OPEN',
1508
+ prReviewState: null,
1509
+ prHasMergeConflict: false,
1175
1510
  prCiStatus: CIStatus.UNKNOWN,
1176
1511
  ratchetEnabled: true,
1177
1512
  ratchetState: RatchetState.CI_FAILED,
1178
1513
  ratchetActiveSessionId: 'deleted-session',
1179
- ratchetLastCiRunId: 'previous-snapshot-key',
1514
+ ratchetDispatchSnapshotKey: 'previous-snapshot-key',
1180
1515
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1181
1516
  ratchetDispatchOutcome: 'RUNNING',
1182
1517
  ratchetDispatchRetryCount: 0,
@@ -1197,11 +1532,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1197
1532
  prUrl: 'https://github.com/example/repo/pull/12',
1198
1533
  prNumber: 12,
1199
1534
  prState: 'OPEN',
1535
+ prReviewState: null,
1536
+ prHasMergeConflict: false,
1200
1537
  prCiStatus: CIStatus.UNKNOWN,
1201
1538
  ratchetEnabled: true,
1202
1539
  ratchetState: RatchetState.CI_FAILED,
1203
1540
  ratchetActiveSessionId: 'finished-session',
1204
- ratchetLastCiRunId: 'previous-snapshot-key',
1541
+ ratchetDispatchSnapshotKey: 'previous-snapshot-key',
1205
1542
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1206
1543
  ratchetDispatchOutcome: 'RUNNING',
1207
1544
  ratchetDispatchRetryCount: 0,
@@ -1222,11 +1559,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1222
1559
  prUrl: 'https://github.com/example/repo/pull/12',
1223
1560
  prNumber: 12,
1224
1561
  prState: 'OPEN',
1562
+ prReviewState: null,
1563
+ prHasMergeConflict: false,
1225
1564
  prCiStatus: CIStatus.UNKNOWN,
1226
1565
  ratchetEnabled: true,
1227
1566
  ratchetState: RatchetState.CI_FAILED,
1228
1567
  ratchetActiveSessionId: 'finished-session',
1229
- ratchetLastCiRunId: 'previous-snapshot-key',
1568
+ ratchetDispatchSnapshotKey: 'previous-snapshot-key',
1230
1569
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1231
1570
  ratchetDispatchOutcome: 'RUNNING',
1232
1571
  ratchetDispatchRetryCount: 0,
@@ -1257,11 +1596,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1257
1596
  prUrl: 'https://github.com/example/repo/pull/11',
1258
1597
  prNumber: 11,
1259
1598
  prState: 'OPEN',
1599
+ prReviewState: null,
1600
+ prHasMergeConflict: false,
1260
1601
  prCiStatus: CIStatus.UNKNOWN,
1261
1602
  ratchetEnabled: true,
1262
1603
  ratchetState: RatchetState.CI_FAILED,
1263
1604
  ratchetActiveSessionId: 'ratchet-session',
1264
- ratchetLastCiRunId: 'snapshot-key',
1605
+ ratchetDispatchSnapshotKey: 'snapshot-key',
1265
1606
  prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
1266
1607
  ratchetDispatchOutcome: 'RUNNING',
1267
1608
  ratchetDispatchRetryCount: 0,
@@ -1327,11 +1668,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1327
1668
  prUrl: 'https://github.com/example/repo/pull/10',
1328
1669
  prNumber: 10,
1329
1670
  prState: 'OPEN',
1671
+ prReviewState: null,
1672
+ prHasMergeConflict: false,
1330
1673
  prCiStatus: CIStatus.UNKNOWN,
1331
1674
  ratchetEnabled: true,
1332
1675
  ratchetState: RatchetState.READY,
1333
1676
  ratchetActiveSessionId: null,
1334
- ratchetLastCiRunId: 'prev-snapshot',
1677
+ ratchetDispatchSnapshotKey: 'prev-snapshot',
1335
1678
  prReviewLastCheckedAt: null,
1336
1679
  ratchetDispatchOutcome: null,
1337
1680
  ratchetDispatchRetryCount: 0,
@@ -1543,7 +1886,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1543
1886
  ratchetEnabled: true,
1544
1887
  ratchetState: RatchetState.IDLE,
1545
1888
  ratchetActiveSessionId: null,
1546
- ratchetLastCiRunId: null,
1889
+ ratchetDispatchSnapshotKey: null,
1547
1890
  prReviewLastCheckedAt: null,
1548
1891
  ratchetDispatchOutcome: null,
1549
1892
  ratchetDispatchRetryCount: 0,
@@ -1563,7 +1906,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1563
1906
  ratchetEnabled: true,
1564
1907
  ratchetState: RatchetState.IDLE,
1565
1908
  ratchetActiveSessionId: null,
1566
- ratchetLastCiRunId: null,
1909
+ ratchetDispatchSnapshotKey: null,
1567
1910
  prReviewLastCheckedAt: null,
1568
1911
  ratchetDispatchOutcome: null,
1569
1912
  ratchetDispatchRetryCount: 0,
@@ -1577,7 +1920,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1577
1920
  expect(workspaceRatchetService.clearActiveSession).not.toHaveBeenCalled();
1578
1921
  });
1579
1922
  it('returns WAITING when shutting down', async () => {
1580
- unsafeCoerce(ratchetService).isShuttingDown = true;
1923
+ setRatchetShuttingDown(true);
1581
1924
  const workspace = {
1582
1925
  id: 'ws-shutdown',
1583
1926
  prUrl: 'https://github.com/example/repo/pull/1',
@@ -1585,7 +1928,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1585
1928
  ratchetEnabled: true,
1586
1929
  ratchetState: RatchetState.CI_FAILED,
1587
1930
  ratchetActiveSessionId: null,
1588
- ratchetLastCiRunId: null,
1931
+ ratchetDispatchSnapshotKey: null,
1589
1932
  prReviewLastCheckedAt: null,
1590
1933
  ratchetDispatchOutcome: null,
1591
1934
  ratchetDispatchRetryCount: 0,
@@ -1605,7 +1948,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1605
1948
  ratchetEnabled: true,
1606
1949
  ratchetState: RatchetState.CI_FAILED,
1607
1950
  ratchetActiveSessionId: null,
1608
- ratchetLastCiRunId: null,
1951
+ ratchetDispatchSnapshotKey: null,
1609
1952
  prReviewLastCheckedAt: null,
1610
1953
  ratchetDispatchOutcome: null,
1611
1954
  ratchetDispatchRetryCount: 0,
@@ -1621,7 +1964,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1621
1964
  });
1622
1965
  describe('checkAllWorkspaces', () => {
1623
1966
  it('returns zero counts when shutting down', async () => {
1624
- unsafeCoerce(ratchetService).isShuttingDown = true;
1967
+ setRatchetShuttingDown(true);
1625
1968
  const result = await ratchetService.checkAllWorkspaces();
1626
1969
  expect(result).toEqual({ checked: 0, stateChanges: 0, actionsTriggered: 0, results: [] });
1627
1970
  });
@@ -1636,11 +1979,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1636
1979
  prUrl: `https://github.com/example/repo/pull/${id}`,
1637
1980
  prNumber: 1,
1638
1981
  prState: 'OPEN',
1982
+ prReviewState: null,
1983
+ prHasMergeConflict: false,
1639
1984
  prCiStatus: CIStatus.UNKNOWN,
1640
1985
  ratchetEnabled: true,
1641
1986
  ratchetState: RatchetState.IDLE,
1642
1987
  ratchetActiveSessionId: null,
1643
- ratchetLastCiRunId: null,
1988
+ ratchetDispatchSnapshotKey: null,
1644
1989
  prReviewLastCheckedAt: null,
1645
1990
  ratchetDispatchOutcome: null,
1646
1991
  ratchetDispatchRetryCount: 0,
@@ -1665,7 +2010,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1665
2010
  ratchetEnabled: true,
1666
2011
  ratchetState: RatchetState.IDLE,
1667
2012
  ratchetActiveSessionId: null,
1668
- ratchetLastCiRunId: null,
2013
+ ratchetDispatchSnapshotKey: null,
1669
2014
  prReviewLastCheckedAt: null,
1670
2015
  ratchetDispatchOutcome: null,
1671
2016
  ratchetDispatchRetryCount: 0,
@@ -1681,7 +2026,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1681
2026
  ratchetEnabled: true,
1682
2027
  ratchetState: RatchetState.CI_RUNNING,
1683
2028
  ratchetActiveSessionId: null,
1684
- ratchetLastCiRunId: null,
2029
+ ratchetDispatchSnapshotKey: null,
1685
2030
  prReviewLastCheckedAt: null,
1686
2031
  ratchetDispatchOutcome: null,
1687
2032
  ratchetDispatchRetryCount: 0,
@@ -1723,13 +2068,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1723
2068
  prUrl: `https://github.com/example/repo/pull/${index + 1}`,
1724
2069
  prNumber: index + 1,
1725
2070
  prState: 'OPEN',
2071
+ prReviewState: null,
2072
+ prHasMergeConflict: false,
1726
2073
  prCiStatus: CIStatus.UNKNOWN,
1727
2074
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
1728
2075
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
1729
2076
  ratchetEnabled: true,
1730
2077
  ratchetState: RatchetState.IDLE,
1731
2078
  ratchetActiveSessionId: null,
1732
- ratchetLastCiRunId: null,
2079
+ ratchetDispatchSnapshotKey: null,
1733
2080
  prReviewLastCheckedAt: null,
1734
2081
  ratchetDispatchOutcome: null,
1735
2082
  ratchetDispatchRetryCount: 0,
@@ -1796,13 +2143,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1796
2143
  prUrl: `https://github.com/example/repo/pull/${index + 1}`,
1797
2144
  prNumber: index + 1,
1798
2145
  prState: 'OPEN',
2146
+ prReviewState: null,
2147
+ prHasMergeConflict: false,
1799
2148
  prCiStatus: CIStatus.UNKNOWN,
1800
2149
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
1801
2150
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
1802
2151
  ratchetEnabled: true,
1803
2152
  ratchetState: RatchetState.IDLE,
1804
2153
  ratchetActiveSessionId: null,
1805
- ratchetLastCiRunId: null,
2154
+ ratchetDispatchSnapshotKey: null,
1806
2155
  prReviewLastCheckedAt: null,
1807
2156
  ratchetDispatchOutcome: null,
1808
2157
  ratchetDispatchRetryCount: 0,
@@ -1852,98 +2201,10 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1852
2201
  vi.useRealTimers();
1853
2202
  });
1854
2203
  });
1855
- describe('markPrClosed', () => {
2204
+ describe('check abort safety', () => {
1856
2205
  afterEach(() => {
1857
2206
  ratchetService.removeAllListeners();
1858
2207
  });
1859
- it('resets ratchet state to IDLE via CAS on fromState and emits a state change', async () => {
1860
- vi.mocked(workspaceDataService.findById).mockResolvedValue({
1861
- id: 'ws-closed',
1862
- ratchetEnabled: true,
1863
- ratchetState: RatchetState.CI_FAILED,
1864
- });
1865
- vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(true);
1866
- const stateEvents = [];
1867
- ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
1868
- stateEvents.push(event);
1869
- });
1870
- await ratchetService.markPrClosed('ws-closed');
1871
- expect(workspaceRatchetService.transitionStateIfEnabled).toHaveBeenCalledWith('ws-closed', RatchetState.CI_FAILED, {
1872
- ratchetState: RatchetState.IDLE,
1873
- ratchetLastCheckedAt: expect.any(Date),
1874
- });
1875
- expect(stateEvents).toEqual([
1876
- {
1877
- workspaceId: 'ws-closed',
1878
- fromState: RatchetState.CI_FAILED,
1879
- toState: RatchetState.IDLE,
1880
- },
1881
- ]);
1882
- });
1883
- it('emits the fromState that actually won the compare-and-swap after losing a race', async () => {
1884
- vi.mocked(workspaceDataService.findById)
1885
- .mockResolvedValueOnce({
1886
- id: 'ws-closed',
1887
- ratchetEnabled: true,
1888
- ratchetState: RatchetState.CI_FAILED,
1889
- })
1890
- .mockResolvedValueOnce({
1891
- id: 'ws-closed',
1892
- ratchetEnabled: true,
1893
- ratchetState: RatchetState.CI_RUNNING,
1894
- });
1895
- vi.mocked(workspaceRatchetService.transitionStateIfEnabled)
1896
- .mockResolvedValueOnce(false)
1897
- .mockResolvedValueOnce(true);
1898
- const stateEvents = [];
1899
- ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
1900
- stateEvents.push(event);
1901
- });
1902
- await ratchetService.markPrClosed('ws-closed');
1903
- expect(workspaceRatchetService.transitionStateIfEnabled).toHaveBeenNthCalledWith(1, 'ws-closed', RatchetState.CI_FAILED, expect.objectContaining({ ratchetState: RatchetState.IDLE }));
1904
- expect(workspaceRatchetService.transitionStateIfEnabled).toHaveBeenNthCalledWith(2, 'ws-closed', RatchetState.CI_RUNNING, expect.objectContaining({ ratchetState: RatchetState.IDLE }));
1905
- expect(stateEvents).toEqual([
1906
- {
1907
- workspaceId: 'ws-closed',
1908
- fromState: RatchetState.CI_RUNNING,
1909
- toState: RatchetState.IDLE,
1910
- },
1911
- ]);
1912
- });
1913
- it('is a no-op when ratchet state is already IDLE', async () => {
1914
- vi.mocked(workspaceDataService.findById).mockResolvedValue({
1915
- id: 'ws-closed',
1916
- ratchetEnabled: true,
1917
- ratchetState: RatchetState.IDLE,
1918
- });
1919
- await ratchetService.markPrClosed('ws-closed');
1920
- expect(workspaceRatchetService.transitionStateIfEnabled).not.toHaveBeenCalled();
1921
- });
1922
- it('does not emit when ratcheting was disabled concurrently', async () => {
1923
- vi.mocked(workspaceDataService.findById)
1924
- .mockResolvedValueOnce({
1925
- id: 'ws-closed',
1926
- ratchetEnabled: true,
1927
- ratchetState: RatchetState.CI_FAILED,
1928
- })
1929
- .mockResolvedValueOnce({
1930
- id: 'ws-closed',
1931
- ratchetEnabled: false,
1932
- ratchetState: RatchetState.IDLE,
1933
- });
1934
- vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
1935
- const stateEvents = [];
1936
- ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
1937
- stateEvents.push(event);
1938
- });
1939
- await ratchetService.markPrClosed('ws-closed');
1940
- expect(stateEvents).toEqual([]);
1941
- });
1942
- it('is a no-op when workspace is not found', async () => {
1943
- vi.mocked(workspaceDataService.findById).mockResolvedValue(null);
1944
- await ratchetService.markPrClosed('ws-missing');
1945
- expect(workspaceRatchetService.transitionStateIfEnabled).not.toHaveBeenCalled();
1946
- });
1947
2208
  it('does not continue to side effects after a timed-out await completes', async () => {
1948
2209
  unsafeCoerce(ratchetService).workspaceCheckTimeoutMs = 5;
1949
2210
  const workspace = {
@@ -1951,13 +2212,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1951
2212
  prUrl: 'https://github.com/example/repo/pull/1',
1952
2213
  prNumber: 1,
1953
2214
  prState: 'OPEN',
2215
+ prReviewState: null,
2216
+ prHasMergeConflict: false,
1954
2217
  prCiStatus: CIStatus.FAILURE,
1955
2218
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
1956
2219
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
1957
2220
  ratchetEnabled: true,
1958
2221
  ratchetState: RatchetState.IDLE,
1959
2222
  ratchetActiveSessionId: null,
1960
- ratchetLastCiRunId: null,
2223
+ ratchetDispatchSnapshotKey: null,
1961
2224
  prReviewLastCheckedAt: null,
1962
2225
  ratchetDispatchOutcome: null,
1963
2226
  ratchetDispatchRetryCount: 0,
@@ -1987,17 +2250,17 @@ describe('ratchet service (state-change + idle dispatch)', () => {
1987
2250
  releaseFetch();
1988
2251
  await new Promise((resolve) => setTimeout(resolve, 0));
1989
2252
  expect(finishSpy).not.toHaveBeenCalled();
1990
- expect(workspaceRatchetService.transitionStateIfEnabled).not.toHaveBeenCalled();
2253
+ expect(workspaceRatchetService.recordCheckIfEnabled).not.toHaveBeenCalled();
1991
2254
  });
1992
2255
  });
1993
2256
  describe('checkWorkspaceById', () => {
1994
2257
  it('returns null when shutting down', async () => {
1995
- unsafeCoerce(ratchetService).isShuttingDown = true;
2258
+ setRatchetShuttingDown(true);
1996
2259
  const result = await ratchetService.checkWorkspaceById('ws-1');
1997
2260
  expect(result).toBeNull();
1998
2261
  });
1999
2262
  it('returns null when workspace not found', async () => {
2000
- unsafeCoerce(ratchetService).isShuttingDown = false;
2263
+ setRatchetShuttingDown(false);
2001
2264
  vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(null);
2002
2265
  const result = await ratchetService.checkWorkspaceById('ws-nonexistent');
2003
2266
  expect(result).toBeNull();
@@ -2008,11 +2271,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2008
2271
  prUrl: 'https://github.com/example/repo/pull/9',
2009
2272
  prNumber: 9,
2010
2273
  prState: 'OPEN',
2274
+ prReviewState: null,
2275
+ prHasMergeConflict: false,
2011
2276
  prCiStatus: CIStatus.UNKNOWN,
2012
2277
  ratchetEnabled: true,
2013
2278
  ratchetState: RatchetState.CI_RUNNING,
2014
2279
  ratchetActiveSessionId: null,
2015
- ratchetLastCiRunId: null,
2280
+ ratchetDispatchSnapshotKey: null,
2016
2281
  prReviewLastCheckedAt: null,
2017
2282
  ratchetDispatchOutcome: null,
2018
2283
  ratchetDispatchRetryCount: 0,
@@ -2023,7 +2288,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2023
2288
  repo: 'repo',
2024
2289
  number: 9,
2025
2290
  });
2026
- vi.mocked(mockGitHubBridge.isRecentlyFetched).mockReturnValue(true);
2291
+ fakeCoordinator.cooldownActive = true;
2027
2292
  const result = await ratchetService.checkWorkspaceById('ws-cooldown');
2028
2293
  expect(result?.action).toEqual({ type: 'WAITING', reason: 'recently_fetched' });
2029
2294
  expect(mockGitHubBridge.getPRFullDetails).not.toHaveBeenCalled();
@@ -2034,13 +2299,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2034
2299
  prUrl: 'https://github.com/example/repo/pull/9',
2035
2300
  prNumber: 9,
2036
2301
  prState: 'OPEN',
2302
+ prReviewState: null,
2303
+ prHasMergeConflict: false,
2037
2304
  prCiStatus: CIStatus.UNKNOWN,
2038
2305
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
2039
2306
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
2040
2307
  ratchetEnabled: true,
2041
2308
  ratchetState: RatchetState.CI_RUNNING,
2042
2309
  ratchetActiveSessionId: null,
2043
- ratchetLastCiRunId: null,
2310
+ ratchetDispatchSnapshotKey: null,
2044
2311
  prReviewLastCheckedAt: null,
2045
2312
  ratchetDispatchOutcome: null,
2046
2313
  ratchetDispatchRetryCount: 0,
@@ -2051,8 +2318,9 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2051
2318
  repo: 'repo',
2052
2319
  number: 9,
2053
2320
  });
2054
- vi.mocked(mockGitHubBridge.isRecentlyFetched).mockReturnValue(true);
2321
+ fakeCoordinator.cooldownActive = true;
2055
2322
  vi.mocked(mockGitHubBridge.getPRFullDetails).mockResolvedValue({
2323
+ isDraft: false,
2056
2324
  state: 'OPEN',
2057
2325
  number: 9,
2058
2326
  url: 'https://github.com/example/repo/pull/9',
@@ -2077,13 +2345,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2077
2345
  prUrl: 'https://github.com/example/repo/pull/9',
2078
2346
  prNumber: 9,
2079
2347
  prState: 'OPEN',
2348
+ prReviewState: null,
2349
+ prHasMergeConflict: false,
2080
2350
  prCiStatus: CIStatus.UNKNOWN,
2081
2351
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
2082
2352
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
2083
2353
  ratchetEnabled: true,
2084
2354
  ratchetState: RatchetState.CI_RUNNING,
2085
2355
  ratchetActiveSessionId: null,
2086
- ratchetLastCiRunId: null,
2356
+ ratchetDispatchSnapshotKey: null,
2087
2357
  prReviewLastCheckedAt: null,
2088
2358
  ratchetDispatchOutcome: null,
2089
2359
  ratchetDispatchRetryCount: 0,
@@ -2094,8 +2364,9 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2094
2364
  repo: 'repo',
2095
2365
  number: 9,
2096
2366
  });
2097
- vi.mocked(mockGitHubBridge.isFetchInFlight).mockReturnValueOnce(true).mockReturnValue(false);
2367
+ fakeCoordinator.inFlightSkips = 1;
2098
2368
  vi.mocked(mockGitHubBridge.getPRFullDetails).mockResolvedValue({
2369
+ isDraft: false,
2099
2370
  state: 'OPEN',
2100
2371
  number: 9,
2101
2372
  url: 'https://github.com/example/repo/pull/9',
@@ -2120,11 +2391,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2120
2391
  prUrl: 'https://github.com/example/repo/pull/9',
2121
2392
  prNumber: 9,
2122
2393
  prState: 'OPEN',
2394
+ prReviewState: null,
2395
+ prHasMergeConflict: false,
2123
2396
  prCiStatus: CIStatus.UNKNOWN,
2124
2397
  ratchetEnabled: true,
2125
2398
  ratchetState: RatchetState.CI_RUNNING,
2126
2399
  ratchetActiveSessionId: null,
2127
- ratchetLastCiRunId: null,
2400
+ ratchetDispatchSnapshotKey: null,
2128
2401
  prReviewLastCheckedAt: null,
2129
2402
  ratchetDispatchOutcome: null,
2130
2403
  ratchetDispatchRetryCount: 0,
@@ -2135,28 +2408,30 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2135
2408
  repo: 'repo',
2136
2409
  number: 9,
2137
2410
  });
2138
- vi.mocked(mockGitHubBridge.isFetchInFlight).mockReturnValue(true);
2411
+ fakeCoordinator.inFlightSkips = Number.POSITIVE_INFINITY;
2139
2412
  const result = await ratchetService.checkWorkspaceById('ws-rerun-cap', {
2140
2413
  bypassPrFetchCooldown: true,
2141
2414
  });
2142
2415
  expect(result?.action).toEqual({ type: 'WAITING', reason: 'recently_fetched' });
2143
- expect(mockGitHubBridge.isFetchInFlight).toHaveBeenCalledTimes(2);
2416
+ expect(mockGitHubBridge.coordinatePrFetch).toHaveBeenCalledTimes(2);
2144
2417
  expect(mockGitHubBridge.getPRFullDetails).not.toHaveBeenCalled();
2145
2418
  });
2146
2419
  it('deduplicates concurrent checks for the same workspace', async () => {
2147
- unsafeCoerce(ratchetService).isShuttingDown = false;
2420
+ setRatchetShuttingDown(false);
2148
2421
  const workspace = {
2149
2422
  id: 'ws-1',
2150
2423
  prUrl: 'https://github.com/example/repo/pull/1',
2151
2424
  prNumber: 1,
2152
2425
  prState: 'OPEN',
2426
+ prReviewState: null,
2427
+ prHasMergeConflict: false,
2153
2428
  prCiStatus: CIStatus.UNKNOWN,
2154
2429
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
2155
2430
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
2156
2431
  ratchetEnabled: true,
2157
2432
  ratchetState: RatchetState.IDLE,
2158
2433
  ratchetActiveSessionId: null,
2159
- ratchetLastCiRunId: null,
2434
+ ratchetDispatchSnapshotKey: null,
2160
2435
  prReviewLastCheckedAt: null,
2161
2436
  ratchetDispatchOutcome: null,
2162
2437
  ratchetDispatchRetryCount: 0,
@@ -2486,22 +2761,58 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2486
2761
  expect(result).toEqual({ kind: 'settled', outcome: 'DIED' });
2487
2762
  expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith('ws-4', 'failed-session', 'DIED');
2488
2763
  });
2489
- it('settles a provider-mismatched session as DIED and stops it', async () => {
2764
+ it('waits for provider-mismatch cleanup before returning a successful settlement', async () => {
2765
+ let finishStop;
2766
+ const pendingStop = new Promise((resolve) => {
2767
+ finishStop = resolve;
2768
+ });
2490
2769
  vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
2491
2770
  id: 'codex-session',
2492
2771
  provider: 'CODEX',
2493
2772
  status: SessionStatus.RUNNING,
2494
2773
  });
2495
- vi.mocked(mockSessionBridge.stopSession).mockResolvedValue();
2496
- const result = await callCheckActiveFixerSession({
2774
+ vi.mocked(mockSessionBridge.stopSession).mockReturnValue(pendingStop);
2775
+ const check = callCheckActiveFixerSession({
2497
2776
  id: 'ws-5',
2498
2777
  ratchetActiveSessionId: 'codex-session',
2499
2778
  defaultSessionProvider: 'WORKSPACE_DEFAULT',
2500
2779
  ratchetSessionProvider: 'WORKSPACE_DEFAULT',
2501
2780
  });
2502
- expect(result).toEqual({ kind: 'settled', outcome: 'DIED' });
2781
+ await vi.waitFor(() => expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('codex-session'));
2782
+ await expect(Promise.race([check, Promise.resolve({ kind: 'cleanup_pending' })])).resolves.toEqual({ kind: 'cleanup_pending' });
2503
2783
  expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith('ws-5', 'codex-session', 'DIED');
2504
- expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('codex-session');
2784
+ finishStop();
2785
+ await expect(check).resolves.toEqual({ kind: 'settled', outcome: 'DIED' });
2786
+ });
2787
+ it('returns cancellation without waiting for provider-mismatch cleanup', async () => {
2788
+ const controller = new AbortController();
2789
+ const timeoutError = new Error('Workspace check timed out');
2790
+ let finishStop;
2791
+ const pendingStop = new Promise((resolve) => {
2792
+ finishStop = resolve;
2793
+ });
2794
+ vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
2795
+ id: 'codex-session',
2796
+ provider: 'CODEX',
2797
+ status: SessionStatus.RUNNING,
2798
+ });
2799
+ vi.mocked(mockSessionBridge.stopSession).mockReturnValue(pendingStop);
2800
+ vi.mocked(mockWorkspaceBridge.recordSessionEnd).mockImplementation(() => {
2801
+ controller.abort(timeoutError);
2802
+ return Promise.resolve(true);
2803
+ });
2804
+ const check = unsafeCoerce(ratchetService).checkActiveFixerSession({
2805
+ id: 'ws-provider-mismatch-cancelled-after-settlement',
2806
+ ratchetActiveSessionId: 'codex-session',
2807
+ defaultSessionProvider: 'WORKSPACE_DEFAULT',
2808
+ ratchetSessionProvider: 'WORKSPACE_DEFAULT',
2809
+ }, controller.signal);
2810
+ const outcome = check.then((value) => ({ status: 'resolved', value }), (error) => ({ status: 'rejected', error }));
2811
+ await vi.waitFor(() => expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('codex-session'));
2812
+ await expect(Promise.race([outcome, Promise.resolve({ status: 'pending' })])).resolves.toEqual({ status: 'rejected', error: timeoutError });
2813
+ expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith('ws-provider-mismatch-cancelled-after-settlement', 'codex-session', 'DIED');
2814
+ finishStop();
2815
+ await pendingStop;
2505
2816
  });
2506
2817
  it('returns the active fixer when the session is working', async () => {
2507
2818
  vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
@@ -2703,6 +3014,10 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2703
3014
  promptCompletion: Promise.resolve(false),
2704
3015
  });
2705
3016
  vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
3017
+ const events = [];
3018
+ ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
3019
+ events.push(event);
3020
+ });
2706
3021
  const result = await unsafeCoerce(ratchetService).triggerFixer({
2707
3022
  id: 'ws-failed-prompt',
2708
3023
  prUrl: 'https://github.com/example/repo/pull/20',
@@ -2716,6 +3031,10 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2716
3031
  expect(result).toMatchObject({ type: 'TRIGGERED_FIXER' });
2717
3032
  await vi.waitFor(() => expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalledWith('ws-failed-prompt', 'failed-prompt-session', 'DIED'));
2718
3033
  expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('failed-prompt-session');
3034
+ await vi.waitFor(() => expect(events).toEqual([
3035
+ { workspaceId: 'ws-failed-prompt' },
3036
+ { workspaceId: 'ws-failed-prompt' },
3037
+ ]));
2719
3038
  });
2720
3039
  it('does not stop a newer active session when an old prompt completion fails', async () => {
2721
3040
  vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
@@ -2726,6 +3045,10 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2726
3045
  });
2727
3046
  vi.mocked(workspaceRatchetService.recordSessionEnd).mockResolvedValue(false);
2728
3047
  vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
3048
+ const events = [];
3049
+ ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
3050
+ events.push(event);
3051
+ });
2729
3052
  await unsafeCoerce(ratchetService).triggerFixer({
2730
3053
  id: 'ws-replaced-prompt',
2731
3054
  prUrl: 'https://github.com/example/repo/pull/20',
@@ -2738,6 +3061,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2738
3061
  }, 0);
2739
3062
  await vi.waitFor(() => expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalled());
2740
3063
  expect(mockSessionBridge.stopSession).not.toHaveBeenCalled();
3064
+ expect(events).toEqual([{ workspaceId: 'ws-replaced-prompt' }]);
2741
3065
  });
2742
3066
  it('cleans up a fixer through prompt failure after its dispatch record is persisted', async () => {
2743
3067
  const controller = new AbortController();
@@ -2805,7 +3129,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2805
3129
  ratchetEnabled: true,
2806
3130
  ratchetState: RatchetState.CI_FAILED,
2807
3131
  ratchetActiveSessionId: null,
2808
- ratchetLastCiRunId: null,
3132
+ ratchetDispatchSnapshotKey: null,
2809
3133
  prReviewLastCheckedAt: null,
2810
3134
  ratchetDispatchOutcome: null,
2811
3135
  ratchetDispatchRetryCount: 0,
@@ -2828,7 +3152,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2828
3152
  ratchetEnabled: true,
2829
3153
  ratchetState: RatchetState.CI_FAILED,
2830
3154
  ratchetActiveSessionId: null,
2831
- ratchetLastCiRunId: null,
3155
+ ratchetDispatchSnapshotKey: null,
2832
3156
  prReviewLastCheckedAt: null,
2833
3157
  ratchetDispatchOutcome: null,
2834
3158
  ratchetDispatchRetryCount: 2,
@@ -2861,7 +3185,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2861
3185
  ratchetEnabled: true,
2862
3186
  ratchetState: RatchetState.CI_FAILED,
2863
3187
  ratchetActiveSessionId: null,
2864
- ratchetLastCiRunId: null,
3188
+ ratchetDispatchSnapshotKey: null,
2865
3189
  prReviewLastCheckedAt: null,
2866
3190
  ratchetDispatchOutcome: null,
2867
3191
  ratchetDispatchRetryCount: 0,
@@ -2890,7 +3214,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
2890
3214
  ratchetEnabled: true,
2891
3215
  ratchetState: RatchetState.CI_FAILED,
2892
3216
  ratchetActiveSessionId: null,
2893
- ratchetLastCiRunId: null,
3217
+ ratchetDispatchSnapshotKey: null,
2894
3218
  prReviewLastCheckedAt: null,
2895
3219
  ratchetDispatchOutcome: null,
2896
3220
  ratchetDispatchRetryCount: 0,
@@ -3000,32 +3324,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
3000
3324
  afterEach(() => {
3001
3325
  ratchetService.removeAllListeners();
3002
3326
  });
3003
- it('emits ratchet_state_changed when disabled workspace state changes', async () => {
3004
- const workspace = {
3005
- id: 'ws-disabled-change',
3006
- prUrl: 'https://github.com/example/repo/pull/30',
3007
- prNumber: 30,
3008
- ratchetEnabled: false,
3009
- ratchetState: RatchetState.CI_FAILED,
3010
- ratchetActiveSessionId: null,
3011
- ratchetLastCiRunId: null,
3012
- prReviewLastCheckedAt: null,
3013
- ratchetDispatchOutcome: null,
3014
- ratchetDispatchRetryCount: 0,
3015
- };
3016
- const events = [];
3017
- ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
3018
- events.push(event);
3019
- });
3020
- await unsafeCoerce(ratchetService).processWorkspace(workspace);
3021
- expect(events).toHaveLength(1);
3022
- expect(events[0]).toEqual({
3023
- workspaceId: 'ws-disabled-change',
3024
- fromState: RatchetState.CI_FAILED,
3025
- toState: RatchetState.IDLE,
3026
- });
3027
- });
3028
- it('does NOT emit when disabled workspace state is already IDLE', async () => {
3327
+ it('never emits from a check on a disabled workspace', async () => {
3029
3328
  const workspace = {
3030
3329
  id: 'ws-disabled-idle',
3031
3330
  prUrl: 'https://github.com/example/repo/pull/31',
@@ -3033,7 +3332,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
3033
3332
  ratchetEnabled: false,
3034
3333
  ratchetState: RatchetState.IDLE,
3035
3334
  ratchetActiveSessionId: null,
3036
- ratchetLastCiRunId: null,
3335
+ ratchetDispatchSnapshotKey: null,
3037
3336
  prReviewLastCheckedAt: null,
3038
3337
  ratchetDispatchOutcome: null,
3039
3338
  ratchetDispatchRetryCount: 0,
@@ -3053,7 +3352,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
3053
3352
  ratchetEnabled: true,
3054
3353
  ratchetState: RatchetState.IDLE,
3055
3354
  ratchetActiveSessionId: null,
3056
- ratchetLastCiRunId: null,
3355
+ ratchetDispatchSnapshotKey: null,
3057
3356
  prReviewLastCheckedAt: null,
3058
3357
  ratchetDispatchOutcome: null,
3059
3358
  ratchetDispatchRetryCount: 0,
@@ -3094,7 +3393,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
3094
3393
  ratchetEnabled: true,
3095
3394
  ratchetState: RatchetState.CI_FAILED,
3096
3395
  ratchetActiveSessionId: null,
3097
- ratchetLastCiRunId: null,
3396
+ ratchetDispatchSnapshotKey: null,
3098
3397
  prReviewLastCheckedAt: null,
3099
3398
  ratchetDispatchOutcome: null,
3100
3399
  ratchetDispatchRetryCount: 0,
@@ -3129,7 +3428,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
3129
3428
  ratchetEnabled: true,
3130
3429
  ratchetState: RatchetState.CI_FAILED,
3131
3430
  ratchetActiveSessionId: null,
3132
- ratchetLastCiRunId: null,
3431
+ ratchetDispatchSnapshotKey: null,
3133
3432
  prReviewLastCheckedAt: null,
3134
3433
  ratchetDispatchOutcome: null,
3135
3434
  ratchetDispatchRetryCount: 0,