factory-factory 0.4.0 → 0.4.1
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.
- package/README.md +61 -344
- package/dist/client/assets/{arc-BZLkggFv.js → arc-lK3Ig9GV.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-0dfKDS01.js → architectureDiagram-3BPJPVTR-CeUbfBqe.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-kPnqTUvo.js → blockDiagram-GPEHLZMM-DiVGPkq2.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-fGcSJ5RM.js → c4Diagram-AAUBKEIU-CT8hJB-h.js} +1 -1
- package/dist/client/assets/channel-CvY1mvIl.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-nkRXvoLd.js → chunk-2J33WTMH-B0h8q8fD.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-BzGqW4v8.js → chunk-4BX2VUAB-km6NpEMz.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CKYhsw8v.js → chunk-55IACEB6-COUWt3oA.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-D6c3bkpP.js → chunk-727SXJPM-Bp-ts2at.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-Cp_aqtpa.js → chunk-AQP2D5EJ-dyo9i4xa.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-CkbLLRk5.js → chunk-FMBD7UC4-B4C3KvLe.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-BZ894oON.js → chunk-ND2GUHAM-Qhi4WqzZ.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-D4NOzC69.js → chunk-QZHKN3VN-Ce3Q_vrs.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-Db7ZXJ6w.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Db7ZXJ6w.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-CPSnsVY6.js → cose-bilkent-S5V4N54A-D6QofwFq.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-CDuVn0gJ.js → dagre-BM42HDAG-CDzpFdgD.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DkPx69Lt.js → diagram-2AECGRRQ-dl1_7lyq.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CchGithI.js → diagram-5GNKFQAL-B0ynMwBY.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DQ50kQAK.js → diagram-KO2AKTUF-B9ABz-Wk.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-hKBATxk5.js → diagram-LMA3HP47-DZxXcfiX.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-Bga7_0RO.js → diagram-OG6HWLK6-BncGM9Gv.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-D26at0F2.js → erDiagram-TEJ5UH35-B9hxScvO.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Qf-TRw4O.js → flowDiagram-I6XJVG4X-DgZ2jwJQ.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CmRredaI.js → ganttDiagram-6RSMTGT7-BrnNMNRY.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-QQP7Sl8F.js → gitGraphDiagram-PVQCEYII-BJmed6oD.js} +1 -1
- package/dist/client/assets/index-Btlruz7h.css +1 -0
- package/dist/client/assets/{index-Db00yCQO.js → index-DEKuJM5_.js} +179 -177
- package/dist/client/assets/{infoDiagram-5YYISTIA-YKWLGpI0.js → infoDiagram-5YYISTIA-CtLzR4ip.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DrCgRttT.js → ishikawaDiagram-YF4QCWOH-BLrvV5ke.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CcyKXKKG.js → journeyDiagram-JHISSGLW-B2-TMwJI.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CsGSN3QV.js → kanban-definition-UN3LZRKU-B5mGKgYF.js} +1 -1
- package/dist/client/assets/{linear-DG8wt3yl.js → linear-ConE9euY.js} +1 -1
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-CD6E0vLi.js → mindmap-definition-RKZ34NQL-B0BaMk8D.js} +1 -1
- package/dist/client/assets/{mobile-baseline-CCXJGaWY.js → mobile-baseline-DWCt7ZGJ.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-PIN8tU1a.js → pieDiagram-4H26LBE5-DgPu3GTs.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-DV6ne1ch.js → quadrantDiagram-W4KKPZXB-DDbeggF4.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-Cly9IJv1.js → requirementDiagram-4Y6WPE33-Cc3ozz7U.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-D2SFbF9j.js → sankeyDiagram-5OEKKPKP-DmYoq588.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BsxZzGc-.js → sequenceDiagram-3UESZ5HK-EVqdDzgf.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-DtZoFzqs.js → stateDiagram-AJRCARHV-BRd6IxSa.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DR2vMoX5.js +1 -0
- package/dist/client/assets/{terminal-instance-DFzmxfzG.js → terminal-instance-CDKJdDaO.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-B7ZqNmvc.js → timeline-definition-PNZ67QCA-CyxBqgqv.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-Biz7Z4hM.js → vennDiagram-CIIHVFJN-CLslQYVi.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-B-ZjZQUx.js → wardley-L42UT6IY-DyEDLg3x.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-C9yV9o-K.js → wardleyDiagram-YWT4CUSO-CjJBpd3P.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DuWAbR0h.js → xychartDiagram-2RQKCTM6-DwzoT5Dl.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/working.png +0 -0
- package/dist/prisma/generated/commonInputTypes.d.ts +30 -0
- package/dist/prisma/generated/commonInputTypes.d.ts.map +1 -1
- package/dist/prisma/generated/enums.d.ts +5 -0
- package/dist/prisma/generated/enums.d.ts.map +1 -1
- package/dist/prisma/generated/enums.js +4 -0
- package/dist/prisma/generated/enums.js.map +1 -1
- package/dist/prisma/generated/internal/class.js +4 -4
- package/dist/prisma/generated/internal/class.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.d.ts +5 -0
- package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.js +4 -0
- package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +4 -0
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +4 -0
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/prisma/generated/models/UserSettings.d.ts +32 -1
- package/dist/prisma/generated/models/UserSettings.d.ts.map +1 -1
- package/dist/prisma/generated/models/Workspace.d.ts +220 -1
- package/dist/prisma/generated/models/Workspace.d.ts.map +1 -1
- package/dist/src/backend/app-context.d.ts +90 -25
- package/dist/src/backend/app-context.d.ts.map +1 -1
- package/dist/src/backend/app-context.js +145 -42
- package/dist/src/backend/app-context.js.map +1 -1
- package/dist/src/backend/app-context.test.d.ts +2 -0
- package/dist/src/backend/app-context.test.d.ts.map +1 -0
- package/dist/src/backend/app-context.test.js +51 -0
- package/dist/src/backend/app-context.test.js.map +1 -0
- package/dist/src/backend/clients/git.client.d.ts.map +1 -1
- package/dist/src/backend/clients/git.client.js +5 -0
- package/dist/src/backend/clients/git.client.js.map +1 -1
- package/dist/src/backend/clients/git.client.test.js +24 -0
- package/dist/src/backend/clients/git.client.test.js.map +1 -1
- package/dist/src/backend/index.js +5 -5
- package/dist/src/backend/index.js.map +1 -1
- package/dist/src/backend/interceptors/branch-rename.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/branch-rename.interceptor.js +79 -5
- package/dist/src/backend/interceptors/branch-rename.interceptor.js.map +1 -1
- package/dist/src/backend/interceptors/branch-rename.interceptor.test.js +120 -16
- package/dist/src/backend/interceptors/branch-rename.interceptor.test.js.map +1 -1
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js +3 -0
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.js.map +1 -1
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js +8 -0
- package/dist/src/backend/interceptors/pre-pr-rename.interceptor.test.js.map +1 -1
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.js +49 -0
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.js.map +1 -1
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.test.js +98 -0
- package/dist/src/backend/interceptors/pre-push-rename.interceptor.test.js.map +1 -1
- package/dist/src/backend/lib/application-error.d.ts +6 -0
- package/dist/src/backend/lib/application-error.d.ts.map +1 -0
- package/dist/src/backend/lib/application-error.js +9 -0
- package/dist/src/backend/lib/application-error.js.map +1 -0
- package/dist/src/backend/lib/application-error.test.d.ts +2 -0
- package/dist/src/backend/lib/application-error.test.d.ts.map +1 -0
- package/dist/src/backend/lib/application-error.test.js +23 -0
- package/dist/src/backend/lib/application-error.test.js.map +1 -0
- package/dist/src/backend/lib/git-helpers.d.ts +1 -7
- package/dist/src/backend/lib/git-helpers.d.ts.map +1 -1
- package/dist/src/backend/lib/git-helpers.js +4 -33
- package/dist/src/backend/lib/git-helpers.js.map +1 -1
- package/dist/src/backend/lib/git-helpers.test.js +17 -10
- package/dist/src/backend/lib/git-helpers.test.js.map +1 -1
- package/dist/src/backend/lib/process-liveness.d.ts +2 -0
- package/dist/src/backend/lib/process-liveness.d.ts.map +1 -0
- package/dist/src/backend/lib/process-liveness.js +26 -0
- package/dist/src/backend/lib/process-liveness.js.map +1 -0
- package/dist/src/backend/lib/process-liveness.test.d.ts +2 -0
- package/dist/src/backend/lib/process-liveness.test.d.ts.map +1 -0
- package/dist/src/backend/lib/process-liveness.test.js +35 -0
- package/dist/src/backend/lib/process-liveness.test.js.map +1 -0
- package/dist/src/backend/lib/session-summaries.d.ts +4 -5
- package/dist/src/backend/lib/session-summaries.d.ts.map +1 -1
- package/dist/src/backend/lib/session-summaries.js.map +1 -1
- package/dist/src/backend/lib/workspace-derived-state.d.ts +9 -1
- package/dist/src/backend/lib/workspace-derived-state.d.ts.map +1 -1
- package/dist/src/backend/lib/workspace-derived-state.js +6 -1
- package/dist/src/backend/lib/workspace-derived-state.js.map +1 -1
- package/dist/src/backend/lib/workspace-derived-state.test.js +11 -3
- package/dist/src/backend/lib/workspace-derived-state.test.js.map +1 -1
- package/dist/src/backend/middleware/cors.middleware.js +1 -1
- package/dist/src/backend/middleware/cors.middleware.js.map +1 -1
- package/dist/src/backend/middleware/index.d.ts +1 -1
- package/dist/src/backend/middleware/index.d.ts.map +1 -1
- package/dist/src/backend/middleware/index.js +1 -1
- package/dist/src/backend/middleware/index.js.map +1 -1
- package/dist/src/backend/middleware/middleware.test.js +1 -1
- package/dist/src/backend/middleware/middleware.test.js.map +1 -1
- package/dist/src/backend/middleware/request-logger.middleware.d.ts +1 -2
- package/dist/src/backend/middleware/request-logger.middleware.d.ts.map +1 -1
- package/dist/src/backend/middleware/request-logger.middleware.js +0 -2
- package/dist/src/backend/middleware/request-logger.middleware.js.map +1 -1
- package/dist/src/backend/orchestration/data-backup.service.d.ts.map +1 -1
- package/dist/src/backend/orchestration/data-backup.service.js +3 -1
- package/dist/src/backend/orchestration/data-backup.service.js.map +1 -1
- package/dist/src/backend/orchestration/data-backup.service.test.js +29 -0
- package/dist/src/backend/orchestration/data-backup.service.test.js.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts +24 -12
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.js +53 -63
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js +173 -82
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/event-coalescer.integration.test.d.ts +2 -0
- package/dist/src/backend/orchestration/event-coalescer.integration.test.d.ts.map +1 -0
- package/dist/src/backend/orchestration/event-coalescer.integration.test.js +47 -0
- package/dist/src/backend/orchestration/event-coalescer.integration.test.js.map +1 -0
- package/dist/src/backend/orchestration/event-collector-lifecycle.integration.test.d.ts +2 -0
- package/dist/src/backend/orchestration/event-collector-lifecycle.integration.test.d.ts.map +1 -0
- package/dist/src/backend/orchestration/event-collector-lifecycle.integration.test.js +34 -0
- package/dist/src/backend/orchestration/event-collector-lifecycle.integration.test.js.map +1 -0
- package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts +37 -10
- package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.js +297 -121
- package/dist/src/backend/orchestration/event-collector.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.test.js +354 -42
- package/dist/src/backend/orchestration/event-collector.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/health.service.js +2 -2
- package/dist/src/backend/orchestration/health.service.js.map +1 -1
- package/dist/src/backend/orchestration/linear-config.helper.js +2 -2
- package/dist/src/backend/orchestration/linear-config.helper.js.map +1 -1
- package/dist/src/backend/orchestration/reconciliation.service.d.ts +13 -1
- package/dist/src/backend/orchestration/reconciliation.service.d.ts.map +1 -1
- package/dist/src/backend/orchestration/reconciliation.service.js +16 -29
- package/dist/src/backend/orchestration/reconciliation.service.js.map +1 -1
- package/dist/src/backend/orchestration/reconciliation.service.test.js +15 -47
- package/dist/src/backend/orchestration/reconciliation.service.test.js.map +1 -1
- package/dist/src/backend/orchestration/scheduler.service.d.ts +2 -1
- package/dist/src/backend/orchestration/scheduler.service.d.ts.map +1 -1
- package/dist/src/backend/orchestration/scheduler.service.js +107 -44
- package/dist/src/backend/orchestration/scheduler.service.js.map +1 -1
- package/dist/src/backend/orchestration/scheduler.service.test.js +266 -59
- package/dist/src/backend/orchestration/scheduler.service.test.js.map +1 -1
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts +18 -11
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js +59 -49
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.test.js +156 -24
- package/dist/src/backend/orchestration/snapshot-reconciliation.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/types.d.ts +2 -2
- package/dist/src/backend/orchestration/types.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts +13 -9
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.js +8 -10
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js +44 -13
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-children.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-children.orchestrator.js +11 -12
- package/dist/src/backend/orchestration/workspace-children.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-children.orchestrator.test.js +41 -21
- package/dist/src/backend/orchestration/workspace-children.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.js +3 -3
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init-script-pipeline.d.ts +1 -1
- package/dist/src/backend/orchestration/workspace-init-script-pipeline.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-init-script-pipeline.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.js +34 -20
- package/dist/src/backend/orchestration/workspace-init.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js +278 -102
- package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.d.ts +24 -0
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.d.ts.map +1 -0
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.js +66 -0
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.js.map +1 -0
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.test.d.ts +2 -0
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.test.d.ts.map +1 -0
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.test.js +235 -0
- package/dist/src/backend/orchestration/workspace-notification-delivery.orchestrator.test.js.map +1 -0
- package/dist/src/backend/routers/health.router.d.ts.map +1 -1
- package/dist/src/backend/routers/health.router.js +5 -5
- package/dist/src/backend/routers/health.router.js.map +1 -1
- package/dist/src/backend/routers/health.router.test.js +3 -5
- package/dist/src/backend/routers/health.router.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/chat-connection-registry.d.ts +15 -6
- package/dist/src/backend/routers/websocket/chat-connection-registry.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/chat-connection-registry.js +80 -33
- package/dist/src/backend/routers/websocket/chat-connection-registry.js.map +1 -1
- package/dist/src/backend/routers/websocket/chat-connection-registry.test.js +60 -21
- package/dist/src/backend/routers/websocket/chat-connection-registry.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/chat.handler.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/chat.handler.js +4 -3
- package/dist/src/backend/routers/websocket/chat.handler.js.map +1 -1
- package/dist/src/backend/routers/websocket/chat.handler.test.js +49 -4
- package/dist/src/backend/routers/websocket/chat.handler.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/context-injection.test.js +450 -14
- package/dist/src/backend/routers/websocket/context-injection.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/dev-logs.handler.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/dev-logs.handler.js +16 -3
- package/dist/src/backend/routers/websocket/dev-logs.handler.js.map +1 -1
- package/dist/src/backend/routers/websocket/index.d.ts +2 -1
- package/dist/src/backend/routers/websocket/index.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/index.js +2 -1
- package/dist/src/backend/routers/websocket/index.js.map +1 -1
- package/dist/src/backend/routers/websocket/post-run-logs.handler.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/post-run-logs.handler.js +6 -3
- package/dist/src/backend/routers/websocket/post-run-logs.handler.js.map +1 -1
- package/dist/src/backend/routers/websocket/snapshots.handler.d.ts +7 -5
- package/dist/src/backend/routers/websocket/snapshots.handler.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/snapshots.handler.js +50 -23
- package/dist/src/backend/routers/websocket/snapshots.handler.js.map +1 -1
- package/dist/src/backend/routers/websocket/snapshots.handler.test.js +128 -62
- package/dist/src/backend/routers/websocket/snapshots.handler.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/terminal.handler.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/terminal.handler.js +35 -26
- package/dist/src/backend/routers/websocket/terminal.handler.js.map +1 -1
- package/dist/src/backend/routers/websocket/terminal.handler.test.js +35 -9
- package/dist/src/backend/routers/websocket/terminal.handler.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/upgrade-utils.d.ts +4 -4
- package/dist/src/backend/routers/websocket/upgrade-utils.d.ts.map +1 -1
- package/dist/src/backend/routers/websocket/upgrade-utils.js +1 -1
- package/dist/src/backend/routers/websocket/upgrade-utils.js.map +1 -1
- package/dist/src/backend/routers/websocket/upgrade-utils.test.js +39 -2
- package/dist/src/backend/routers/websocket/upgrade-utils.test.js.map +1 -1
- package/dist/src/backend/routers/websocket/websocket.integration.test.js +47 -9
- package/dist/src/backend/routers/websocket/websocket.integration.test.js.map +1 -1
- package/dist/src/backend/server.d.ts +3 -2
- package/dist/src/backend/server.d.ts.map +1 -1
- package/dist/src/backend/server.js +37 -37
- package/dist/src/backend/server.js.map +1 -1
- package/dist/src/backend/server.upgrade.test.js +177 -137
- package/dist/src/backend/server.upgrade.test.js.map +1 -1
- package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.d.ts +4 -0
- package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.d.ts.map +1 -1
- package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.js +66 -18
- package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.js.map +1 -1
- package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.test.js +139 -2
- package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.test.js.map +1 -1
- package/dist/src/backend/services/auto-iteration/service/bridges.d.ts +1 -0
- package/dist/src/backend/services/auto-iteration/service/bridges.d.ts.map +1 -1
- package/dist/src/backend/services/auto-iteration/service/git-ops.d.ts.map +1 -1
- package/dist/src/backend/services/auto-iteration/service/git-ops.js +32 -11
- package/dist/src/backend/services/auto-iteration/service/git-ops.js.map +1 -1
- package/dist/src/backend/services/auto-iteration/service/git-ops.test.d.ts +2 -0
- package/dist/src/backend/services/auto-iteration/service/git-ops.test.d.ts.map +1 -0
- package/dist/src/backend/services/auto-iteration/service/git-ops.test.js +59 -0
- package/dist/src/backend/services/auto-iteration/service/git-ops.test.js.map +1 -0
- package/dist/src/backend/services/check-service-accessor-boundaries.test.d.ts +2 -0
- package/dist/src/backend/services/check-service-accessor-boundaries.test.d.ts.map +1 -0
- package/dist/src/backend/services/check-service-accessor-boundaries.test.js +386 -0
- package/dist/src/backend/services/check-service-accessor-boundaries.test.js.map +1 -0
- package/dist/src/backend/services/check-single-writer.test.js +76 -2
- package/dist/src/backend/services/check-single-writer.test.js.map +1 -1
- package/dist/src/backend/services/config.service.d.ts +7 -0
- package/dist/src/backend/services/config.service.d.ts.map +1 -1
- package/dist/src/backend/services/config.service.js +9 -0
- package/dist/src/backend/services/config.service.js.map +1 -1
- package/dist/src/backend/services/config.service.test.js +41 -0
- package/dist/src/backend/services/config.service.test.js.map +1 -1
- package/dist/src/backend/services/constants.d.ts +3 -0
- package/dist/src/backend/services/constants.d.ts.map +1 -1
- package/dist/src/backend/services/constants.js +3 -0
- package/dist/src/backend/services/constants.js.map +1 -1
- package/dist/src/backend/services/decision-log/index.d.ts +1 -1
- package/dist/src/backend/services/decision-log/index.d.ts.map +1 -1
- package/dist/src/backend/services/decision-log/index.js +1 -1
- package/dist/src/backend/services/decision-log/index.js.map +1 -1
- package/dist/src/backend/services/decision-log/service/decision-log-domain-exports.test.d.ts +2 -0
- package/dist/src/backend/services/decision-log/service/decision-log-domain-exports.test.d.ts.map +1 -0
- package/dist/src/backend/services/decision-log/service/decision-log-domain-exports.test.js +8 -0
- package/dist/src/backend/services/decision-log/service/decision-log-domain-exports.test.js.map +1 -0
- package/dist/src/backend/{orchestration/decision-log-query.service.d.ts → services/decision-log/service/decision-log.service.d.ts} +4 -4
- package/dist/src/backend/services/decision-log/service/decision-log.service.d.ts.map +1 -0
- package/dist/src/backend/{orchestration/decision-log-query.service.js → services/decision-log/service/decision-log.service.js} +4 -4
- package/dist/src/backend/services/decision-log/service/decision-log.service.js.map +1 -0
- package/dist/src/backend/services/decision-log/service/decision-log.service.test.d.ts +2 -0
- package/dist/src/backend/services/decision-log/service/decision-log.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/decision-log/service/decision-log.service.test.js +45 -0
- package/dist/src/backend/services/decision-log/service/decision-log.service.test.js.map +1 -0
- package/dist/src/backend/services/decision-log/service/index.d.ts +2 -0
- package/dist/src/backend/services/decision-log/service/index.d.ts.map +1 -0
- package/dist/src/backend/services/decision-log/service/index.js +2 -0
- package/dist/src/backend/services/decision-log/service/index.js.map +1 -0
- package/dist/src/backend/services/env-schemas.d.ts +3 -0
- package/dist/src/backend/services/env-schemas.d.ts.map +1 -1
- package/dist/src/backend/services/env-schemas.js +3 -0
- package/dist/src/backend/services/env-schemas.js.map +1 -1
- package/dist/src/backend/services/github/service/bridges.d.ts +51 -0
- package/dist/src/backend/services/github/service/bridges.d.ts.map +1 -1
- package/dist/src/backend/services/github/service/github-cli/schemas.d.ts +30 -6
- package/dist/src/backend/services/github/service/github-cli/schemas.d.ts.map +1 -1
- package/dist/src/backend/services/github/service/github-cli/schemas.js +18 -0
- package/dist/src/backend/services/github/service/github-cli/schemas.js.map +1 -1
- package/dist/src/backend/services/github/service/github-cli/types.d.ts +6 -0
- package/dist/src/backend/services/github/service/github-cli/types.d.ts.map +1 -1
- package/dist/src/backend/services/github/service/github-cli.service.d.ts +3 -6
- package/dist/src/backend/services/github/service/github-cli.service.d.ts.map +1 -1
- package/dist/src/backend/services/github/service/github-cli.service.js +39 -33
- package/dist/src/backend/services/github/service/github-cli.service.js.map +1 -1
- package/dist/src/backend/services/github/service/github-cli.service.test.js +63 -67
- package/dist/src/backend/services/github/service/github-cli.service.test.js.map +1 -1
- package/dist/src/backend/services/github/service/index.d.ts +2 -2
- package/dist/src/backend/services/github/service/index.d.ts.map +1 -1
- package/dist/src/backend/services/github/service/index.js +1 -1
- package/dist/src/backend/services/github/service/index.js.map +1 -1
- package/dist/src/backend/services/github/service/pr-fetch-registry.d.ts +13 -6
- package/dist/src/backend/services/github/service/pr-fetch-registry.d.ts.map +1 -1
- package/dist/src/backend/services/github/service/pr-fetch-registry.js +77 -12
- package/dist/src/backend/services/github/service/pr-fetch-registry.js.map +1 -1
- package/dist/src/backend/services/github/service/pr-fetch-registry.test.d.ts +2 -0
- package/dist/src/backend/services/github/service/pr-fetch-registry.test.d.ts.map +1 -0
- package/dist/src/backend/services/github/service/pr-fetch-registry.test.js +112 -0
- package/dist/src/backend/services/github/service/pr-fetch-registry.test.js.map +1 -0
- package/dist/src/backend/services/github/service/pr-snapshot.service.d.ts +19 -3
- package/dist/src/backend/services/github/service/pr-snapshot.service.d.ts.map +1 -1
- package/dist/src/backend/services/github/service/pr-snapshot.service.js +115 -16
- package/dist/src/backend/services/github/service/pr-snapshot.service.js.map +1 -1
- package/dist/src/backend/services/github/service/pr-snapshot.service.test.js +255 -9
- package/dist/src/backend/services/github/service/pr-snapshot.service.test.js.map +1 -1
- package/dist/src/backend/services/periodic-task/index.d.ts +0 -1
- package/dist/src/backend/services/periodic-task/index.d.ts.map +1 -1
- package/dist/src/backend/services/periodic-task/index.js +0 -1
- package/dist/src/backend/services/periodic-task/index.js.map +1 -1
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.d.ts +2 -2
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.d.ts.map +1 -1
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.js +17 -10
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.js.map +1 -1
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.js +29 -10
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.js.map +1 -1
- package/dist/src/backend/services/periodic-task/service/periodic-task.service.d.ts +103 -0
- package/dist/src/backend/services/periodic-task/service/periodic-task.service.d.ts.map +1 -1
- package/dist/src/backend/services/periodic-task/service/periodic-task.service.js +47 -1
- package/dist/src/backend/services/periodic-task/service/periodic-task.service.js.map +1 -1
- package/dist/src/backend/services/periodic-task/service/periodic-task.service.test.js +104 -8
- package/dist/src/backend/services/periodic-task/service/periodic-task.service.test.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/bridges.d.ts +34 -4
- package/dist/src/backend/services/ratchet/service/bridges.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/fixer-session.service.d.ts +6 -1
- package/dist/src/backend/services/ratchet/service/fixer-session.service.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/fixer-session.service.js +47 -8
- package/dist/src/backend/services/ratchet/service/fixer-session.service.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/fixer-session.service.test.js +131 -29
- package/dist/src/backend/services/ratchet/service/fixer-session.service.test.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/index.d.ts +3 -3
- package/dist/src/backend/services/ratchet/service/index.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/index.js +1 -1
- package/dist/src/backend/services/ratchet/service/index.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-active-session.helpers.d.ts +5 -1
- package/dist/src/backend/services/ratchet/service/ratchet-active-session.helpers.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-active-session.helpers.js +9 -6
- package/dist/src/backend/services/ratchet/service/ratchet-active-session.helpers.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-fixer-dispatch.helpers.d.ts +3 -0
- package/dist/src/backend/services/ratchet/service/ratchet-fixer-dispatch.helpers.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-fixer-dispatch.helpers.js +47 -10
- package/dist/src/backend/services/ratchet/service/ratchet-fixer-dispatch.helpers.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.d.ts +8 -3
- package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.js +63 -27
- package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.test.js +325 -15
- package/dist/src/backend/services/ratchet/service/ratchet-pr-state.helpers.test.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-provider-resolver.service.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-provider-resolver.service.js +4 -4
- package/dist/src/backend/services/ratchet/service/ratchet-provider-resolver.service.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet-provider-resolver.service.test.js +14 -14
- package/dist/src/backend/services/ratchet/service/ratchet-provider-resolver.service.test.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet.service.d.ts +8 -1
- package/dist/src/backend/services/ratchet/service/ratchet.service.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet.service.js +54 -29
- package/dist/src/backend/services/ratchet/service/ratchet.service.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet.service.test.js +577 -194
- package/dist/src/backend/services/ratchet/service/ratchet.service.test.js.map +1 -1
- package/dist/src/backend/services/ratchet/service/ratchet.types.d.ts +2 -2
- package/dist/src/backend/services/ratchet/service/ratchet.types.d.ts.map +1 -1
- package/dist/src/backend/services/registry.d.ts +43 -0
- package/dist/src/backend/services/registry.d.ts.map +1 -1
- package/dist/src/backend/services/registry.js +42 -0
- package/dist/src/backend/services/registry.js.map +1 -1
- package/dist/src/backend/services/resources.integration.test.js +189 -96
- package/dist/src/backend/services/resources.integration.test.js.map +1 -1
- package/dist/src/backend/services/run-script/service/bridges.d.ts +4 -0
- package/dist/src/backend/services/run-script/service/bridges.d.ts.map +1 -1
- package/dist/src/backend/services/{factory-config.service.d.ts → run-script/service/factory-config.service.d.ts} +1 -1
- package/dist/src/backend/services/run-script/service/factory-config.service.d.ts.map +1 -0
- package/dist/src/backend/services/{factory-config.service.js → run-script/service/factory-config.service.js} +1 -1
- package/dist/src/backend/services/run-script/service/factory-config.service.js.map +1 -0
- package/dist/src/backend/services/run-script/service/factory-config.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/{factory-config.service.test.js → run-script/service/factory-config.service.test.js} +1 -1
- package/dist/src/backend/services/run-script/service/factory-config.service.test.js.map +1 -0
- package/dist/src/backend/services/run-script/service/index.d.ts +2 -0
- package/dist/src/backend/services/run-script/service/index.d.ts.map +1 -1
- package/dist/src/backend/services/run-script/service/index.js +2 -0
- package/dist/src/backend/services/run-script/service/index.js.map +1 -1
- package/dist/src/backend/services/run-script/service/port-allocation.service.d.ts.map +1 -0
- package/dist/src/backend/services/run-script/service/port-allocation.service.js.map +1 -0
- package/dist/src/backend/services/run-script/service/port-allocation.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/run-script/service/port-allocation.service.test.js.map +1 -0
- package/dist/src/backend/services/{run-script-config-persistence.service.d.ts → run-script/service/run-script-config-persistence.service.d.ts} +10 -1
- package/dist/src/backend/services/run-script/service/run-script-config-persistence.service.d.ts.map +1 -0
- package/dist/src/backend/services/{run-script-config-persistence.service.js → run-script/service/run-script-config-persistence.service.js} +46 -2
- package/dist/src/backend/services/run-script/service/run-script-config-persistence.service.js.map +1 -0
- package/dist/src/backend/services/run-script/service/run-script-config-persistence.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/{run-script-config-persistence.service.test.js → run-script/service/run-script-config-persistence.service.test.js} +47 -0
- package/dist/src/backend/services/run-script/service/run-script-config-persistence.service.test.js.map +1 -0
- package/dist/src/backend/services/run-script/service/run-script-domain-exports.test.js +11 -1
- package/dist/src/backend/services/run-script/service/run-script-domain-exports.test.js.map +1 -1
- package/dist/src/backend/services/run-script/service/run-script-process-utils.d.ts.map +1 -1
- package/dist/src/backend/services/run-script/service/run-script-process-utils.js +1 -1
- package/dist/src/backend/services/run-script/service/run-script-process-utils.js.map +1 -1
- package/dist/src/backend/services/run-script/service/run-script-proxy.service.d.ts.map +1 -0
- package/dist/src/backend/services/{run-script-proxy.service.js → run-script/service/run-script-proxy.service.js} +3 -3
- package/dist/src/backend/services/run-script/service/run-script-proxy.service.js.map +1 -0
- package/dist/src/backend/services/run-script/service/run-script-proxy.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/{run-script-proxy.service.test.js → run-script/service/run-script-proxy.service.test.js} +3 -3
- package/dist/src/backend/services/run-script/service/run-script-proxy.service.test.js.map +1 -0
- package/dist/src/backend/services/run-script/service/run-script-state-machine.service.d.ts +9 -9
- package/dist/src/backend/services/run-script/service/run-script-state-machine.service.d.ts.map +1 -1
- package/dist/src/backend/services/run-script/service/run-script-state-machine.service.js +8 -8
- package/dist/src/backend/services/run-script/service/run-script-state-machine.service.js.map +1 -1
- package/dist/src/backend/services/run-script/service/run-script.service.js +16 -16
- package/dist/src/backend/services/run-script/service/run-script.service.js.map +1 -1
- package/dist/src/backend/services/run-script/service/run-script.service.test.js +5 -5
- package/dist/src/backend/services/run-script/service/run-script.service.test.js.map +1 -1
- package/dist/src/backend/services/run-script/service/startup-script.service.d.ts.map +1 -1
- package/dist/src/backend/services/run-script/service/startup-script.service.js +4 -7
- package/dist/src/backend/services/run-script/service/startup-script.service.js.map +1 -1
- package/dist/src/backend/services/run-script/service/startup-script.service.test.js +5 -1
- package/dist/src/backend/services/run-script/service/startup-script.service.test.js.map +1 -1
- package/dist/src/backend/services/service-registry-check.helpers.d.ts +6 -0
- package/dist/src/backend/services/service-registry-check.helpers.d.ts.map +1 -0
- package/dist/src/backend/services/service-registry-check.helpers.js +22 -0
- package/dist/src/backend/services/service-registry-check.helpers.js.map +1 -0
- package/dist/src/backend/services/service-registry-check.test.d.ts +2 -0
- package/dist/src/backend/services/service-registry-check.test.d.ts.map +1 -0
- package/dist/src/backend/services/service-registry-check.test.js +36 -0
- package/dist/src/backend/services/service-registry-check.test.js.map +1 -0
- package/dist/src/backend/services/session/index.d.ts +0 -2
- package/dist/src/backend/services/session/index.d.ts.map +1 -1
- package/dist/src/backend/services/session/index.js +0 -2
- package/dist/src/backend/services/session/index.js.map +1 -1
- package/dist/src/backend/services/session/resources/agent-session.accessor.d.ts +4 -3
- package/dist/src/backend/services/session/resources/agent-session.accessor.d.ts.map +1 -1
- package/dist/src/backend/services/session/resources/agent-session.accessor.js +6 -15
- package/dist/src/backend/services/session/resources/agent-session.accessor.js.map +1 -1
- package/dist/src/backend/services/session/resources/agent-session.accessor.test.js +11 -15
- package/dist/src/backend/services/session/resources/agent-session.accessor.test.js.map +1 -1
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.js +25 -9
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.js.map +1 -1
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.test.js +109 -26
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.test.js.map +1 -1
- package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.js +2 -2
- package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.js.map +1 -1
- package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.test.d.ts +2 -0
- package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.test.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.test.js +119 -0
- package/dist/src/backend/services/session/service/acp/child-workspace-mcp-server.test.js.map +1 -0
- package/dist/src/backend/services/session/service/bridges.d.ts +1 -0
- package/dist/src/backend/services/session/service/bridges.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js +3 -3
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.test.js +16 -16
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/data/session-data.service.d.ts +18 -166
- package/dist/src/backend/services/session/service/data/session-data.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/data/session-data.service.js +68 -36
- package/dist/src/backend/services/session/service/data/session-data.service.js.map +1 -1
- package/dist/src/backend/services/session/service/data/session-data.service.test.d.ts +2 -0
- package/dist/src/backend/services/session/service/data/session-data.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/data/session-data.service.test.js +103 -0
- package/dist/src/backend/services/session/service/data/session-data.service.test.js.map +1 -0
- package/dist/src/backend/services/session/service/data/session-provider-resolver.service.d.ts +9 -0
- package/dist/src/backend/services/session/service/data/session-provider-resolver.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/data/session-provider-resolver.service.js +15 -5
- package/dist/src/backend/services/session/service/data/session-provider-resolver.service.js.map +1 -1
- package/dist/src/backend/services/session/service/data/session-provider-resolver.service.test.js +23 -10
- package/dist/src/backend/services/session/service/data/session-provider-resolver.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/index.d.ts +3 -2
- package/dist/src/backend/services/session/service/index.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/index.js +2 -2
- package/dist/src/backend/services/session/service/index.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.d.ts +15 -4
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.js +63 -6
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.text-streaming.test.d.ts +2 -0
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.text-streaming.test.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.text-streaming.test.js +230 -0
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.text-streaming.test.js.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.d.ts +2 -1
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.js +3 -28
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.test.d.ts +2 -0
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.test.js +33 -0
- package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.test.js.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.js +15 -4
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.test.js +59 -6
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js +14 -7
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.test.js +74 -44
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.prompt-builder.d.ts +5 -0
- package/dist/src/backend/services/session/service/lifecycle/session.prompt-builder.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.prompt-builder.js +19 -11
- package/dist/src/backend/services/session/service/lifecycle/session.prompt-builder.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.prompt-builder.test.js +32 -1
- package/dist/src/backend/services/session/service/lifecycle/session.prompt-builder.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.repository.d.ts +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.repository.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.repository.js +3 -3
- package/dist/src/backend/services/session/service/lifecycle/session.repository.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.repository.test.js +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.repository.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.service.js +2 -0
- package/dist/src/backend/services/session/service/lifecycle/session.service.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.service.test.js +18 -2
- package/dist/src/backend/services/session/service/lifecycle/session.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/session-domain.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/session-domain.service.js +2 -1
- package/dist/src/backend/services/session/service/session-domain.service.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-queue.test.js +1 -0
- package/dist/src/backend/services/session/service/store/session-queue.test.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-replay-builder.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/store/session-replay-builder.js +2 -1
- package/dist/src/backend/services/session/service/store/session-replay-builder.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-replay-builder.test.js +13 -0
- package/dist/src/backend/services/session/service/store/session-replay-builder.test.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-runtime-machine.test.js +1 -0
- package/dist/src/backend/services/session/service/store/session-runtime-machine.test.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-store-registry.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/store/session-store-registry.js +1 -0
- package/dist/src/backend/services/session/service/store/session-store-registry.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-store.types.d.ts +1 -0
- package/dist/src/backend/services/session/service/store/session-store.types.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/store/session-transcript.d.ts +1 -0
- package/dist/src/backend/services/session/service/store/session-transcript.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/store/session-transcript.js +83 -15
- package/dist/src/backend/services/session/service/store/session-transcript.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-transcript.test.js +148 -30
- package/dist/src/backend/services/session/service/store/session-transcript.test.js.map +1 -1
- package/dist/src/backend/services/session/service/store/slash-command-cache.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/store/slash-command-cache.service.js +23 -18
- package/dist/src/backend/services/session/service/store/slash-command-cache.service.js.map +1 -1
- package/dist/src/backend/services/session/service/store/slash-command-cache.service.test.js +70 -19
- package/dist/src/backend/services/session/service/store/slash-command-cache.service.test.js.map +1 -1
- package/dist/src/backend/services/session/types.d.ts +25 -0
- package/dist/src/backend/services/session/types.d.ts.map +1 -0
- package/dist/src/backend/services/session/types.js +2 -0
- package/dist/src/backend/services/session/types.js.map +1 -0
- package/dist/src/backend/services/settings/index.d.ts +1 -3
- package/dist/src/backend/services/settings/index.d.ts.map +1 -1
- package/dist/src/backend/services/settings/index.js +1 -3
- package/dist/src/backend/services/settings/index.js.map +1 -1
- package/dist/src/backend/services/settings/resources/user-settings.accessor.d.ts +3 -1
- package/dist/src/backend/services/settings/resources/user-settings.accessor.d.ts.map +1 -1
- package/dist/src/backend/services/settings/resources/user-settings.accessor.js +9 -0
- package/dist/src/backend/services/settings/resources/user-settings.accessor.js.map +1 -1
- package/dist/src/backend/services/settings/service/health.service.d.ts +6 -0
- package/dist/src/backend/services/settings/service/health.service.d.ts.map +1 -0
- package/dist/src/backend/services/settings/service/health.service.js +8 -0
- package/dist/src/backend/services/settings/service/health.service.js.map +1 -0
- package/dist/src/backend/services/settings/service/health.service.test.d.ts +2 -0
- package/dist/src/backend/services/settings/service/health.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/settings/service/health.service.test.js +16 -0
- package/dist/src/backend/services/settings/service/health.service.test.js.map +1 -0
- package/dist/src/backend/services/settings/service/index.d.ts +3 -0
- package/dist/src/backend/services/settings/service/index.d.ts.map +1 -0
- package/dist/src/backend/services/settings/service/index.js +3 -0
- package/dist/src/backend/services/settings/service/index.js.map +1 -0
- package/dist/src/backend/services/settings/service/settings-domain-exports.test.d.ts +2 -0
- package/dist/src/backend/services/settings/service/settings-domain-exports.test.d.ts.map +1 -0
- package/dist/src/backend/services/settings/service/settings-domain-exports.test.js +9 -0
- package/dist/src/backend/services/settings/service/settings-domain-exports.test.js.map +1 -0
- package/dist/src/backend/services/settings/service/user-settings.service.d.ts +27 -0
- package/dist/src/backend/services/settings/service/user-settings.service.d.ts.map +1 -0
- package/dist/src/backend/services/settings/service/user-settings.service.js +23 -0
- package/dist/src/backend/services/settings/service/user-settings.service.js.map +1 -0
- package/dist/src/backend/services/settings/service/user-settings.service.test.d.ts +2 -0
- package/dist/src/backend/services/settings/service/user-settings.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/settings/service/user-settings.service.test.js +58 -0
- package/dist/src/backend/services/settings/service/user-settings.service.test.js.map +1 -0
- package/dist/src/backend/services/terminal/index.d.ts +0 -1
- package/dist/src/backend/services/terminal/index.d.ts.map +1 -1
- package/dist/src/backend/services/terminal/index.js +0 -1
- package/dist/src/backend/services/terminal/index.js.map +1 -1
- package/dist/src/backend/services/terminal/service/index.d.ts +2 -0
- package/dist/src/backend/services/terminal/service/index.d.ts.map +1 -1
- package/dist/src/backend/services/terminal/service/index.js +1 -0
- package/dist/src/backend/services/terminal/service/index.js.map +1 -1
- package/dist/src/backend/services/terminal/service/terminal-domain-exports.test.js +4 -1
- package/dist/src/backend/services/terminal/service/terminal-domain-exports.test.js.map +1 -1
- package/dist/src/backend/services/terminal/service/terminal-session.service.d.ts +95 -0
- package/dist/src/backend/services/terminal/service/terminal-session.service.d.ts.map +1 -0
- package/dist/src/backend/services/terminal/service/terminal-session.service.js +43 -0
- package/dist/src/backend/services/terminal/service/terminal-session.service.js.map +1 -0
- package/dist/src/backend/services/terminal/service/terminal-session.service.test.d.ts +2 -0
- package/dist/src/backend/services/terminal/service/terminal-session.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/terminal/service/terminal-session.service.test.js +46 -0
- package/dist/src/backend/services/terminal/service/terminal-session.service.test.js.map +1 -0
- package/dist/src/backend/services/workspace/index.d.ts +0 -3
- package/dist/src/backend/services/workspace/index.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/index.js +0 -3
- package/dist/src/backend/services/workspace/index.js.map +1 -1
- package/dist/src/backend/services/workspace/resources/project.accessor.d.ts +1 -1
- package/dist/src/backend/services/workspace/resources/workspace.accessor.d.ts +66 -2
- package/dist/src/backend/services/workspace/resources/workspace.accessor.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/resources/workspace.accessor.js +259 -2
- package/dist/src/backend/services/workspace/resources/workspace.accessor.js.map +1 -1
- package/dist/src/backend/services/workspace/resources/workspace.accessor.test.js +517 -0
- package/dist/src/backend/services/workspace/resources/workspace.accessor.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/bridges.d.ts +1 -2
- package/dist/src/backend/services/workspace/service/bridges.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/index.d.ts +12 -1
- package/dist/src/backend/services/workspace/service/index.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/index.js +11 -1
- package/dist/src/backend/services/workspace/service/index.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.d.ts +9 -0
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js +26 -36
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js +47 -10
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/data.service.d.ts +156 -122
- package/dist/src/backend/services/workspace/service/lifecycle/data.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/data.service.js +27 -7
- package/dist/src/backend/services/workspace/service/lifecycle/data.service.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/data.service.test.js +14 -1
- package/dist/src/backend/services/workspace/service/lifecycle/data.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.js +8 -1
- package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.test.js +3 -5
- package/dist/src/backend/services/workspace/service/lifecycle/state-machine.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.d.ts +206 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.js +26 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-auto-iteration.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.d.ts +76 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.js +32 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.test.d.ts +2 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.test.js +65 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-pr-snapshot.service.test.js.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.d.ts +243 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.js +42 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-ratchet.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-relationships.service.d.ts +186 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-relationships.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-relationships.service.js +11 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-relationships.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.d.ts +161 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.js +51 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-run-script.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-state-capabilities.test.d.ts +2 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-state-capabilities.test.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-state-capabilities.test.js +96 -0
- package/dist/src/backend/services/workspace/service/lifecycle/workspace-state-capabilities.test.js.map +1 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.d.ts +2 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.js +11 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.js.map +1 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.test.d.ts +2 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.test.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.test.js +24 -0
- package/dist/src/backend/services/workspace/service/pr-discovery-schedule.test.js.map +1 -0
- package/dist/src/backend/services/workspace/service/query/project-management.service.d.ts +27 -21
- package/dist/src/backend/services/workspace/service/query/project-management.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.d.ts +446 -0
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.js +23 -0
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.test.d.ts +2 -0
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.test.js +36 -0
- package/dist/src/backend/services/workspace/service/query/workspace-maintenance.service.test.js.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.d.ts +58 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.js +24 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.test.d.ts +2 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.test.js +28 -0
- package/dist/src/backend/services/workspace/service/query/workspace-notification.service.test.js.map +1 -0
- package/dist/src/backend/services/workspace/service/query/workspace-query.service.d.ts +45 -55
- package/dist/src/backend/services/workspace/service/query/workspace-query.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/query/workspace-query.service.js +13 -64
- package/dist/src/backend/services/workspace/service/query/workspace-query.service.js.map +1 -1
- package/dist/src/backend/services/workspace/service/query/workspace-query.service.test.js +110 -64
- package/dist/src/backend/services/workspace/service/query/workspace-query.service.test.js.map +1 -1
- package/dist/src/backend/services/{workspace-snapshot-store.service.d.ts → workspace/service/snapshot/workspace-snapshot-store.service.d.ts} +24 -45
- package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.d.ts.map +1 -0
- package/dist/src/backend/services/{workspace-snapshot-store.service.js → workspace/service/snapshot/workspace-snapshot-store.service.js} +144 -31
- package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/{workspace-snapshot-store.service.test.js → workspace/service/snapshot/workspace-snapshot-store.service.test.js} +229 -18
- package/dist/src/backend/services/workspace/service/snapshot/workspace-snapshot-store.service.test.js.map +1 -0
- package/dist/src/backend/services/workspace/service/state/kanban-state.d.ts +18 -3
- package/dist/src/backend/services/workspace/service/state/kanban-state.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/state/kanban-state.js +136 -16
- package/dist/src/backend/services/workspace/service/state/kanban-state.js.map +1 -1
- package/dist/src/backend/services/workspace/service/state/kanban-state.test.js +319 -63
- package/dist/src/backend/services/workspace/service/state/kanban-state.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/workspace-domain-exports.test.js +18 -1
- package/dist/src/backend/services/workspace/service/workspace-domain-exports.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/worktree/git-clone.service.d.ts.map +1 -0
- package/dist/src/backend/services/{git-clone.service.js → workspace/service/worktree/git-clone.service.js} +4 -4
- package/dist/src/backend/services/workspace/service/worktree/git-clone.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/worktree/git-clone.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/{git-clone.service.test.js → workspace/service/worktree/git-clone.service.test.js} +1 -1
- package/dist/src/backend/services/workspace/service/worktree/git-clone.service.test.js.map +1 -0
- package/dist/src/backend/services/{git-ops.service.d.ts → workspace/service/worktree/git-ops.service.d.ts} +3 -4
- package/dist/src/backend/services/workspace/service/worktree/git-ops.service.d.ts.map +1 -0
- package/dist/src/backend/services/{git-ops.service.js → workspace/service/worktree/git-ops.service.js} +55 -33
- package/dist/src/backend/services/workspace/service/worktree/git-ops.service.js.map +1 -0
- package/dist/src/backend/services/workspace/service/worktree/git-ops.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/{git-ops.service.test.js → workspace/service/worktree/git-ops.service.test.js} +89 -16
- package/dist/src/backend/services/workspace/service/worktree/git-ops.service.test.js.map +1 -0
- package/dist/src/backend/services/workspace/service/worktree/worktree-init.test.js +27 -19
- package/dist/src/backend/services/workspace/service/worktree/worktree-init.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.js +3 -1
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.js.map +1 -1
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.test.js +66 -2
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace/types.d.ts +32 -0
- package/dist/src/backend/services/workspace/types.d.ts.map +1 -0
- package/dist/src/backend/services/workspace/types.js +2 -0
- package/dist/src/backend/services/workspace/types.js.map +1 -0
- package/dist/src/backend/services/workspace-git-state.service.d.ts +99 -0
- package/dist/src/backend/services/workspace-git-state.service.d.ts.map +1 -0
- package/dist/src/backend/services/workspace-git-state.service.js +393 -0
- package/dist/src/backend/services/workspace-git-state.service.js.map +1 -0
- package/dist/src/backend/services/workspace-git-state.service.test.d.ts +2 -0
- package/dist/src/backend/services/workspace-git-state.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/workspace-git-state.service.test.js +476 -0
- package/dist/src/backend/services/workspace-git-state.service.test.js.map +1 -0
- package/dist/src/backend/testing/typescript-import-test-utils.d.ts +11 -0
- package/dist/src/backend/testing/typescript-import-test-utils.d.ts.map +1 -0
- package/dist/src/backend/testing/typescript-import-test-utils.js +47 -0
- package/dist/src/backend/testing/typescript-import-test-utils.js.map +1 -0
- package/dist/src/backend/trpc/admin.router.test.js +18 -26
- package/dist/src/backend/trpc/admin.router.test.js.map +1 -1
- package/dist/src/backend/trpc/admin.trpc.d.ts +7 -5
- package/dist/src/backend/trpc/admin.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/admin.trpc.js +11 -15
- package/dist/src/backend/trpc/admin.trpc.js.map +1 -1
- package/dist/src/backend/trpc/application-error-mapper.d.ts +4 -0
- package/dist/src/backend/trpc/application-error-mapper.d.ts.map +1 -0
- package/dist/src/backend/trpc/application-error-mapper.js +16 -0
- package/dist/src/backend/trpc/application-error-mapper.js.map +1 -0
- package/dist/src/backend/trpc/application-error-mapper.test.d.ts +2 -0
- package/dist/src/backend/trpc/application-error-mapper.test.d.ts.map +1 -0
- package/dist/src/backend/trpc/application-error-mapper.test.js +23 -0
- package/dist/src/backend/trpc/application-error-mapper.test.js.map +1 -0
- package/dist/src/backend/trpc/auto-iteration.trpc.d.ts +1 -1
- package/dist/src/backend/trpc/auto-iteration.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/auto-iteration.trpc.js +20 -12
- package/dist/src/backend/trpc/auto-iteration.trpc.js.map +1 -1
- package/dist/src/backend/trpc/auto-iteration.trpc.test.js +10 -9
- package/dist/src/backend/trpc/auto-iteration.trpc.test.js.map +1 -1
- package/dist/src/backend/trpc/closed-sessions.router.test.js +3 -4
- package/dist/src/backend/trpc/closed-sessions.router.test.js.map +1 -1
- package/dist/src/backend/trpc/closed-sessions.trpc.d.ts +5 -5
- package/dist/src/backend/trpc/closed-sessions.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/closed-sessions.trpc.js +8 -4
- package/dist/src/backend/trpc/closed-sessions.trpc.js.map +1 -1
- package/dist/src/backend/trpc/context-dependencies.test.d.ts +2 -0
- package/dist/src/backend/trpc/context-dependencies.test.d.ts.map +1 -0
- package/dist/src/backend/trpc/context-dependencies.test.js +134 -0
- package/dist/src/backend/trpc/context-dependencies.test.js.map +1 -0
- package/dist/src/backend/trpc/decision-log.router.test.js +11 -8
- package/dist/src/backend/trpc/decision-log.router.test.js.map +1 -1
- package/dist/src/backend/trpc/decision-log.trpc.d.ts +3 -3
- package/dist/src/backend/trpc/decision-log.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/decision-log.trpc.js +6 -7
- package/dist/src/backend/trpc/decision-log.trpc.js.map +1 -1
- package/dist/src/backend/trpc/github.router.test.js +12 -6
- package/dist/src/backend/trpc/github.router.test.js.map +1 -1
- package/dist/src/backend/trpc/github.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/github.trpc.js +11 -8
- package/dist/src/backend/trpc/github.trpc.js.map +1 -1
- package/dist/src/backend/trpc/index.d.ts +528 -828
- package/dist/src/backend/trpc/index.d.ts.map +1 -1
- package/dist/src/backend/trpc/index.js +0 -1
- package/dist/src/backend/trpc/index.js.map +1 -1
- package/dist/src/backend/trpc/issue-filter.d.ts.map +1 -1
- package/dist/src/backend/trpc/issue-filter.js.map +1 -1
- package/dist/src/backend/trpc/linear.router.test.js +21 -21
- package/dist/src/backend/trpc/linear.router.test.js.map +1 -1
- package/dist/src/backend/trpc/linear.trpc.d.ts +4 -4
- package/dist/src/backend/trpc/linear.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/linear.trpc.js +9 -10
- package/dist/src/backend/trpc/linear.trpc.js.map +1 -1
- package/dist/src/backend/trpc/periodic-task.trpc.d.ts +17 -17
- package/dist/src/backend/trpc/periodic-task.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/periodic-task.trpc.js +17 -17
- package/dist/src/backend/trpc/periodic-task.trpc.js.map +1 -1
- package/dist/src/backend/trpc/project.router.test.js +20 -21
- package/dist/src/backend/trpc/project.router.test.js.map +1 -1
- package/dist/src/backend/trpc/project.trpc.d.ts +31 -25
- package/dist/src/backend/trpc/project.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/project.trpc.js +32 -30
- package/dist/src/backend/trpc/project.trpc.js.map +1 -1
- package/dist/src/backend/trpc/session.router.test.js +11 -9
- package/dist/src/backend/trpc/session.router.test.js.map +1 -1
- package/dist/src/backend/trpc/session.trpc.d.ts +47 -404
- package/dist/src/backend/trpc/session.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/session.trpc.js +30 -27
- package/dist/src/backend/trpc/session.trpc.js.map +1 -1
- package/dist/src/backend/trpc/trpc.d.ts +2 -4
- package/dist/src/backend/trpc/trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/trpc.js +14 -12
- package/dist/src/backend/trpc/trpc.js.map +1 -1
- package/dist/src/backend/trpc/trpc.test.js +58 -1
- package/dist/src/backend/trpc/trpc.test.js.map +1 -1
- package/dist/src/backend/trpc/user-settings.router.test.js +27 -14
- package/dist/src/backend/trpc/user-settings.router.test.js.map +1 -1
- package/dist/src/backend/trpc/user-settings.trpc.d.ts +6 -3
- package/dist/src/backend/trpc/user-settings.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/user-settings.trpc.js +13 -14
- package/dist/src/backend/trpc/user-settings.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/children.router.test.d.ts +2 -0
- package/dist/src/backend/trpc/workspace/children.router.test.d.ts.map +1 -0
- package/dist/src/backend/trpc/workspace/children.router.test.js +257 -0
- package/dist/src/backend/trpc/workspace/children.router.test.js.map +1 -0
- package/dist/src/backend/trpc/workspace/children.trpc.d.ts +154 -0
- package/dist/src/backend/trpc/workspace/children.trpc.d.ts.map +1 -0
- package/dist/src/backend/trpc/workspace/children.trpc.js +163 -0
- package/dist/src/backend/trpc/workspace/children.trpc.js.map +1 -0
- package/dist/src/backend/trpc/workspace/composition.test.d.ts +2 -0
- package/dist/src/backend/trpc/workspace/composition.test.d.ts.map +1 -0
- package/dist/src/backend/trpc/workspace/composition.test.js +51 -0
- package/dist/src/backend/trpc/workspace/composition.test.js.map +1 -0
- package/dist/src/backend/trpc/workspace/files.router.test.js +6 -0
- package/dist/src/backend/trpc/workspace/files.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace/files.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/files.trpc.js +14 -13
- package/dist/src/backend/trpc/workspace/files.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/git.router.test.js +137 -147
- package/dist/src/backend/trpc/workspace/git.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace/git.trpc.d.ts +2 -2
- package/dist/src/backend/trpc/workspace/git.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/git.trpc.js +53 -75
- package/dist/src/backend/trpc/workspace/git.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/ide.router.test.js +10 -9
- package/dist/src/backend/trpc/workspace/ide.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace/ide.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/ide.trpc.js +4 -4
- package/dist/src/backend/trpc/workspace/ide.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/init.router.test.js +18 -41
- package/dist/src/backend/trpc/workspace/init.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace/init.trpc.d.ts +22 -18
- package/dist/src/backend/trpc/workspace/init.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/init.trpc.js +14 -11
- package/dist/src/backend/trpc/workspace/init.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/run-script.router.test.js +6 -10
- package/dist/src/backend/trpc/workspace/run-script.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/run-script.trpc.js +3 -4
- package/dist/src/backend/trpc/workspace/run-script.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts +43 -35
- package/dist/src/backend/trpc/workspace/workspace-helpers.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace/workspace-helpers.js +7 -8
- package/dist/src/backend/trpc/workspace/workspace-helpers.js.map +1 -1
- package/dist/src/backend/trpc/workspace/workspace-helpers.test.js +17 -15
- package/dist/src/backend/trpc/workspace/workspace-helpers.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace.router.test.js +139 -265
- package/dist/src/backend/trpc/workspace.router.test.js.map +1 -1
- package/dist/src/backend/trpc/workspace.trpc.d.ts +1491 -325
- package/dist/src/backend/trpc/workspace.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace.trpc.js +47 -258
- package/dist/src/backend/trpc/workspace.trpc.js.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/renderer-window.d.ts.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/renderer-window.js +2 -1
- package/dist/src/shared/acp-protocol/protocol/renderer-window.js.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/websocket.d.ts +9 -0
- package/dist/src/shared/acp-protocol/protocol/websocket.d.ts.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/websocket.js +1 -0
- package/dist/src/shared/acp-protocol/protocol/websocket.js.map +1 -1
- package/dist/src/shared/core/enums.d.ts +5 -0
- package/dist/src/shared/core/enums.d.ts.map +1 -1
- package/dist/src/shared/core/enums.js +4 -0
- package/dist/src/shared/core/enums.js.map +1 -1
- package/dist/src/shared/core/index.d.ts +2 -2
- package/dist/src/shared/core/index.d.ts.map +1 -1
- package/dist/src/shared/core/index.js +2 -2
- package/dist/src/shared/core/index.js.map +1 -1
- package/dist/src/shared/core/workspace-sidebar-status.d.ts +4 -2
- package/dist/src/shared/core/workspace-sidebar-status.d.ts.map +1 -1
- package/dist/src/shared/core/workspace-sidebar-status.js +11 -0
- package/dist/src/shared/core/workspace-sidebar-status.js.map +1 -1
- package/dist/src/shared/schemas/export-data.schema.d.ts +20 -12
- package/dist/src/shared/schemas/export-data.schema.d.ts.map +1 -1
- package/dist/src/shared/schemas/export-data.schema.js +3 -1
- package/dist/src/shared/schemas/export-data.schema.js.map +1 -1
- package/dist/src/shared/session-runtime.d.ts +6 -3
- package/dist/src/shared/session-runtime.d.ts.map +1 -1
- package/dist/src/shared/session-runtime.js +10 -0
- package/dist/src/shared/session-runtime.js.map +1 -1
- package/dist/src/shared/workspace-flow-state.d.ts +4 -2
- package/dist/src/shared/workspace-flow-state.d.ts.map +1 -1
- package/dist/src/shared/workspace-flow-state.js +16 -1
- package/dist/src/shared/workspace-flow-state.js.map +1 -1
- package/dist/src/shared/workspace-snapshot.d.ts +1020 -0
- package/dist/src/shared/workspace-snapshot.d.ts.map +1 -0
- package/dist/src/shared/workspace-snapshot.js +113 -0
- package/dist/src/shared/workspace-snapshot.js.map +1 -0
- package/dist/src/shared/workspace-status-reason.d.ts +6 -3
- package/dist/src/shared/workspace-status-reason.d.ts.map +1 -1
- package/dist/src/shared/workspace-status-reason.js +35 -0
- package/dist/src/shared/workspace-status-reason.js.map +1 -1
- package/dist/src/test-utils/application-graph.d.ts +69 -0
- package/dist/src/test-utils/application-graph.d.ts.map +1 -0
- package/dist/src/test-utils/application-graph.js +353 -0
- package/dist/src/test-utils/application-graph.js.map +1 -0
- package/dist/tsconfig.backend.tsbuildinfo +1 -1
- package/package.json +2 -5
- package/prisma/migrations/20260717150000_add_pr_discovery_schedule/migration.sql +8 -0
- package/prisma/migrations/20260717160000_add_ratchet_review_trigger_mode/migration.sql +2 -0
- package/prisma/schema.prisma +13 -1
- package/dist/client/assets/channel-76ipWABm.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-FuxnCTTL.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-FuxnCTTL.js +0 -1
- package/dist/client/assets/index-kItkrW7R.css +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Dhf9Ohaz.js +0 -1
- package/dist/src/backend/clients/index.d.ts +0 -2
- package/dist/src/backend/clients/index.d.ts.map +0 -1
- package/dist/src/backend/clients/index.js +0 -2
- package/dist/src/backend/clients/index.js.map +0 -1
- package/dist/src/backend/orchestration/decision-log-query.service.d.ts.map +0 -1
- package/dist/src/backend/orchestration/decision-log-query.service.js.map +0 -1
- package/dist/src/backend/orchestration/decision-log-query.service.test.d.ts +0 -2
- package/dist/src/backend/orchestration/decision-log-query.service.test.d.ts.map +0 -1
- package/dist/src/backend/orchestration/decision-log-query.service.test.js +0 -44
- package/dist/src/backend/orchestration/decision-log-query.service.test.js.map +0 -1
- package/dist/src/backend/services/factory-config.service.d.ts.map +0 -1
- package/dist/src/backend/services/factory-config.service.js.map +0 -1
- package/dist/src/backend/services/factory-config.service.test.d.ts.map +0 -1
- package/dist/src/backend/services/factory-config.service.test.js.map +0 -1
- package/dist/src/backend/services/git-clone.service.d.ts.map +0 -1
- package/dist/src/backend/services/git-clone.service.js.map +0 -1
- package/dist/src/backend/services/git-clone.service.test.d.ts.map +0 -1
- package/dist/src/backend/services/git-clone.service.test.js.map +0 -1
- package/dist/src/backend/services/git-ops.service.d.ts.map +0 -1
- package/dist/src/backend/services/git-ops.service.js.map +0 -1
- package/dist/src/backend/services/git-ops.service.test.d.ts.map +0 -1
- package/dist/src/backend/services/git-ops.service.test.js.map +0 -1
- package/dist/src/backend/services/port-allocation.service.d.ts.map +0 -1
- package/dist/src/backend/services/port-allocation.service.js.map +0 -1
- package/dist/src/backend/services/port-allocation.service.test.d.ts.map +0 -1
- package/dist/src/backend/services/port-allocation.service.test.js.map +0 -1
- package/dist/src/backend/services/run-script-config-persistence.service.d.ts.map +0 -1
- package/dist/src/backend/services/run-script-config-persistence.service.js.map +0 -1
- package/dist/src/backend/services/run-script-config-persistence.service.test.d.ts.map +0 -1
- package/dist/src/backend/services/run-script-config-persistence.service.test.js.map +0 -1
- package/dist/src/backend/services/run-script-proxy.service.d.ts.map +0 -1
- package/dist/src/backend/services/run-script-proxy.service.js.map +0 -1
- package/dist/src/backend/services/run-script-proxy.service.test.d.ts.map +0 -1
- package/dist/src/backend/services/run-script-proxy.service.test.js.map +0 -1
- package/dist/src/backend/services/workspace/service/query/user-settings-query.service.d.ts +0 -24
- package/dist/src/backend/services/workspace/service/query/user-settings-query.service.d.ts.map +0 -1
- package/dist/src/backend/services/workspace/service/query/user-settings-query.service.js +0 -17
- package/dist/src/backend/services/workspace/service/query/user-settings-query.service.js.map +0 -1
- package/dist/src/backend/services/workspace-snapshot-store.service.d.ts.map +0 -1
- package/dist/src/backend/services/workspace-snapshot-store.service.js.map +0 -1
- package/dist/src/backend/services/workspace-snapshot-store.service.test.d.ts.map +0 -1
- package/dist/src/backend/services/workspace-snapshot-store.service.test.js.map +0 -1
- package/dist/src/backend/trpc/procedures/index.d.ts +0 -2
- package/dist/src/backend/trpc/procedures/index.d.ts.map +0 -1
- package/dist/src/backend/trpc/procedures/index.js +0 -2
- package/dist/src/backend/trpc/procedures/index.js.map +0 -1
- package/dist/src/backend/trpc/procedures/project-scoped.d.ts +0 -7
- package/dist/src/backend/trpc/procedures/project-scoped.d.ts.map +0 -1
- package/dist/src/backend/trpc/procedures/project-scoped.js +0 -18
- package/dist/src/backend/trpc/procedures/project-scoped.js.map +0 -1
- package/dist/src/backend/trpc/procedures/project-scoped.test.d.ts +0 -2
- package/dist/src/backend/trpc/procedures/project-scoped.test.d.ts.map +0 -1
- package/dist/src/backend/trpc/procedures/project-scoped.test.js +0 -17
- package/dist/src/backend/trpc/procedures/project-scoped.test.js.map +0 -1
- /package/dist/src/backend/services/{factory-config.service.test.d.ts → run-script/service/factory-config.service.test.d.ts} +0 -0
- /package/dist/src/backend/services/{port-allocation.service.d.ts → run-script/service/port-allocation.service.d.ts} +0 -0
- /package/dist/src/backend/services/{port-allocation.service.js → run-script/service/port-allocation.service.js} +0 -0
- /package/dist/src/backend/services/{port-allocation.service.test.d.ts → run-script/service/port-allocation.service.test.d.ts} +0 -0
- /package/dist/src/backend/services/{port-allocation.service.test.js → run-script/service/port-allocation.service.test.js} +0 -0
- /package/dist/src/backend/services/{run-script-config-persistence.service.test.d.ts → run-script/service/run-script-config-persistence.service.test.d.ts} +0 -0
- /package/dist/src/backend/services/{run-script-proxy.service.d.ts → run-script/service/run-script-proxy.service.d.ts} +0 -0
- /package/dist/src/backend/services/{run-script-proxy.service.test.d.ts → run-script/service/run-script-proxy.service.test.d.ts} +0 -0
- /package/dist/src/backend/services/{workspace-snapshot-store.service.test.d.ts → workspace/service/snapshot/workspace-snapshot-store.service.test.d.ts} +0 -0
- /package/dist/src/backend/services/{git-clone.service.d.ts → workspace/service/worktree/git-clone.service.d.ts} +0 -0
- /package/dist/src/backend/services/{git-clone.service.test.d.ts → workspace/service/worktree/git-clone.service.test.d.ts} +0 -0
- /package/dist/src/backend/services/{git-ops.service.test.d.ts → workspace/service/worktree/git-ops.service.test.d.ts} +0 -0
|
@@ -3,26 +3,30 @@ import { 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', () => ({
|
|
6
|
-
|
|
6
|
+
workspaceDataService: {
|
|
7
7
|
findById: vi.fn(),
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
},
|
|
9
|
+
workspaceRatchetService: {
|
|
10
|
+
findCandidates: vi.fn(),
|
|
11
|
+
findCandidateById: vi.fn(),
|
|
12
|
+
clearActiveSession: vi.fn(),
|
|
13
|
+
enable: vi.fn(),
|
|
14
|
+
disable: vi.fn(),
|
|
15
|
+
transitionStateIfEnabled: vi.fn(),
|
|
16
|
+
settleIdleWhileDisabled: vi.fn(),
|
|
17
|
+
recordDispatchIfEnabled: vi.fn(),
|
|
18
|
+
adoptActiveSessionIfEnabled: vi.fn(),
|
|
19
|
+
recordSessionEnd: vi.fn(),
|
|
16
20
|
},
|
|
17
21
|
}));
|
|
18
22
|
vi.mock('@/backend/services/session', () => ({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
sessionDataService: {
|
|
24
|
+
findAgentSessionById: vi.fn(),
|
|
25
|
+
findAgentSessionsByWorkspaceId: vi.fn(),
|
|
22
26
|
},
|
|
23
27
|
}));
|
|
24
28
|
vi.mock('@/backend/services/settings', () => ({
|
|
25
|
-
|
|
29
|
+
userSettingsService: {
|
|
26
30
|
get: vi.fn(),
|
|
27
31
|
getDefaultSessionProvider: vi.fn(),
|
|
28
32
|
},
|
|
@@ -40,15 +44,16 @@ vi.mock('@/backend/services/logger.service', () => ({
|
|
|
40
44
|
error: vi.fn(),
|
|
41
45
|
}),
|
|
42
46
|
}));
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import { workspaceAccessor } from '../../../../backend/services/workspace/index.js';
|
|
47
|
+
import { userSettingsService } from '../../../../backend/services/settings/index.js';
|
|
48
|
+
import { workspaceDataService, workspaceRatchetService } from '../../../../backend/services/workspace/index.js';
|
|
46
49
|
import { fixerSessionService } from './fixer-session.service.js';
|
|
47
|
-
import { RATCHET_STATE_CHANGED, RATCHET_TOGGLED, ratchetService, } from './ratchet.service.js';
|
|
50
|
+
import { RATCHET_DISPATCH_CHANGED, RATCHET_STATE_CHANGED, RATCHET_TOGGLED, ratchetService, } from './ratchet.service.js';
|
|
48
51
|
import { buildRatchetingLogContext } from './ratchet-decision-logging.helpers.js';
|
|
49
52
|
import { computeDispatchSnapshotKey, computeLatestReviewActivityAtMs, determineRatchetState, } from './ratchet-pr-state.helpers.js';
|
|
50
53
|
const mockSessionBridge = {
|
|
54
|
+
findSessionById: vi.fn(),
|
|
51
55
|
findSessionsByWorkspaceId: vi.fn(),
|
|
56
|
+
acquireFixerSession: vi.fn(),
|
|
52
57
|
isSessionRunning: vi.fn(),
|
|
53
58
|
isSessionWorking: vi.fn(),
|
|
54
59
|
stopSession: vi.fn(),
|
|
@@ -57,6 +62,10 @@ const mockSessionBridge = {
|
|
|
57
62
|
sendSessionMessage: vi.fn(),
|
|
58
63
|
injectCommittedUserMessage: vi.fn(),
|
|
59
64
|
};
|
|
65
|
+
const mockWorkspaceBridge = {
|
|
66
|
+
findFixerContext: vi.fn(),
|
|
67
|
+
recordSessionEnd: vi.fn(),
|
|
68
|
+
};
|
|
60
69
|
const mockGitHubBridge = {
|
|
61
70
|
extractPRInfo: vi.fn(),
|
|
62
71
|
getPRFullDetails: vi.fn(),
|
|
@@ -67,7 +76,7 @@ const mockGitHubBridge = {
|
|
|
67
76
|
fetchAndComputePRState: vi.fn(),
|
|
68
77
|
isRecentlyFetched: vi.fn(),
|
|
69
78
|
isFetchInFlight: vi.fn(),
|
|
70
|
-
startFetch: vi.fn(),
|
|
79
|
+
startFetch: vi.fn(() => 41),
|
|
71
80
|
registerFetch: vi.fn(),
|
|
72
81
|
cancelFetch: vi.fn(),
|
|
73
82
|
};
|
|
@@ -86,18 +95,20 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
86
95
|
session: mockSessionBridge,
|
|
87
96
|
github: mockGitHubBridge,
|
|
88
97
|
snapshot: mockSnapshotBridge,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
vi.mocked(
|
|
92
|
-
vi.mocked(
|
|
93
|
-
vi.mocked(
|
|
94
|
-
vi.mocked(
|
|
95
|
-
vi.mocked(
|
|
98
|
+
workspace: mockWorkspaceBridge,
|
|
99
|
+
});
|
|
100
|
+
vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(true);
|
|
101
|
+
vi.mocked(workspaceRatchetService.settleIdleWhileDisabled).mockResolvedValue(true);
|
|
102
|
+
vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockResolvedValue(true);
|
|
103
|
+
vi.mocked(workspaceRatchetService.adoptActiveSessionIfEnabled).mockResolvedValue(true);
|
|
104
|
+
vi.mocked(workspaceRatchetService.recordSessionEnd).mockResolvedValue(true);
|
|
105
|
+
vi.mocked(mockWorkspaceBridge.recordSessionEnd).mockResolvedValue(true);
|
|
106
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
96
107
|
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
97
108
|
vi.mocked(mockGitHubBridge.getAuthenticatedUsername).mockResolvedValue(null);
|
|
98
109
|
vi.mocked(mockGitHubBridge.getResolvedReviewCommentIds).mockResolvedValue(new Set());
|
|
99
110
|
vi.mocked(mockSessionBridge.isSessionWorking).mockReturnValue(false);
|
|
100
|
-
vi.mocked(
|
|
111
|
+
vi.mocked(userSettingsService.get).mockResolvedValue({
|
|
101
112
|
id: 'settings-1',
|
|
102
113
|
userId: 'default',
|
|
103
114
|
preferredIde: 'cursor',
|
|
@@ -108,6 +119,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
108
119
|
cachedSlashCommands: null,
|
|
109
120
|
ratchetEnabled: false,
|
|
110
121
|
ratchetReplyToPrComments: true,
|
|
122
|
+
ratchetReviewTriggerMode: 'CHANGES_REQUESTED',
|
|
111
123
|
defaultSessionProvider: 'CLAUDE',
|
|
112
124
|
defaultClaudeModel: 'sonnet',
|
|
113
125
|
defaultCodexModel: 'default',
|
|
@@ -118,13 +130,18 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
118
130
|
createdAt: new Date('2026-01-01T00:00:00.000Z'),
|
|
119
131
|
updatedAt: new Date('2026-01-01T00:00:00.000Z'),
|
|
120
132
|
});
|
|
121
|
-
vi.mocked(
|
|
133
|
+
vi.mocked(userSettingsService.getDefaultSessionProvider).mockResolvedValue('CLAUDE');
|
|
134
|
+
});
|
|
135
|
+
it('records session completion through the configured workspace bridge', async () => {
|
|
136
|
+
await ratchetService.recordSessionEnd('workspace-1', 'session-1', 'COMPLETED');
|
|
137
|
+
expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith('workspace-1', 'session-1', 'COMPLETED');
|
|
138
|
+
expect(workspaceRatchetService.recordSessionEnd).not.toHaveBeenCalled();
|
|
122
139
|
});
|
|
123
140
|
afterEach(() => {
|
|
124
141
|
ratchetService.removeAllListeners();
|
|
125
142
|
});
|
|
126
143
|
it('checks workspaces and processes each', async () => {
|
|
127
|
-
vi.mocked(
|
|
144
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue([
|
|
128
145
|
{
|
|
129
146
|
id: 'ws-1',
|
|
130
147
|
prUrl: 'https://github.com/example/repo/pull/1',
|
|
@@ -167,7 +184,6 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
167
184
|
ratchetDispatchRetryCount: 0,
|
|
168
185
|
};
|
|
169
186
|
const fetchPRStateSpy = vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState');
|
|
170
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
171
187
|
const triggerSpy = vi.spyOn(unsafeCoerce(ratchetService), 'triggerFixer');
|
|
172
188
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
173
189
|
expect(fetchPRStateSpy).not.toHaveBeenCalled();
|
|
@@ -176,7 +192,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
176
192
|
action: { type: 'DISABLED', reason: 'Workspace ratcheting disabled' },
|
|
177
193
|
newState: RatchetState.IDLE,
|
|
178
194
|
});
|
|
179
|
-
expect(
|
|
195
|
+
expect(workspaceRatchetService.settleIdleWhileDisabled).toHaveBeenCalledWith('ws-disabled', RatchetState.IDLE);
|
|
180
196
|
});
|
|
181
197
|
it('settles a disabled workspace to IDLE via CAS and emits an accurate fromState', async () => {
|
|
182
198
|
const workspace = {
|
|
@@ -193,13 +209,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
193
209
|
ratchetDispatchOutcome: null,
|
|
194
210
|
ratchetDispatchRetryCount: 0,
|
|
195
211
|
};
|
|
196
|
-
vi.mocked(
|
|
212
|
+
vi.mocked(workspaceRatchetService.settleIdleWhileDisabled).mockResolvedValue(true);
|
|
197
213
|
const events = [];
|
|
198
214
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
199
215
|
events.push(event);
|
|
200
216
|
});
|
|
201
217
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
202
|
-
expect(
|
|
218
|
+
expect(workspaceRatchetService.settleIdleWhileDisabled).toHaveBeenCalledWith('ws-disabled-settle', RatchetState.CI_FAILED);
|
|
203
219
|
expect(result).toMatchObject({
|
|
204
220
|
previousState: RatchetState.CI_FAILED,
|
|
205
221
|
newState: RatchetState.IDLE,
|
|
@@ -228,7 +244,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
228
244
|
ratchetDispatchOutcome: null,
|
|
229
245
|
ratchetDispatchRetryCount: 0,
|
|
230
246
|
};
|
|
231
|
-
vi.mocked(
|
|
247
|
+
vi.mocked(workspaceRatchetService.settleIdleWhileDisabled).mockResolvedValue(false);
|
|
232
248
|
const events = [];
|
|
233
249
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
234
250
|
events.push(event);
|
|
@@ -274,8 +290,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
274
290
|
},
|
|
275
291
|
],
|
|
276
292
|
});
|
|
277
|
-
vi.mocked(
|
|
278
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([
|
|
293
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([
|
|
279
294
|
{
|
|
280
295
|
id: 'chat-1',
|
|
281
296
|
workflow: 'default-followup',
|
|
@@ -316,8 +331,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
316
331
|
prState: 'OPEN',
|
|
317
332
|
prNumber: 4,
|
|
318
333
|
});
|
|
319
|
-
vi.mocked(
|
|
320
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
334
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
321
335
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
322
336
|
status: 'started',
|
|
323
337
|
sessionId: 'ratchet-session',
|
|
@@ -327,13 +341,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
327
341
|
expect(result).toMatchObject({
|
|
328
342
|
action: { type: 'TRIGGERED_FIXER' },
|
|
329
343
|
});
|
|
330
|
-
expect(
|
|
344
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalledWith('ws-change', {
|
|
331
345
|
sessionId: 'ratchet-session',
|
|
332
346
|
snapshotKey: '2026-01-02T00:00:00Z',
|
|
333
347
|
retryCount: 0,
|
|
334
348
|
});
|
|
335
349
|
const finalUpdatePayload = vi
|
|
336
|
-
.mocked(
|
|
350
|
+
.mocked(workspaceRatchetService.transitionStateIfEnabled)
|
|
337
351
|
.mock.calls.at(-1)?.[2];
|
|
338
352
|
expect(finalUpdatePayload).not.toHaveProperty('ratchetLastCiRunId');
|
|
339
353
|
expect(finalUpdatePayload).not.toHaveProperty('prReviewLastCheckedAt');
|
|
@@ -363,27 +377,32 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
363
377
|
prState: 'OPEN',
|
|
364
378
|
prNumber: 40,
|
|
365
379
|
});
|
|
366
|
-
vi.mocked(
|
|
380
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
367
381
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
368
382
|
status: 'started',
|
|
369
383
|
sessionId: 'raced-session',
|
|
370
384
|
promptSent: true,
|
|
371
385
|
});
|
|
372
|
-
vi.mocked(
|
|
373
|
-
vi.mocked(
|
|
374
|
-
vi.mocked(
|
|
386
|
+
vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockResolvedValue(false);
|
|
387
|
+
vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
|
|
388
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
375
389
|
id: 'ws-disable-race-dispatch',
|
|
376
390
|
ratchetEnabled: false,
|
|
377
391
|
});
|
|
378
392
|
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
393
|
+
const events = [];
|
|
394
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
395
|
+
events.push(event);
|
|
396
|
+
});
|
|
379
397
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
380
398
|
expect(result).toMatchObject({
|
|
381
399
|
newState: RatchetState.IDLE,
|
|
382
400
|
action: { type: 'DISABLED', reason: 'Workspace ratcheting disabled' },
|
|
383
401
|
});
|
|
384
|
-
expect(
|
|
402
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalledWith('ws-disable-race-dispatch', { sessionId: 'raced-session', snapshotKey: 'new-snapshot', retryCount: 0 });
|
|
385
403
|
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('raced-session');
|
|
386
404
|
expect(mockSnapshotBridge.recordReviewCheck).not.toHaveBeenCalled();
|
|
405
|
+
expect(events).toHaveLength(0);
|
|
387
406
|
});
|
|
388
407
|
it('dispatches when session is running but idle', async () => {
|
|
389
408
|
const workspace = {
|
|
@@ -409,8 +428,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
409
428
|
prState: 'OPEN',
|
|
410
429
|
prNumber: 44,
|
|
411
430
|
});
|
|
412
|
-
vi.mocked(
|
|
413
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([
|
|
431
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([
|
|
414
432
|
{
|
|
415
433
|
id: 'chat-idle-1',
|
|
416
434
|
workflow: 'default-followup',
|
|
@@ -455,8 +473,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
455
473
|
prState: 'OPEN',
|
|
456
474
|
prNumber: 5,
|
|
457
475
|
});
|
|
458
|
-
vi.mocked(
|
|
459
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
476
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
460
477
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
461
478
|
expect(result).toMatchObject({
|
|
462
479
|
action: {
|
|
@@ -464,7 +481,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
464
481
|
reason: 'PR state unchanged since last ratchet dispatch',
|
|
465
482
|
},
|
|
466
483
|
});
|
|
467
|
-
expect(
|
|
484
|
+
expect(mockSessionBridge.findSessionsByWorkspaceId).not.toHaveBeenCalled();
|
|
468
485
|
expect(mockSnapshotBridge.recordReviewCheck).not.toHaveBeenCalled();
|
|
469
486
|
});
|
|
470
487
|
it('does not dispatch repeatedly for unchanged CHANGES_REQUESTED state', async () => {
|
|
@@ -500,8 +517,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
500
517
|
},
|
|
501
518
|
],
|
|
502
519
|
});
|
|
503
|
-
vi.mocked(
|
|
504
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
520
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
505
521
|
const triggerSpy = vi.spyOn(unsafeCoerce(ratchetService), 'triggerFixer');
|
|
506
522
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
507
523
|
expect(triggerSpy).not.toHaveBeenCalled();
|
|
@@ -511,9 +527,9 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
511
527
|
reason: 'PR state unchanged since last ratchet dispatch',
|
|
512
528
|
},
|
|
513
529
|
});
|
|
514
|
-
expect(
|
|
530
|
+
expect(mockSessionBridge.findSessionsByWorkspaceId).not.toHaveBeenCalled();
|
|
515
531
|
});
|
|
516
|
-
it('
|
|
532
|
+
it('dispatches for CHANGES_REQUESTED when there are no PR review comments', async () => {
|
|
517
533
|
const workspace = {
|
|
518
534
|
id: 'ws-review-no-comments',
|
|
519
535
|
prUrl: 'https://github.com/example/repo/pull/56',
|
|
@@ -538,19 +554,20 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
538
554
|
prNumber: 56,
|
|
539
555
|
reviewComments: [],
|
|
540
556
|
});
|
|
541
|
-
vi.mocked(
|
|
542
|
-
vi.mocked(
|
|
557
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
558
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
559
|
+
status: 'started',
|
|
560
|
+
sessionId: 'ratchet-session',
|
|
561
|
+
promptSent: true,
|
|
562
|
+
});
|
|
543
563
|
const triggerSpy = vi.spyOn(unsafeCoerce(ratchetService), 'triggerFixer');
|
|
544
564
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
545
|
-
expect(triggerSpy).
|
|
565
|
+
expect(triggerSpy).toHaveBeenCalled();
|
|
546
566
|
expect(result).toMatchObject({
|
|
547
|
-
action: {
|
|
548
|
-
type: 'WAITING',
|
|
549
|
-
reason: 'No CI failures or PR review comments to address',
|
|
550
|
-
},
|
|
567
|
+
action: { type: 'TRIGGERED_FIXER' },
|
|
551
568
|
});
|
|
552
569
|
});
|
|
553
|
-
it('dispatches for PR review summary feedback
|
|
570
|
+
it('dispatches for PR review summary feedback in all-feedback mode', async () => {
|
|
554
571
|
const workspace = {
|
|
555
572
|
id: 'ws-review-summary',
|
|
556
573
|
prUrl: 'https://github.com/example/repo/pull/57',
|
|
@@ -565,7 +582,14 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
565
582
|
ratchetDispatchOutcome: null,
|
|
566
583
|
ratchetDispatchRetryCount: 0,
|
|
567
584
|
};
|
|
568
|
-
vi.
|
|
585
|
+
vi.mocked(userSettingsService.get).mockResolvedValue({
|
|
586
|
+
ratchetReviewTriggerMode: 'ALL_REVIEW_FEEDBACK',
|
|
587
|
+
ratchetReplyToPrComments: true,
|
|
588
|
+
ratchetPermissions: 'YOLO',
|
|
589
|
+
});
|
|
590
|
+
const fetchPRStateSpy = vi
|
|
591
|
+
.spyOn(unsafeCoerce(ratchetService), 'fetchPRState')
|
|
592
|
+
.mockResolvedValue({
|
|
569
593
|
ciStatus: CIStatus.SUCCESS,
|
|
570
594
|
snapshotKey: 'ci:SUCCESS|no-changes-requested:1767315600000|merge:clean',
|
|
571
595
|
hasChangesRequested: false,
|
|
@@ -584,8 +608,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
584
608
|
},
|
|
585
609
|
],
|
|
586
610
|
});
|
|
587
|
-
vi.mocked(
|
|
588
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
611
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
589
612
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
590
613
|
status: 'started',
|
|
591
614
|
sessionId: 'ratchet-session',
|
|
@@ -597,6 +620,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
597
620
|
newState: RatchetState.READY,
|
|
598
621
|
});
|
|
599
622
|
expect(fixerSessionService.acquireAndDispatch).toHaveBeenCalled();
|
|
623
|
+
expect(fetchPRStateSpy).toHaveBeenCalledWith(workspace, null, expect.objectContaining({ reviewTriggerMode: 'ALL_REVIEW_FEEDBACK' }), expect.any(AbortSignal));
|
|
600
624
|
});
|
|
601
625
|
it('treats closed PR as IDLE and does not dispatch', () => {
|
|
602
626
|
const state = determineRatchetState({
|
|
@@ -642,8 +666,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
642
666
|
},
|
|
643
667
|
],
|
|
644
668
|
});
|
|
645
|
-
vi.mocked(
|
|
646
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
669
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
647
670
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
648
671
|
status: 'started',
|
|
649
672
|
sessionId: 'ratchet-session',
|
|
@@ -655,9 +678,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
655
678
|
expect(result).toMatchObject({
|
|
656
679
|
action: { type: 'ERROR', error: 'Failed to deliver initial ratchet prompt' },
|
|
657
680
|
});
|
|
658
|
-
expect(
|
|
659
|
-
ratchetActiveSessionId: null,
|
|
660
|
-
});
|
|
681
|
+
expect(workspaceRatchetService.clearActiveSession).toHaveBeenCalledWith(workspace.id);
|
|
661
682
|
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('ratchet-session');
|
|
662
683
|
});
|
|
663
684
|
it('routes an aborted prompt-failure path through orphan cleanup', async () => {
|
|
@@ -669,7 +690,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
669
690
|
sessionId: 'aborted-prompt-session',
|
|
670
691
|
promptSent: false,
|
|
671
692
|
});
|
|
672
|
-
vi.mocked(
|
|
693
|
+
vi.mocked(workspaceRatchetService.clearActiveSession).mockImplementation(() => new Promise((resolve) => {
|
|
673
694
|
finishPointerClear = () => resolve({});
|
|
674
695
|
}));
|
|
675
696
|
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
@@ -683,13 +704,30 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
683
704
|
reviewComments: [],
|
|
684
705
|
hasMergeConflict: false,
|
|
685
706
|
}, 0, controller.signal);
|
|
686
|
-
await vi.waitFor(() => expect(
|
|
707
|
+
await vi.waitFor(() => expect(workspaceRatchetService.clearActiveSession).toHaveBeenCalled());
|
|
687
708
|
controller.abort(timeoutError);
|
|
688
709
|
finishPointerClear();
|
|
689
710
|
await expect(trigger).rejects.toBe(timeoutError);
|
|
690
|
-
expect(
|
|
711
|
+
expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalledWith('ws-aborted-prompt', 'aborted-prompt-session', 'COMPLETED');
|
|
691
712
|
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('aborted-prompt-session');
|
|
692
713
|
});
|
|
714
|
+
it('publishes a dispatch invalidation after lifecycle settlement', async () => {
|
|
715
|
+
const events = [];
|
|
716
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
717
|
+
events.push(event);
|
|
718
|
+
});
|
|
719
|
+
await ratchetService.recordSessionEnd('ws-1', 'session-1', 'DIED');
|
|
720
|
+
expect(events).toContainEqual({ workspaceId: 'ws-1' });
|
|
721
|
+
});
|
|
722
|
+
it('does not publish a dispatch change when lifecycle settlement loses its CAS', async () => {
|
|
723
|
+
const events = [];
|
|
724
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
725
|
+
events.push(event);
|
|
726
|
+
});
|
|
727
|
+
vi.mocked(mockWorkspaceBridge.recordSessionEnd).mockResolvedValue(false);
|
|
728
|
+
await ratchetService.recordSessionEnd('ws-1', 'session-1', 'DIED');
|
|
729
|
+
expect(events).toHaveLength(0);
|
|
730
|
+
});
|
|
693
731
|
it('does not dispatch on a clean PR with no new review activity', async () => {
|
|
694
732
|
const recentCheck = new Date();
|
|
695
733
|
const workspace = {
|
|
@@ -715,8 +753,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
715
753
|
prState: 'OPEN',
|
|
716
754
|
prNumber: 8,
|
|
717
755
|
});
|
|
718
|
-
vi.mocked(
|
|
719
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
756
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
720
757
|
const triggerSpy = vi.spyOn(unsafeCoerce(ratchetService), 'triggerFixer');
|
|
721
758
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
722
759
|
expect(triggerSpy).not.toHaveBeenCalled();
|
|
@@ -727,6 +764,56 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
727
764
|
},
|
|
728
765
|
});
|
|
729
766
|
});
|
|
767
|
+
it('dispatches stale actionable review comments when the PR snapshot changes', async () => {
|
|
768
|
+
const recentCheck = new Date();
|
|
769
|
+
const workspace = {
|
|
770
|
+
id: 'ws-stale-actionable-review',
|
|
771
|
+
prUrl: 'https://github.com/example/repo/pull/43',
|
|
772
|
+
prNumber: 43,
|
|
773
|
+
prState: 'OPEN',
|
|
774
|
+
prCiStatus: CIStatus.FAILURE,
|
|
775
|
+
ratchetEnabled: true,
|
|
776
|
+
ratchetState: RatchetState.CI_FAILED,
|
|
777
|
+
ratchetActiveSessionId: null,
|
|
778
|
+
ratchetLastCiRunId: 'failed-snapshot',
|
|
779
|
+
prReviewLastCheckedAt: recentCheck,
|
|
780
|
+
ratchetDispatchOutcome: 'COMPLETED',
|
|
781
|
+
ratchetDispatchRetryCount: 0,
|
|
782
|
+
};
|
|
783
|
+
vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
|
|
784
|
+
ciStatus: CIStatus.SUCCESS,
|
|
785
|
+
snapshotKey: 'successful-snapshot',
|
|
786
|
+
hasChangesRequested: false,
|
|
787
|
+
hasMergeConflict: false,
|
|
788
|
+
latestReviewActivityAtMs: recentCheck.getTime() - 1000,
|
|
789
|
+
statusCheckRollup: null,
|
|
790
|
+
prState: 'OPEN',
|
|
791
|
+
prNumber: 43,
|
|
792
|
+
reviewComments: [
|
|
793
|
+
{
|
|
794
|
+
author: 'reviewer',
|
|
795
|
+
body: 'Please handle this edge case.',
|
|
796
|
+
path: 'src/example.ts',
|
|
797
|
+
line: 10,
|
|
798
|
+
url: 'https://github.com/example/repo/pull/43#discussion_r1',
|
|
799
|
+
},
|
|
800
|
+
],
|
|
801
|
+
});
|
|
802
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
803
|
+
status: 'started',
|
|
804
|
+
sessionId: 'ratchet-review-session',
|
|
805
|
+
promptSent: true,
|
|
806
|
+
});
|
|
807
|
+
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
808
|
+
expect(result).toMatchObject({
|
|
809
|
+
action: { type: 'TRIGGERED_FIXER', sessionId: 'ratchet-review-session' },
|
|
810
|
+
});
|
|
811
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalledWith('ws-stale-actionable-review', {
|
|
812
|
+
sessionId: 'ratchet-review-session',
|
|
813
|
+
snapshotKey: 'successful-snapshot',
|
|
814
|
+
retryCount: 0,
|
|
815
|
+
});
|
|
816
|
+
});
|
|
730
817
|
it('returns disabled when stale check-state update loses disable race', async () => {
|
|
731
818
|
const recentCheck = new Date();
|
|
732
819
|
const workspace = {
|
|
@@ -752,12 +839,12 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
752
839
|
prState: 'OPEN',
|
|
753
840
|
prNumber: 41,
|
|
754
841
|
});
|
|
755
|
-
vi.mocked(
|
|
756
|
-
vi.mocked(
|
|
842
|
+
vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
|
|
843
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
757
844
|
id: 'ws-disable-race-state',
|
|
758
845
|
ratchetEnabled: false,
|
|
759
846
|
});
|
|
760
|
-
vi.mocked(
|
|
847
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
761
848
|
const events = [];
|
|
762
849
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
763
850
|
events.push(event);
|
|
@@ -795,19 +882,19 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
795
882
|
prState: 'OPEN',
|
|
796
883
|
prNumber: 42,
|
|
797
884
|
});
|
|
798
|
-
vi.mocked(
|
|
799
|
-
vi.mocked(
|
|
885
|
+
vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
|
|
886
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
800
887
|
id: 'ws-superseded',
|
|
801
888
|
ratchetEnabled: true,
|
|
802
889
|
ratchetState: RatchetState.IDLE,
|
|
803
890
|
});
|
|
804
|
-
vi.mocked(
|
|
891
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
805
892
|
const events = [];
|
|
806
893
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
807
894
|
events.push(event);
|
|
808
895
|
});
|
|
809
896
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
810
|
-
expect(
|
|
897
|
+
expect(workspaceRatchetService.transitionStateIfEnabled).toHaveBeenCalledWith('ws-superseded', RatchetState.CI_RUNNING, expect.objectContaining({ ratchetState: RatchetState.READY }));
|
|
811
898
|
expect(result).toMatchObject({
|
|
812
899
|
previousState: RatchetState.CI_RUNNING,
|
|
813
900
|
newState: RatchetState.CI_RUNNING,
|
|
@@ -844,8 +931,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
844
931
|
prState: 'OPEN',
|
|
845
932
|
prNumber: 13,
|
|
846
933
|
});
|
|
847
|
-
vi.mocked(
|
|
848
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
934
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
849
935
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
850
936
|
status: 'started',
|
|
851
937
|
sessionId: 'retry-session',
|
|
@@ -855,7 +941,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
855
941
|
expect(result).toMatchObject({
|
|
856
942
|
action: { type: 'TRIGGERED_FIXER' },
|
|
857
943
|
});
|
|
858
|
-
expect(
|
|
944
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalledWith('ws-died-retry', {
|
|
859
945
|
sessionId: 'retry-session',
|
|
860
946
|
snapshotKey: 'same-snapshot',
|
|
861
947
|
retryCount: 2,
|
|
@@ -887,22 +973,26 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
887
973
|
prNumber: 14,
|
|
888
974
|
reviewComments: [],
|
|
889
975
|
});
|
|
890
|
-
vi.mocked(
|
|
891
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
976
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
892
977
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
893
978
|
status: 'started',
|
|
894
979
|
sessionId: 'retry-session',
|
|
895
980
|
promptSent: true,
|
|
896
981
|
});
|
|
982
|
+
const events = [];
|
|
983
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
984
|
+
events.push(event);
|
|
985
|
+
});
|
|
897
986
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
898
987
|
expect(result).toMatchObject({
|
|
899
988
|
action: { type: 'TRIGGERED_FIXER' },
|
|
900
989
|
});
|
|
901
|
-
expect(
|
|
990
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalledWith('ws-died-clean', {
|
|
902
991
|
sessionId: 'retry-session',
|
|
903
992
|
snapshotKey: 'clean-snapshot',
|
|
904
993
|
retryCount: 1,
|
|
905
994
|
});
|
|
995
|
+
expect(events).toContainEqual({ workspaceId: 'ws-died-clean' });
|
|
906
996
|
});
|
|
907
997
|
it('stops retrying a died fixer once the retry budget is exhausted', async () => {
|
|
908
998
|
const workspace = {
|
|
@@ -928,7 +1018,6 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
928
1018
|
prState: 'OPEN',
|
|
929
1019
|
prNumber: 15,
|
|
930
1020
|
});
|
|
931
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
932
1021
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
933
1022
|
expect(result).toMatchObject({
|
|
934
1023
|
action: {
|
|
@@ -962,8 +1051,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
962
1051
|
prState: 'OPEN',
|
|
963
1052
|
prNumber: 16,
|
|
964
1053
|
});
|
|
965
|
-
vi.mocked(
|
|
966
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
1054
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
967
1055
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
968
1056
|
status: 'started',
|
|
969
1057
|
sessionId: 'fresh-session',
|
|
@@ -973,7 +1061,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
973
1061
|
expect(result).toMatchObject({
|
|
974
1062
|
action: { type: 'TRIGGERED_FIXER' },
|
|
975
1063
|
});
|
|
976
|
-
expect(
|
|
1064
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalledWith('ws-died-changed', { sessionId: 'fresh-session', snapshotKey: 'new-snapshot', retryCount: 0 });
|
|
977
1065
|
});
|
|
978
1066
|
it('does not redispatch when the previous fixer completed and PR state is unchanged', async () => {
|
|
979
1067
|
const workspace = {
|
|
@@ -999,7 +1087,6 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
999
1087
|
prState: 'OPEN',
|
|
1000
1088
|
prNumber: 17,
|
|
1001
1089
|
});
|
|
1002
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
1003
1090
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
1004
1091
|
expect(result).toMatchObject({
|
|
1005
1092
|
action: {
|
|
@@ -1009,6 +1096,51 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1009
1096
|
});
|
|
1010
1097
|
expect(fixerSessionService.acquireAndDispatch).not.toHaveBeenCalled();
|
|
1011
1098
|
});
|
|
1099
|
+
it('dispatches a fresh fixer after switching PRs with identical merge-conflict state', async () => {
|
|
1100
|
+
const previousSnapshotKey = computeDispatchSnapshotKey(123, CIStatus.SUCCESS, false, null, null, true);
|
|
1101
|
+
const currentSnapshotKey = computeDispatchSnapshotKey(456, CIStatus.SUCCESS, false, null, null, true);
|
|
1102
|
+
expect(previousSnapshotKey).toBe('pr:123|ci:SUCCESS|no-changes-requested:none|merge:conflict');
|
|
1103
|
+
expect(currentSnapshotKey).toBe('pr:456|ci:SUCCESS|no-changes-requested:none|merge:conflict');
|
|
1104
|
+
const workspace = {
|
|
1105
|
+
id: 'ws-pr-switch-merge-conflict',
|
|
1106
|
+
prUrl: 'https://github.com/example/repo/pull/456',
|
|
1107
|
+
prNumber: 456,
|
|
1108
|
+
prState: 'OPEN',
|
|
1109
|
+
prCiStatus: CIStatus.SUCCESS,
|
|
1110
|
+
ratchetEnabled: true,
|
|
1111
|
+
ratchetState: RatchetState.MERGE_CONFLICT,
|
|
1112
|
+
ratchetActiveSessionId: null,
|
|
1113
|
+
ratchetLastCiRunId: previousSnapshotKey,
|
|
1114
|
+
prReviewLastCheckedAt: new Date('2026-01-01T00:00:00Z'),
|
|
1115
|
+
ratchetDispatchOutcome: 'COMPLETED',
|
|
1116
|
+
ratchetDispatchRetryCount: 2,
|
|
1117
|
+
};
|
|
1118
|
+
vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({
|
|
1119
|
+
ciStatus: CIStatus.SUCCESS,
|
|
1120
|
+
snapshotKey: currentSnapshotKey,
|
|
1121
|
+
hasChangesRequested: false,
|
|
1122
|
+
hasMergeConflict: true,
|
|
1123
|
+
latestReviewActivityAtMs: null,
|
|
1124
|
+
statusCheckRollup: null,
|
|
1125
|
+
prState: 'OPEN',
|
|
1126
|
+
prNumber: 456,
|
|
1127
|
+
reviewComments: [],
|
|
1128
|
+
});
|
|
1129
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
1130
|
+
status: 'started',
|
|
1131
|
+
sessionId: 'fresh-pr-session',
|
|
1132
|
+
promptSent: true,
|
|
1133
|
+
});
|
|
1134
|
+
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
1135
|
+
expect(result).toMatchObject({
|
|
1136
|
+
action: { type: 'TRIGGERED_FIXER' },
|
|
1137
|
+
});
|
|
1138
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalledWith(workspace.id, {
|
|
1139
|
+
sessionId: 'fresh-pr-session',
|
|
1140
|
+
snapshotKey: currentSnapshotKey,
|
|
1141
|
+
retryCount: 0,
|
|
1142
|
+
});
|
|
1143
|
+
});
|
|
1012
1144
|
it('settles the dispatch as DIED when ratchet session process is not running', async () => {
|
|
1013
1145
|
const workspace = {
|
|
1014
1146
|
id: 'ws-stale-active',
|
|
@@ -1024,7 +1156,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1024
1156
|
ratchetDispatchOutcome: 'RUNNING',
|
|
1025
1157
|
ratchetDispatchRetryCount: 0,
|
|
1026
1158
|
};
|
|
1027
|
-
vi.mocked(
|
|
1159
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
|
|
1028
1160
|
id: 'ratchet-session',
|
|
1029
1161
|
provider: 'CLAUDE',
|
|
1030
1162
|
status: SessionStatus.RUNNING,
|
|
@@ -1032,7 +1164,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1032
1164
|
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(false);
|
|
1033
1165
|
const result = await unsafeCoerce(ratchetService).checkActiveFixerSession(workspace);
|
|
1034
1166
|
expect(result).toEqual({ kind: 'settled', outcome: 'DIED' });
|
|
1035
|
-
expect(
|
|
1167
|
+
expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith(workspace.id, 'ratchet-session', 'DIED');
|
|
1036
1168
|
});
|
|
1037
1169
|
it('settles the dispatch as DIED when ratchet session is not found in database', async () => {
|
|
1038
1170
|
const workspace = {
|
|
@@ -1049,10 +1181,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1049
1181
|
ratchetDispatchOutcome: 'RUNNING',
|
|
1050
1182
|
ratchetDispatchRetryCount: 0,
|
|
1051
1183
|
};
|
|
1052
|
-
vi.mocked(
|
|
1184
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue(null);
|
|
1185
|
+
const events = [];
|
|
1186
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
1187
|
+
events.push(event);
|
|
1188
|
+
});
|
|
1053
1189
|
const result = await unsafeCoerce(ratchetService).checkActiveFixerSession(workspace);
|
|
1054
1190
|
expect(result).toEqual({ kind: 'settled', outcome: 'DIED' });
|
|
1055
|
-
expect(
|
|
1191
|
+
expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith(workspace.id, 'deleted-session', 'DIED');
|
|
1192
|
+
expect(events).toEqual([{ workspaceId: 'ws-missing-session' }]);
|
|
1056
1193
|
});
|
|
1057
1194
|
it('reports a concurrent end when another path already settled the dispatch', async () => {
|
|
1058
1195
|
const workspace = {
|
|
@@ -1069,10 +1206,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1069
1206
|
ratchetDispatchOutcome: 'RUNNING',
|
|
1070
1207
|
ratchetDispatchRetryCount: 0,
|
|
1071
1208
|
};
|
|
1072
|
-
vi.mocked(
|
|
1073
|
-
vi.mocked(
|
|
1209
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue(null);
|
|
1210
|
+
vi.mocked(mockWorkspaceBridge.recordSessionEnd).mockResolvedValue(false);
|
|
1211
|
+
const events = [];
|
|
1212
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
1213
|
+
events.push(event);
|
|
1214
|
+
});
|
|
1074
1215
|
const result = await unsafeCoerce(ratchetService).checkActiveFixerSession(workspace);
|
|
1075
1216
|
expect(result).toEqual({ kind: 'ended_concurrently' });
|
|
1217
|
+
expect(events).toHaveLength(0);
|
|
1076
1218
|
});
|
|
1077
1219
|
it('waits for the next cycle when the fixer ends concurrently mid-check', async () => {
|
|
1078
1220
|
const workspace = {
|
|
@@ -1098,9 +1240,8 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1098
1240
|
prState: 'OPEN',
|
|
1099
1241
|
prNumber: 12,
|
|
1100
1242
|
});
|
|
1101
|
-
vi.mocked(
|
|
1102
|
-
vi.mocked(
|
|
1103
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
1243
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue(null);
|
|
1244
|
+
vi.mocked(mockWorkspaceBridge.recordSessionEnd).mockResolvedValue(false);
|
|
1104
1245
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
1105
1246
|
expect(result).toMatchObject({
|
|
1106
1247
|
action: {
|
|
@@ -1125,7 +1266,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1125
1266
|
ratchetDispatchOutcome: 'RUNNING',
|
|
1126
1267
|
ratchetDispatchRetryCount: 0,
|
|
1127
1268
|
};
|
|
1128
|
-
vi.mocked(
|
|
1269
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
|
|
1129
1270
|
id: 'ratchet-session',
|
|
1130
1271
|
provider: 'CLAUDE',
|
|
1131
1272
|
status: SessionStatus.RUNNING,
|
|
@@ -1135,7 +1276,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1135
1276
|
vi.mocked(mockSessionBridge.stopSession).mockResolvedValue();
|
|
1136
1277
|
const result = await unsafeCoerce(ratchetService).checkActiveFixerSession(workspace);
|
|
1137
1278
|
expect(result).toEqual({ kind: 'settled', outcome: 'COMPLETED' });
|
|
1138
|
-
expect(
|
|
1279
|
+
expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith(workspace.id, 'ratchet-session', 'COMPLETED');
|
|
1139
1280
|
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('ratchet-session');
|
|
1140
1281
|
});
|
|
1141
1282
|
it('decides to trigger fixer when context is actionable', async () => {
|
|
@@ -1218,11 +1359,19 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1218
1359
|
it('ignores review activity authored by the authenticated user', () => {
|
|
1219
1360
|
const latestActivity = computeLatestReviewActivityAtMs({
|
|
1220
1361
|
reviews: [
|
|
1221
|
-
{
|
|
1222
|
-
|
|
1362
|
+
{
|
|
1363
|
+
submittedAt: '2026-01-02T00:00:00Z',
|
|
1364
|
+
author: { login: 'ratchet-bot' },
|
|
1365
|
+
state: 'CHANGES_REQUESTED',
|
|
1366
|
+
},
|
|
1367
|
+
{
|
|
1368
|
+
submittedAt: '2026-01-01T00:00:00Z',
|
|
1369
|
+
author: { login: 'reviewer' },
|
|
1370
|
+
state: 'CHANGES_REQUESTED',
|
|
1371
|
+
},
|
|
1223
1372
|
],
|
|
1224
1373
|
comments: [{ updatedAt: '2026-01-02T01:00:00Z', author: { login: 'ratchet-bot' } }],
|
|
1225
|
-
}, [{ updatedAt: '2026-01-01T02:00:00Z', author: { login: 'reviewer2' } }], 'ratchet-bot');
|
|
1374
|
+
}, [{ updatedAt: '2026-01-01T02:00:00Z', author: { login: 'reviewer2' } }], 'ratchet-bot', 'CHANGES_REQUESTED');
|
|
1226
1375
|
expect(latestActivity).toBe(new Date('2026-01-01T02:00:00Z').getTime());
|
|
1227
1376
|
});
|
|
1228
1377
|
describe('determineRatchetState', () => {
|
|
@@ -1285,7 +1434,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1285
1434
|
});
|
|
1286
1435
|
});
|
|
1287
1436
|
describe('computeDispatchSnapshotKey', () => {
|
|
1288
|
-
const callComputeSnapshotKey = (ciStatus, hasChangesRequested, latestReviewActivityAtMs, statusChecks) => computeDispatchSnapshotKey(ciStatus, hasChangesRequested, latestReviewActivityAtMs, statusChecks);
|
|
1437
|
+
const callComputeSnapshotKey = (ciStatus, hasChangesRequested, latestReviewActivityAtMs, statusChecks) => computeDispatchSnapshotKey(123, ciStatus, hasChangesRequested, latestReviewActivityAtMs, statusChecks);
|
|
1289
1438
|
it('includes CI status in key for non-failure states', () => {
|
|
1290
1439
|
const key = callComputeSnapshotKey(CIStatus.SUCCESS, false, null, null);
|
|
1291
1440
|
expect(key).toContain('ci:SUCCESS');
|
|
@@ -1329,36 +1478,60 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1329
1478
|
});
|
|
1330
1479
|
});
|
|
1331
1480
|
describe('computeLatestReviewActivityAtMs edge cases', () => {
|
|
1332
|
-
const callCompute = (prDetails, reviewComments, authenticatedUsername) => computeLatestReviewActivityAtMs(prDetails, reviewComments, authenticatedUsername);
|
|
1481
|
+
const callCompute = (prDetails, reviewComments, authenticatedUsername) => computeLatestReviewActivityAtMs(prDetails, reviewComments, authenticatedUsername, 'CHANGES_REQUESTED');
|
|
1333
1482
|
it('returns null when there are no reviews or comments', () => {
|
|
1334
1483
|
expect(callCompute({ reviews: [], comments: [] }, [], null)).toBeNull();
|
|
1335
1484
|
});
|
|
1336
1485
|
it('returns null when all activity is from the authenticated user', () => {
|
|
1337
1486
|
expect(callCompute({
|
|
1338
|
-
reviews: [
|
|
1487
|
+
reviews: [
|
|
1488
|
+
{
|
|
1489
|
+
submittedAt: '2026-01-01T00:00:00Z',
|
|
1490
|
+
author: { login: 'me' },
|
|
1491
|
+
state: 'CHANGES_REQUESTED',
|
|
1492
|
+
},
|
|
1493
|
+
],
|
|
1339
1494
|
comments: [{ updatedAt: '2026-01-02T00:00:00Z', author: { login: 'me' } }],
|
|
1340
1495
|
}, [{ updatedAt: '2026-01-03T00:00:00Z', author: { login: 'me' } }], 'me')).toBeNull();
|
|
1341
1496
|
});
|
|
1342
1497
|
it('does not filter when authenticatedUsername is null', () => {
|
|
1343
1498
|
const result = callCompute({
|
|
1344
|
-
reviews: [
|
|
1499
|
+
reviews: [
|
|
1500
|
+
{
|
|
1501
|
+
submittedAt: '2026-01-01T00:00:00Z',
|
|
1502
|
+
author: { login: 'bot' },
|
|
1503
|
+
state: 'CHANGES_REQUESTED',
|
|
1504
|
+
},
|
|
1505
|
+
],
|
|
1345
1506
|
comments: [],
|
|
1346
1507
|
}, [], null);
|
|
1347
1508
|
expect(result).toBe(new Date('2026-01-01T00:00:00Z').getTime());
|
|
1348
1509
|
});
|
|
1349
|
-
it('ignores reviews
|
|
1510
|
+
it('ignores reviews with null submittedAt and ordinary PR comments', () => {
|
|
1350
1511
|
const result = callCompute({
|
|
1351
|
-
reviews: [
|
|
1512
|
+
reviews: [
|
|
1513
|
+
{
|
|
1514
|
+
submittedAt: null,
|
|
1515
|
+
author: { login: 'reviewer' },
|
|
1516
|
+
state: 'CHANGES_REQUESTED',
|
|
1517
|
+
},
|
|
1518
|
+
],
|
|
1352
1519
|
comments: [{ updatedAt: '2026-01-02T00:00:00Z', author: { login: 'commenter' } }],
|
|
1353
1520
|
}, [], null);
|
|
1354
|
-
expect(result).
|
|
1521
|
+
expect(result).toBeNull();
|
|
1355
1522
|
});
|
|
1356
1523
|
it('returns the latest timestamp across all sources', () => {
|
|
1357
1524
|
const result = callCompute({
|
|
1358
|
-
reviews: [
|
|
1525
|
+
reviews: [
|
|
1526
|
+
{
|
|
1527
|
+
submittedAt: '2026-01-01T00:00:00Z',
|
|
1528
|
+
author: { login: 'a' },
|
|
1529
|
+
state: 'CHANGES_REQUESTED',
|
|
1530
|
+
},
|
|
1531
|
+
],
|
|
1359
1532
|
comments: [{ updatedAt: '2026-01-03T00:00:00Z', author: { login: 'b' } }],
|
|
1360
1533
|
}, [{ updatedAt: '2026-01-02T00:00:00Z', author: { login: 'c' } }], null);
|
|
1361
|
-
expect(result).toBe(new Date('2026-01-
|
|
1534
|
+
expect(result).toBe(new Date('2026-01-02T00:00:00Z').getTime());
|
|
1362
1535
|
});
|
|
1363
1536
|
});
|
|
1364
1537
|
describe('processWorkspace error handling', () => {
|
|
@@ -1376,7 +1549,6 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1376
1549
|
ratchetDispatchRetryCount: 0,
|
|
1377
1550
|
};
|
|
1378
1551
|
vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue(null);
|
|
1379
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
1380
1552
|
const result = await unsafeCoerce(ratchetService).processWorkspace(workspace);
|
|
1381
1553
|
expect(result).toMatchObject({
|
|
1382
1554
|
action: { type: 'ERROR', error: 'Failed to fetch PR state' },
|
|
@@ -1402,7 +1574,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1402
1574
|
action: { type: 'WAITING', reason: 'recently_fetched' },
|
|
1403
1575
|
newState: RatchetState.IDLE,
|
|
1404
1576
|
});
|
|
1405
|
-
expect(
|
|
1577
|
+
expect(workspaceRatchetService.clearActiveSession).not.toHaveBeenCalled();
|
|
1406
1578
|
});
|
|
1407
1579
|
it('returns WAITING when shutting down', async () => {
|
|
1408
1580
|
unsafeCoerce(ratchetService).isShuttingDown = true;
|
|
@@ -1454,13 +1626,34 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1454
1626
|
expect(result).toEqual({ checked: 0, stateChanges: 0, actionsTriggered: 0, results: [] });
|
|
1455
1627
|
});
|
|
1456
1628
|
it('returns zero counts when no workspaces have PRs', async () => {
|
|
1457
|
-
vi.mocked(
|
|
1629
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue([]);
|
|
1458
1630
|
const result = await ratchetService.checkAllWorkspaces();
|
|
1459
1631
|
expect(result).toEqual({ checked: 0, stateChanges: 0, actionsTriggered: 0, results: [] });
|
|
1460
1632
|
});
|
|
1633
|
+
it('loads the global review trigger mode once for the whole batch', async () => {
|
|
1634
|
+
const workspaces = ['ws-one', 'ws-two'].map((id) => ({
|
|
1635
|
+
id,
|
|
1636
|
+
prUrl: `https://github.com/example/repo/pull/${id}`,
|
|
1637
|
+
prNumber: 1,
|
|
1638
|
+
prState: 'OPEN',
|
|
1639
|
+
prCiStatus: CIStatus.UNKNOWN,
|
|
1640
|
+
ratchetEnabled: true,
|
|
1641
|
+
ratchetState: RatchetState.IDLE,
|
|
1642
|
+
ratchetActiveSessionId: null,
|
|
1643
|
+
ratchetLastCiRunId: null,
|
|
1644
|
+
prReviewLastCheckedAt: null,
|
|
1645
|
+
ratchetDispatchOutcome: null,
|
|
1646
|
+
ratchetDispatchRetryCount: 0,
|
|
1647
|
+
}));
|
|
1648
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue(workspaces);
|
|
1649
|
+
vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue({ skipped: true, reason: 'recently_fetched' });
|
|
1650
|
+
const result = await ratchetService.checkAllWorkspaces();
|
|
1651
|
+
expect(result.checked).toBe(2);
|
|
1652
|
+
expect(userSettingsService.get).toHaveBeenCalledTimes(1);
|
|
1653
|
+
});
|
|
1461
1654
|
it('returns an error result when one workspace check times out', async () => {
|
|
1462
1655
|
unsafeCoerce(ratchetService).workspaceCheckTimeoutMs = 5;
|
|
1463
|
-
vi.mocked(
|
|
1656
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue([
|
|
1464
1657
|
{
|
|
1465
1658
|
id: 'ws-timeout',
|
|
1466
1659
|
prUrl: 'https://github.com/example/repo/pull/1',
|
|
@@ -1541,7 +1734,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1541
1734
|
ratchetDispatchOutcome: null,
|
|
1542
1735
|
ratchetDispatchRetryCount: 0,
|
|
1543
1736
|
}));
|
|
1544
|
-
vi.mocked(
|
|
1737
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue(workspaces);
|
|
1545
1738
|
const processWorkspaceSpy = vi.spyOn(unsafeCoerce(ratchetService), 'processWorkspace');
|
|
1546
1739
|
processWorkspaceSpy.mockImplementation((workspace, _opts, signal) => {
|
|
1547
1740
|
if (workspace.id !== 'ws-queued-timeout-3') {
|
|
@@ -1557,7 +1750,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1557
1750
|
});
|
|
1558
1751
|
});
|
|
1559
1752
|
const result = await ratchetService.checkAllWorkspaces();
|
|
1560
|
-
expect(processWorkspaceSpy).toHaveBeenCalledWith(expect.objectContaining({ id: 'ws-queued-timeout-3' }), undefined, expect.any(AbortSignal), expect.any(Function));
|
|
1753
|
+
expect(processWorkspaceSpy).toHaveBeenCalledWith(expect.objectContaining({ id: 'ws-queued-timeout-3' }), undefined, expect.any(AbortSignal), expect.any(Function), 'CHANGES_REQUESTED');
|
|
1561
1754
|
expect(result.results[3]).toMatchObject({
|
|
1562
1755
|
workspaceId: 'ws-queued-timeout-3',
|
|
1563
1756
|
action: { type: 'WAITING', reason: 'ran after queue' },
|
|
@@ -1572,7 +1765,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1572
1765
|
ratchetEnabled: true,
|
|
1573
1766
|
ratchetState: RatchetState.IDLE,
|
|
1574
1767
|
};
|
|
1575
|
-
vi.mocked(
|
|
1768
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue([workspace]);
|
|
1576
1769
|
let finishCommit;
|
|
1577
1770
|
const commitBarrier = new Promise((resolve) => {
|
|
1578
1771
|
finishCommit = resolve;
|
|
@@ -1614,7 +1807,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1614
1807
|
ratchetDispatchOutcome: null,
|
|
1615
1808
|
ratchetDispatchRetryCount: 0,
|
|
1616
1809
|
}));
|
|
1617
|
-
vi.mocked(
|
|
1810
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue(workspaces);
|
|
1618
1811
|
let active = 0;
|
|
1619
1812
|
let maximumActive = 0;
|
|
1620
1813
|
let releaseChecks;
|
|
@@ -1664,18 +1857,18 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1664
1857
|
ratchetService.removeAllListeners();
|
|
1665
1858
|
});
|
|
1666
1859
|
it('resets ratchet state to IDLE via CAS on fromState and emits a state change', async () => {
|
|
1667
|
-
vi.mocked(
|
|
1860
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
1668
1861
|
id: 'ws-closed',
|
|
1669
1862
|
ratchetEnabled: true,
|
|
1670
1863
|
ratchetState: RatchetState.CI_FAILED,
|
|
1671
1864
|
});
|
|
1672
|
-
vi.mocked(
|
|
1865
|
+
vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(true);
|
|
1673
1866
|
const stateEvents = [];
|
|
1674
1867
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
1675
1868
|
stateEvents.push(event);
|
|
1676
1869
|
});
|
|
1677
1870
|
await ratchetService.markPrClosed('ws-closed');
|
|
1678
|
-
expect(
|
|
1871
|
+
expect(workspaceRatchetService.transitionStateIfEnabled).toHaveBeenCalledWith('ws-closed', RatchetState.CI_FAILED, {
|
|
1679
1872
|
ratchetState: RatchetState.IDLE,
|
|
1680
1873
|
ratchetLastCheckedAt: expect.any(Date),
|
|
1681
1874
|
});
|
|
@@ -1688,7 +1881,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1688
1881
|
]);
|
|
1689
1882
|
});
|
|
1690
1883
|
it('emits the fromState that actually won the compare-and-swap after losing a race', async () => {
|
|
1691
|
-
vi.mocked(
|
|
1884
|
+
vi.mocked(workspaceDataService.findById)
|
|
1692
1885
|
.mockResolvedValueOnce({
|
|
1693
1886
|
id: 'ws-closed',
|
|
1694
1887
|
ratchetEnabled: true,
|
|
@@ -1699,7 +1892,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1699
1892
|
ratchetEnabled: true,
|
|
1700
1893
|
ratchetState: RatchetState.CI_RUNNING,
|
|
1701
1894
|
});
|
|
1702
|
-
vi.mocked(
|
|
1895
|
+
vi.mocked(workspaceRatchetService.transitionStateIfEnabled)
|
|
1703
1896
|
.mockResolvedValueOnce(false)
|
|
1704
1897
|
.mockResolvedValueOnce(true);
|
|
1705
1898
|
const stateEvents = [];
|
|
@@ -1707,8 +1900,8 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1707
1900
|
stateEvents.push(event);
|
|
1708
1901
|
});
|
|
1709
1902
|
await ratchetService.markPrClosed('ws-closed');
|
|
1710
|
-
expect(
|
|
1711
|
-
expect(
|
|
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 }));
|
|
1712
1905
|
expect(stateEvents).toEqual([
|
|
1713
1906
|
{
|
|
1714
1907
|
workspaceId: 'ws-closed',
|
|
@@ -1718,16 +1911,16 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1718
1911
|
]);
|
|
1719
1912
|
});
|
|
1720
1913
|
it('is a no-op when ratchet state is already IDLE', async () => {
|
|
1721
|
-
vi.mocked(
|
|
1914
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
1722
1915
|
id: 'ws-closed',
|
|
1723
1916
|
ratchetEnabled: true,
|
|
1724
1917
|
ratchetState: RatchetState.IDLE,
|
|
1725
1918
|
});
|
|
1726
1919
|
await ratchetService.markPrClosed('ws-closed');
|
|
1727
|
-
expect(
|
|
1920
|
+
expect(workspaceRatchetService.transitionStateIfEnabled).not.toHaveBeenCalled();
|
|
1728
1921
|
});
|
|
1729
1922
|
it('does not emit when ratcheting was disabled concurrently', async () => {
|
|
1730
|
-
vi.mocked(
|
|
1923
|
+
vi.mocked(workspaceDataService.findById)
|
|
1731
1924
|
.mockResolvedValueOnce({
|
|
1732
1925
|
id: 'ws-closed',
|
|
1733
1926
|
ratchetEnabled: true,
|
|
@@ -1738,7 +1931,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1738
1931
|
ratchetEnabled: false,
|
|
1739
1932
|
ratchetState: RatchetState.IDLE,
|
|
1740
1933
|
});
|
|
1741
|
-
vi.mocked(
|
|
1934
|
+
vi.mocked(workspaceRatchetService.transitionStateIfEnabled).mockResolvedValue(false);
|
|
1742
1935
|
const stateEvents = [];
|
|
1743
1936
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
1744
1937
|
stateEvents.push(event);
|
|
@@ -1747,9 +1940,9 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1747
1940
|
expect(stateEvents).toEqual([]);
|
|
1748
1941
|
});
|
|
1749
1942
|
it('is a no-op when workspace is not found', async () => {
|
|
1750
|
-
vi.mocked(
|
|
1943
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue(null);
|
|
1751
1944
|
await ratchetService.markPrClosed('ws-missing');
|
|
1752
|
-
expect(
|
|
1945
|
+
expect(workspaceRatchetService.transitionStateIfEnabled).not.toHaveBeenCalled();
|
|
1753
1946
|
});
|
|
1754
1947
|
it('does not continue to side effects after a timed-out await completes', async () => {
|
|
1755
1948
|
unsafeCoerce(ratchetService).workspaceCheckTimeoutMs = 5;
|
|
@@ -1769,7 +1962,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1769
1962
|
ratchetDispatchOutcome: null,
|
|
1770
1963
|
ratchetDispatchRetryCount: 0,
|
|
1771
1964
|
};
|
|
1772
|
-
vi.mocked(
|
|
1965
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue([workspace]);
|
|
1773
1966
|
let releaseFetch;
|
|
1774
1967
|
const fetchBarrier = new Promise((resolve) => {
|
|
1775
1968
|
releaseFetch = resolve;
|
|
@@ -1794,7 +1987,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1794
1987
|
releaseFetch();
|
|
1795
1988
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1796
1989
|
expect(finishSpy).not.toHaveBeenCalled();
|
|
1797
|
-
expect(
|
|
1990
|
+
expect(workspaceRatchetService.transitionStateIfEnabled).not.toHaveBeenCalled();
|
|
1798
1991
|
});
|
|
1799
1992
|
});
|
|
1800
1993
|
describe('checkWorkspaceById', () => {
|
|
@@ -1805,7 +1998,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1805
1998
|
});
|
|
1806
1999
|
it('returns null when workspace not found', async () => {
|
|
1807
2000
|
unsafeCoerce(ratchetService).isShuttingDown = false;
|
|
1808
|
-
vi.mocked(
|
|
2001
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(null);
|
|
1809
2002
|
const result = await ratchetService.checkWorkspaceById('ws-nonexistent');
|
|
1810
2003
|
expect(result).toBeNull();
|
|
1811
2004
|
});
|
|
@@ -1824,7 +2017,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1824
2017
|
ratchetDispatchOutcome: null,
|
|
1825
2018
|
ratchetDispatchRetryCount: 0,
|
|
1826
2019
|
};
|
|
1827
|
-
vi.mocked(
|
|
2020
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
|
|
1828
2021
|
vi.mocked(mockGitHubBridge.extractPRInfo).mockReturnValue({
|
|
1829
2022
|
owner: 'example',
|
|
1830
2023
|
repo: 'repo',
|
|
@@ -1852,7 +2045,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1852
2045
|
ratchetDispatchOutcome: null,
|
|
1853
2046
|
ratchetDispatchRetryCount: 0,
|
|
1854
2047
|
};
|
|
1855
|
-
vi.mocked(
|
|
2048
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
|
|
1856
2049
|
vi.mocked(mockGitHubBridge.extractPRInfo).mockReturnValue({
|
|
1857
2050
|
owner: 'example',
|
|
1858
2051
|
repo: 'repo',
|
|
@@ -1895,7 +2088,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1895
2088
|
ratchetDispatchOutcome: null,
|
|
1896
2089
|
ratchetDispatchRetryCount: 0,
|
|
1897
2090
|
};
|
|
1898
|
-
vi.mocked(
|
|
2091
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
|
|
1899
2092
|
vi.mocked(mockGitHubBridge.extractPRInfo).mockReturnValue({
|
|
1900
2093
|
owner: 'example',
|
|
1901
2094
|
repo: 'repo',
|
|
@@ -1936,7 +2129,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1936
2129
|
ratchetDispatchOutcome: null,
|
|
1937
2130
|
ratchetDispatchRetryCount: 0,
|
|
1938
2131
|
};
|
|
1939
|
-
vi.mocked(
|
|
2132
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
|
|
1940
2133
|
vi.mocked(mockGitHubBridge.extractPRInfo).mockReturnValue({
|
|
1941
2134
|
owner: 'example',
|
|
1942
2135
|
repo: 'repo',
|
|
@@ -1968,7 +2161,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
1968
2161
|
ratchetDispatchOutcome: null,
|
|
1969
2162
|
ratchetDispatchRetryCount: 0,
|
|
1970
2163
|
};
|
|
1971
|
-
vi.mocked(
|
|
2164
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspace);
|
|
1972
2165
|
let releaseCheck;
|
|
1973
2166
|
const checkBarrier = new Promise((resolve) => {
|
|
1974
2167
|
releaseCheck = () => resolve();
|
|
@@ -2009,8 +2202,8 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2009
2202
|
makeWorkspace('blocker-3'),
|
|
2010
2203
|
makeWorkspace('queued-target'),
|
|
2011
2204
|
];
|
|
2012
|
-
vi.mocked(
|
|
2013
|
-
vi.mocked(
|
|
2205
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue(workspaces);
|
|
2206
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(workspaces[3]);
|
|
2014
2207
|
let releaseBlockers;
|
|
2015
2208
|
const blockerBarrier = new Promise((resolve) => {
|
|
2016
2209
|
releaseBlockers = resolve;
|
|
@@ -2057,7 +2250,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2057
2250
|
makeWorkspace('timed-out-3'),
|
|
2058
2251
|
makeWorkspace('after-timeouts'),
|
|
2059
2252
|
];
|
|
2060
|
-
vi.mocked(
|
|
2253
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue(workspaces);
|
|
2061
2254
|
let finishCleanup;
|
|
2062
2255
|
const cleanupBarrier = new Promise((resolve) => {
|
|
2063
2256
|
finishCleanup = resolve;
|
|
@@ -2103,8 +2296,8 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2103
2296
|
makeWorkspace('batch-blocker-3'),
|
|
2104
2297
|
];
|
|
2105
2298
|
const directWorkspace = makeWorkspace('direct-target');
|
|
2106
|
-
vi.mocked(
|
|
2107
|
-
vi.mocked(
|
|
2299
|
+
vi.mocked(workspaceRatchetService.findCandidates).mockResolvedValue(batchWorkspaces);
|
|
2300
|
+
vi.mocked(workspaceRatchetService.findCandidateById).mockResolvedValue(directWorkspace);
|
|
2108
2301
|
let releaseBatch;
|
|
2109
2302
|
const batchBarrier = new Promise((resolve) => {
|
|
2110
2303
|
releaseBatch = resolve;
|
|
@@ -2138,7 +2331,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2138
2331
|
describe('decideRatchetAction edge cases', () => {
|
|
2139
2332
|
const callDecide = (context) => unsafeCoerce(ratchetService).decideRatchetAction(context);
|
|
2140
2333
|
const arrangeOtherWorkingSession = () => {
|
|
2141
|
-
vi.mocked(
|
|
2334
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([
|
|
2142
2335
|
{ id: 'other-session' },
|
|
2143
2336
|
]);
|
|
2144
2337
|
vi.mocked(mockSessionBridge.isSessionWorking).mockReturnValue(true);
|
|
@@ -2268,7 +2461,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2268
2461
|
expect(result).toEqual({ kind: 'none' });
|
|
2269
2462
|
});
|
|
2270
2463
|
it('settles a non-RUNNING session as COMPLETED when its status is not FAILED', async () => {
|
|
2271
|
-
vi.mocked(
|
|
2464
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
|
|
2272
2465
|
id: 'completed-session',
|
|
2273
2466
|
provider: 'CLAUDE',
|
|
2274
2467
|
status: SessionStatus.IDLE,
|
|
@@ -2278,10 +2471,10 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2278
2471
|
ratchetActiveSessionId: 'completed-session',
|
|
2279
2472
|
});
|
|
2280
2473
|
expect(result).toEqual({ kind: 'settled', outcome: 'COMPLETED' });
|
|
2281
|
-
expect(
|
|
2474
|
+
expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith('ws-3', 'completed-session', 'COMPLETED');
|
|
2282
2475
|
});
|
|
2283
2476
|
it('settles a FAILED session as DIED', async () => {
|
|
2284
|
-
vi.mocked(
|
|
2477
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
|
|
2285
2478
|
id: 'failed-session',
|
|
2286
2479
|
provider: 'CLAUDE',
|
|
2287
2480
|
status: SessionStatus.FAILED,
|
|
@@ -2291,10 +2484,10 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2291
2484
|
ratchetActiveSessionId: 'failed-session',
|
|
2292
2485
|
});
|
|
2293
2486
|
expect(result).toEqual({ kind: 'settled', outcome: 'DIED' });
|
|
2294
|
-
expect(
|
|
2487
|
+
expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith('ws-4', 'failed-session', 'DIED');
|
|
2295
2488
|
});
|
|
2296
2489
|
it('settles a provider-mismatched session as DIED and stops it', async () => {
|
|
2297
|
-
vi.mocked(
|
|
2490
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
|
|
2298
2491
|
id: 'codex-session',
|
|
2299
2492
|
provider: 'CODEX',
|
|
2300
2493
|
status: SessionStatus.RUNNING,
|
|
@@ -2307,11 +2500,11 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2307
2500
|
ratchetSessionProvider: 'WORKSPACE_DEFAULT',
|
|
2308
2501
|
});
|
|
2309
2502
|
expect(result).toEqual({ kind: 'settled', outcome: 'DIED' });
|
|
2310
|
-
expect(
|
|
2503
|
+
expect(mockWorkspaceBridge.recordSessionEnd).toHaveBeenCalledWith('ws-5', 'codex-session', 'DIED');
|
|
2311
2504
|
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('codex-session');
|
|
2312
2505
|
});
|
|
2313
2506
|
it('returns the active fixer when the session is working', async () => {
|
|
2314
|
-
vi.mocked(
|
|
2507
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue({
|
|
2315
2508
|
id: 'working-session',
|
|
2316
2509
|
provider: 'CLAUDE',
|
|
2317
2510
|
status: SessionStatus.RUNNING,
|
|
@@ -2326,28 +2519,111 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2326
2519
|
kind: 'active',
|
|
2327
2520
|
action: { type: 'FIXER_ACTIVE', sessionId: 'working-session' },
|
|
2328
2521
|
});
|
|
2329
|
-
expect(
|
|
2522
|
+
expect(mockWorkspaceBridge.recordSessionEnd).not.toHaveBeenCalled();
|
|
2330
2523
|
});
|
|
2331
2524
|
it('does not settle or stop a fixer after cancellation during session lookup', async () => {
|
|
2332
2525
|
const controller = new AbortController();
|
|
2333
2526
|
const timeoutError = new Error('Workspace check timed out');
|
|
2334
2527
|
let finishLookup;
|
|
2335
|
-
vi.mocked(
|
|
2528
|
+
vi.mocked(mockSessionBridge.findSessionById).mockImplementation(() => new Promise((resolve) => {
|
|
2336
2529
|
finishLookup = resolve;
|
|
2337
2530
|
}));
|
|
2338
2531
|
const check = unsafeCoerce(ratchetService).checkActiveFixerSession({
|
|
2339
2532
|
id: 'ws-cancelled-active-check',
|
|
2340
2533
|
ratchetActiveSessionId: 'session-1',
|
|
2341
2534
|
}, controller.signal);
|
|
2342
|
-
await vi.waitFor(() => expect(
|
|
2535
|
+
await vi.waitFor(() => expect(mockSessionBridge.findSessionById).toHaveBeenCalled());
|
|
2343
2536
|
controller.abort(timeoutError);
|
|
2344
2537
|
finishLookup(null);
|
|
2345
2538
|
await expect(check).rejects.toBe(timeoutError);
|
|
2346
|
-
expect(
|
|
2539
|
+
expect(mockWorkspaceBridge.recordSessionEnd).not.toHaveBeenCalled();
|
|
2347
2540
|
expect(mockSessionBridge.stopSession).not.toHaveBeenCalled();
|
|
2348
2541
|
});
|
|
2542
|
+
it('publishes a successful fallback settlement before observing post-write cancellation', async () => {
|
|
2543
|
+
const controller = new AbortController();
|
|
2544
|
+
const timeoutError = new Error('Workspace check timed out');
|
|
2545
|
+
vi.mocked(mockSessionBridge.findSessionById).mockResolvedValue(null);
|
|
2546
|
+
vi.mocked(mockWorkspaceBridge.recordSessionEnd).mockImplementation(() => {
|
|
2547
|
+
controller.abort(timeoutError);
|
|
2548
|
+
return Promise.resolve(true);
|
|
2549
|
+
});
|
|
2550
|
+
const events = [];
|
|
2551
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
2552
|
+
events.push(event);
|
|
2553
|
+
});
|
|
2554
|
+
const check = unsafeCoerce(ratchetService).checkActiveFixerSession({
|
|
2555
|
+
id: 'ws-cancelled-after-settlement',
|
|
2556
|
+
ratchetActiveSessionId: 'session-1',
|
|
2557
|
+
ratchetDispatchRetryCount: 2,
|
|
2558
|
+
}, controller.signal);
|
|
2559
|
+
await expect(check).rejects.toBe(timeoutError);
|
|
2560
|
+
expect(events).toEqual([{ workspaceId: 'ws-cancelled-after-settlement' }]);
|
|
2561
|
+
});
|
|
2349
2562
|
});
|
|
2350
2563
|
describe('triggerFixer error handling', () => {
|
|
2564
|
+
it('commits the workspace check as soon as the fixer session starts', async () => {
|
|
2565
|
+
const commitSideEffects = vi.fn();
|
|
2566
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockImplementation(async (input) => {
|
|
2567
|
+
await input.afterStart?.({ sessionId: 'started-session', prompt: 'prompt' });
|
|
2568
|
+
return {
|
|
2569
|
+
status: 'started',
|
|
2570
|
+
sessionId: 'started-session',
|
|
2571
|
+
promptSent: true,
|
|
2572
|
+
};
|
|
2573
|
+
});
|
|
2574
|
+
const result = await unsafeCoerce(ratchetService).triggerFixer({
|
|
2575
|
+
id: 'ws-started-dispatch',
|
|
2576
|
+
prUrl: 'https://github.com/example/repo/pull/20',
|
|
2577
|
+
}, {
|
|
2578
|
+
ciStatus: CIStatus.FAILURE,
|
|
2579
|
+
snapshotKey: 'failed:20',
|
|
2580
|
+
prNumber: 20,
|
|
2581
|
+
reviewComments: [],
|
|
2582
|
+
hasMergeConflict: false,
|
|
2583
|
+
}, 0, new AbortController().signal, commitSideEffects);
|
|
2584
|
+
expect(result).toMatchObject({
|
|
2585
|
+
type: 'TRIGGERED_FIXER',
|
|
2586
|
+
sessionId: 'started-session',
|
|
2587
|
+
});
|
|
2588
|
+
expect(commitSideEffects).toHaveBeenCalledTimes(2);
|
|
2589
|
+
});
|
|
2590
|
+
it('cleans up a fixer when cancellation races with session startup', async () => {
|
|
2591
|
+
const controller = new AbortController();
|
|
2592
|
+
const timeoutError = new Error('Workspace check timed out');
|
|
2593
|
+
const commitSideEffects = vi.fn();
|
|
2594
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockImplementation(async (input) => {
|
|
2595
|
+
controller.abort(timeoutError);
|
|
2596
|
+
try {
|
|
2597
|
+
await input.afterStart?.({ sessionId: 'cancelled-startup-session', prompt: 'prompt' });
|
|
2598
|
+
return {
|
|
2599
|
+
status: 'started',
|
|
2600
|
+
sessionId: 'cancelled-startup-session',
|
|
2601
|
+
promptSent: true,
|
|
2602
|
+
};
|
|
2603
|
+
}
|
|
2604
|
+
catch (error) {
|
|
2605
|
+
return {
|
|
2606
|
+
status: 'error',
|
|
2607
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2608
|
+
};
|
|
2609
|
+
}
|
|
2610
|
+
});
|
|
2611
|
+
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
2612
|
+
const trigger = unsafeCoerce(ratchetService).triggerFixer({
|
|
2613
|
+
id: 'ws-cancelled-startup',
|
|
2614
|
+
prUrl: 'https://github.com/example/repo/pull/20',
|
|
2615
|
+
}, {
|
|
2616
|
+
ciStatus: CIStatus.FAILURE,
|
|
2617
|
+
snapshotKey: 'failed:20',
|
|
2618
|
+
prNumber: 20,
|
|
2619
|
+
reviewComments: [],
|
|
2620
|
+
hasMergeConflict: false,
|
|
2621
|
+
}, 0, controller.signal, commitSideEffects);
|
|
2622
|
+
await expect(trigger).rejects.toBe(timeoutError);
|
|
2623
|
+
expect(commitSideEffects).toHaveBeenCalledTimes(1);
|
|
2624
|
+
expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalledWith('ws-cancelled-startup', 'cancelled-startup-session', 'COMPLETED');
|
|
2625
|
+
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('cancelled-startup-session');
|
|
2626
|
+
});
|
|
2351
2627
|
it('does not clean up a fixer after its dispatch record is persisted', async () => {
|
|
2352
2628
|
const controller = new AbortController();
|
|
2353
2629
|
const timeoutError = new Error('Workspace check timed out');
|
|
@@ -2357,11 +2633,15 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2357
2633
|
sessionId: 'cancelled-session',
|
|
2358
2634
|
promptSent: true,
|
|
2359
2635
|
});
|
|
2360
|
-
vi.mocked(
|
|
2636
|
+
vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockImplementation(() => new Promise((resolve) => {
|
|
2361
2637
|
finishRecord = resolve;
|
|
2362
2638
|
}));
|
|
2363
2639
|
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
2364
2640
|
const commitSideEffects = vi.fn();
|
|
2641
|
+
const events = [];
|
|
2642
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
2643
|
+
events.push(event);
|
|
2644
|
+
});
|
|
2365
2645
|
const trigger = unsafeCoerce(ratchetService).triggerFixer({
|
|
2366
2646
|
id: 'ws-cancelled-dispatch',
|
|
2367
2647
|
prUrl: 'https://github.com/example/repo/pull/20',
|
|
@@ -2372,22 +2652,134 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2372
2652
|
reviewComments: [],
|
|
2373
2653
|
hasMergeConflict: false,
|
|
2374
2654
|
}, 0, controller.signal, commitSideEffects);
|
|
2375
|
-
await vi.waitFor(() => expect(
|
|
2655
|
+
await vi.waitFor(() => expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalled());
|
|
2376
2656
|
controller.abort(timeoutError);
|
|
2377
2657
|
finishRecord(true);
|
|
2378
2658
|
await expect(trigger).rejects.toBe(timeoutError);
|
|
2379
2659
|
expect(commitSideEffects).toHaveBeenCalledTimes(1);
|
|
2380
|
-
expect(
|
|
2660
|
+
expect(workspaceRatchetService.recordSessionEnd).not.toHaveBeenCalled();
|
|
2661
|
+
expect(mockSessionBridge.stopSession).not.toHaveBeenCalled();
|
|
2662
|
+
expect(events).toEqual([{ workspaceId: 'ws-cancelled-dispatch' }]);
|
|
2663
|
+
});
|
|
2664
|
+
it('persists and commits a dispatch while prompt completion is pending', async () => {
|
|
2665
|
+
let finishPrompt;
|
|
2666
|
+
const promptCompletion = new Promise((resolve) => {
|
|
2667
|
+
finishPrompt = resolve;
|
|
2668
|
+
});
|
|
2669
|
+
let finishRecord;
|
|
2670
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2671
|
+
status: 'started',
|
|
2672
|
+
sessionId: 'pending-prompt-session',
|
|
2673
|
+
promptSent: true,
|
|
2674
|
+
promptCompletion,
|
|
2675
|
+
});
|
|
2676
|
+
vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockImplementation(() => new Promise((resolve) => {
|
|
2677
|
+
finishRecord = resolve;
|
|
2678
|
+
}));
|
|
2679
|
+
const commitSideEffects = vi.fn();
|
|
2680
|
+
const trigger = unsafeCoerce(ratchetService).triggerFixer({
|
|
2681
|
+
id: 'ws-pending-prompt',
|
|
2682
|
+
prUrl: 'https://github.com/example/repo/pull/20',
|
|
2683
|
+
}, {
|
|
2684
|
+
ciStatus: CIStatus.FAILURE,
|
|
2685
|
+
snapshotKey: 'failed:20',
|
|
2686
|
+
prNumber: 20,
|
|
2687
|
+
reviewComments: [],
|
|
2688
|
+
hasMergeConflict: false,
|
|
2689
|
+
}, 0, new AbortController().signal, commitSideEffects);
|
|
2690
|
+
await vi.waitFor(() => expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalled());
|
|
2691
|
+
expect(commitSideEffects).toHaveBeenCalledTimes(1);
|
|
2692
|
+
finishRecord(true);
|
|
2693
|
+
await expect(trigger).resolves.toMatchObject({ type: 'TRIGGERED_FIXER' });
|
|
2694
|
+
expect(commitSideEffects).toHaveBeenCalledTimes(1);
|
|
2695
|
+
finishPrompt(true);
|
|
2696
|
+
await promptCompletion;
|
|
2697
|
+
});
|
|
2698
|
+
it('settles a persisted dispatch as died when prompt completion fails', async () => {
|
|
2699
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2700
|
+
status: 'started',
|
|
2701
|
+
sessionId: 'failed-prompt-session',
|
|
2702
|
+
promptSent: true,
|
|
2703
|
+
promptCompletion: Promise.resolve(false),
|
|
2704
|
+
});
|
|
2705
|
+
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
2706
|
+
const result = await unsafeCoerce(ratchetService).triggerFixer({
|
|
2707
|
+
id: 'ws-failed-prompt',
|
|
2708
|
+
prUrl: 'https://github.com/example/repo/pull/20',
|
|
2709
|
+
}, {
|
|
2710
|
+
ciStatus: CIStatus.FAILURE,
|
|
2711
|
+
snapshotKey: 'failed:20',
|
|
2712
|
+
prNumber: 20,
|
|
2713
|
+
reviewComments: [],
|
|
2714
|
+
hasMergeConflict: false,
|
|
2715
|
+
}, 0);
|
|
2716
|
+
expect(result).toMatchObject({ type: 'TRIGGERED_FIXER' });
|
|
2717
|
+
await vi.waitFor(() => expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalledWith('ws-failed-prompt', 'failed-prompt-session', 'DIED'));
|
|
2718
|
+
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('failed-prompt-session');
|
|
2719
|
+
});
|
|
2720
|
+
it('does not stop a newer active session when an old prompt completion fails', async () => {
|
|
2721
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2722
|
+
status: 'started',
|
|
2723
|
+
sessionId: 'stale-prompt-session',
|
|
2724
|
+
promptSent: true,
|
|
2725
|
+
promptCompletion: Promise.resolve(false),
|
|
2726
|
+
});
|
|
2727
|
+
vi.mocked(workspaceRatchetService.recordSessionEnd).mockResolvedValue(false);
|
|
2728
|
+
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
2729
|
+
await unsafeCoerce(ratchetService).triggerFixer({
|
|
2730
|
+
id: 'ws-replaced-prompt',
|
|
2731
|
+
prUrl: 'https://github.com/example/repo/pull/20',
|
|
2732
|
+
}, {
|
|
2733
|
+
ciStatus: CIStatus.FAILURE,
|
|
2734
|
+
snapshotKey: 'failed:20',
|
|
2735
|
+
prNumber: 20,
|
|
2736
|
+
reviewComments: [],
|
|
2737
|
+
hasMergeConflict: false,
|
|
2738
|
+
}, 0);
|
|
2739
|
+
await vi.waitFor(() => expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalled());
|
|
2381
2740
|
expect(mockSessionBridge.stopSession).not.toHaveBeenCalled();
|
|
2382
2741
|
});
|
|
2742
|
+
it('cleans up a fixer through prompt failure after its dispatch record is persisted', async () => {
|
|
2743
|
+
const controller = new AbortController();
|
|
2744
|
+
const timeoutError = new Error('Workspace check timed out');
|
|
2745
|
+
let finishRecord;
|
|
2746
|
+
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2747
|
+
status: 'started',
|
|
2748
|
+
sessionId: 'cancelled-session',
|
|
2749
|
+
promptSent: true,
|
|
2750
|
+
promptCompletion: Promise.resolve(false),
|
|
2751
|
+
});
|
|
2752
|
+
vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockImplementation(() => new Promise((resolve) => {
|
|
2753
|
+
finishRecord = resolve;
|
|
2754
|
+
}));
|
|
2755
|
+
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
2756
|
+
const commitSideEffects = vi.fn();
|
|
2757
|
+
const trigger = unsafeCoerce(ratchetService).triggerFixer({
|
|
2758
|
+
id: 'ws-cancelled-dispatch',
|
|
2759
|
+
prUrl: 'https://github.com/example/repo/pull/20',
|
|
2760
|
+
}, {
|
|
2761
|
+
ciStatus: CIStatus.FAILURE,
|
|
2762
|
+
snapshotKey: 'failed:20',
|
|
2763
|
+
prNumber: 20,
|
|
2764
|
+
reviewComments: [],
|
|
2765
|
+
hasMergeConflict: false,
|
|
2766
|
+
}, 0, controller.signal, commitSideEffects);
|
|
2767
|
+
await vi.waitFor(() => expect(workspaceRatchetService.recordDispatchIfEnabled).toHaveBeenCalled());
|
|
2768
|
+
controller.abort(timeoutError);
|
|
2769
|
+
finishRecord(true);
|
|
2770
|
+
await expect(trigger).rejects.toBe(timeoutError);
|
|
2771
|
+
expect(commitSideEffects).toHaveBeenCalledTimes(1);
|
|
2772
|
+
await vi.waitFor(() => expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalledWith('ws-cancelled-dispatch', 'cancelled-session', 'DIED'));
|
|
2773
|
+
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('cancelled-session');
|
|
2774
|
+
});
|
|
2383
2775
|
it('cleans up a started fixer when dispatch persistence fails', async () => {
|
|
2384
2776
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2385
2777
|
status: 'started',
|
|
2386
2778
|
sessionId: 'unrecorded-session',
|
|
2387
2779
|
promptSent: true,
|
|
2388
2780
|
});
|
|
2389
|
-
vi.mocked(
|
|
2390
|
-
vi.mocked(
|
|
2781
|
+
vi.mocked(workspaceRatchetService.recordDispatchIfEnabled).mockRejectedValue(new Error('dispatch record write failed'));
|
|
2782
|
+
vi.mocked(workspaceRatchetService.recordSessionEnd).mockRejectedValue(new Error('dispatch cleanup write failed'));
|
|
2391
2783
|
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
2392
2784
|
const commitSideEffects = vi.fn();
|
|
2393
2785
|
const result = await unsafeCoerce(ratchetService).triggerFixer({
|
|
@@ -2402,7 +2794,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2402
2794
|
}, 0, new AbortController().signal, commitSideEffects);
|
|
2403
2795
|
expect(result).toMatchObject({ type: 'ERROR', error: 'dispatch record write failed' });
|
|
2404
2796
|
expect(commitSideEffects).toHaveBeenCalledTimes(1);
|
|
2405
|
-
expect(
|
|
2797
|
+
expect(workspaceRatchetService.recordSessionEnd).toHaveBeenCalledWith('ws-unrecorded-dispatch', 'unrecorded-session', 'COMPLETED');
|
|
2406
2798
|
expect(mockSessionBridge.stopSession).toHaveBeenCalledWith('unrecorded-session');
|
|
2407
2799
|
});
|
|
2408
2800
|
it('handles acquireAndDispatch throwing an error', async () => {
|
|
@@ -2439,13 +2831,16 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2439
2831
|
ratchetLastCiRunId: null,
|
|
2440
2832
|
prReviewLastCheckedAt: null,
|
|
2441
2833
|
ratchetDispatchOutcome: null,
|
|
2442
|
-
ratchetDispatchRetryCount:
|
|
2834
|
+
ratchetDispatchRetryCount: 2,
|
|
2443
2835
|
};
|
|
2444
2836
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2445
2837
|
status: 'already_active',
|
|
2446
2838
|
sessionId: 'existing-session',
|
|
2447
2839
|
});
|
|
2448
|
-
|
|
2840
|
+
const events = [];
|
|
2841
|
+
ratchetService.on(RATCHET_DISPATCH_CHANGED, (event) => {
|
|
2842
|
+
events.push(event);
|
|
2843
|
+
});
|
|
2449
2844
|
const result = await unsafeCoerce(ratchetService).triggerFixer(workspace, {
|
|
2450
2845
|
ciStatus: CIStatus.FAILURE,
|
|
2451
2846
|
prNumber: 21,
|
|
@@ -2454,8 +2849,9 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2454
2849
|
type: 'FIXER_ACTIVE',
|
|
2455
2850
|
sessionId: 'existing-session',
|
|
2456
2851
|
});
|
|
2457
|
-
expect(
|
|
2458
|
-
expect(
|
|
2852
|
+
expect(workspaceRatchetService.adoptActiveSessionIfEnabled).toHaveBeenCalledWith('ws-already-active', 'existing-session');
|
|
2853
|
+
expect(workspaceRatchetService.recordDispatchIfEnabled).not.toHaveBeenCalled();
|
|
2854
|
+
expect(events).toEqual([{ workspaceId: 'ws-already-active' }]);
|
|
2459
2855
|
});
|
|
2460
2856
|
it('stops already-active fixer when active-session recording loses disable race', async () => {
|
|
2461
2857
|
const workspace = {
|
|
@@ -2474,7 +2870,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2474
2870
|
status: 'already_active',
|
|
2475
2871
|
sessionId: 'existing-session',
|
|
2476
2872
|
});
|
|
2477
|
-
vi.mocked(
|
|
2873
|
+
vi.mocked(workspaceRatchetService.adoptActiveSessionIfEnabled).mockResolvedValue(false);
|
|
2478
2874
|
vi.mocked(mockSessionBridge.isSessionRunning).mockReturnValue(true);
|
|
2479
2875
|
const result = await unsafeCoerce(ratchetService).triggerFixer(workspace, {
|
|
2480
2876
|
ciStatus: CIStatus.FAILURE,
|
|
@@ -2518,12 +2914,13 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2518
2914
|
ratchetService.removeAllListeners();
|
|
2519
2915
|
});
|
|
2520
2916
|
it('emits ratchet_toggled when enabling workspace ratcheting', async () => {
|
|
2521
|
-
vi.mocked(
|
|
2917
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
2522
2918
|
id: 'ws-enable',
|
|
2523
2919
|
ratchetState: RatchetState.CI_FAILED,
|
|
2524
2920
|
ratchetActiveSessionId: null,
|
|
2921
|
+
ratchetDispatchOutcome: 'DIED',
|
|
2922
|
+
ratchetDispatchRetryCount: 2,
|
|
2525
2923
|
});
|
|
2526
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
2527
2924
|
const toggledEvents = [];
|
|
2528
2925
|
const stateEvents = [];
|
|
2529
2926
|
ratchetService.on(RATCHET_TOGGLED, (event) => {
|
|
@@ -2533,7 +2930,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2533
2930
|
stateEvents.push(event);
|
|
2534
2931
|
});
|
|
2535
2932
|
await ratchetService.setWorkspaceRatcheting('ws-enable', true);
|
|
2536
|
-
expect(
|
|
2933
|
+
expect(workspaceRatchetService.enable).toHaveBeenCalledWith('ws-enable');
|
|
2537
2934
|
expect(toggledEvents).toEqual([
|
|
2538
2935
|
{
|
|
2539
2936
|
workspaceId: 'ws-enable',
|
|
@@ -2544,12 +2941,11 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2544
2941
|
expect(stateEvents).toHaveLength(0);
|
|
2545
2942
|
});
|
|
2546
2943
|
it('emits ratchet_toggled and ratchet_state_changed when disabling non-idle workspace', async () => {
|
|
2547
|
-
vi.mocked(
|
|
2944
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
2548
2945
|
id: 'ws-disable',
|
|
2549
2946
|
ratchetState: RatchetState.CI_RUNNING,
|
|
2550
2947
|
ratchetActiveSessionId: null,
|
|
2551
2948
|
});
|
|
2552
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
2553
2949
|
const toggledEvents = [];
|
|
2554
2950
|
const stateEvents = [];
|
|
2555
2951
|
ratchetService.on(RATCHET_TOGGLED, (event) => {
|
|
@@ -2559,14 +2955,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2559
2955
|
stateEvents.push(event);
|
|
2560
2956
|
});
|
|
2561
2957
|
await ratchetService.setWorkspaceRatcheting('ws-disable', false);
|
|
2562
|
-
expect(
|
|
2563
|
-
ratchetEnabled: false,
|
|
2564
|
-
ratchetState: RatchetState.IDLE,
|
|
2565
|
-
ratchetActiveSessionId: null,
|
|
2566
|
-
ratchetLastCiRunId: null,
|
|
2567
|
-
ratchetDispatchOutcome: null,
|
|
2568
|
-
ratchetDispatchRetryCount: 0,
|
|
2569
|
-
});
|
|
2958
|
+
expect(workspaceRatchetService.disable).toHaveBeenCalledWith('ws-disable');
|
|
2570
2959
|
expect(stateEvents).toEqual([
|
|
2571
2960
|
{
|
|
2572
2961
|
workspaceId: 'ws-disable',
|
|
@@ -2583,12 +2972,11 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2583
2972
|
]);
|
|
2584
2973
|
});
|
|
2585
2974
|
it('stops ratchet workflow sessions found after disabling workspace', async () => {
|
|
2586
|
-
vi.mocked(
|
|
2975
|
+
vi.mocked(workspaceDataService.findById).mockResolvedValue({
|
|
2587
2976
|
id: 'ws-disable-raced-session',
|
|
2588
2977
|
ratchetState: RatchetState.CI_RUNNING,
|
|
2589
2978
|
ratchetActiveSessionId: null,
|
|
2590
2979
|
});
|
|
2591
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
2592
2980
|
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([
|
|
2593
2981
|
{
|
|
2594
2982
|
id: 'raced-ratchet-session',
|
|
@@ -2625,7 +3013,6 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2625
3013
|
ratchetDispatchOutcome: null,
|
|
2626
3014
|
ratchetDispatchRetryCount: 0,
|
|
2627
3015
|
};
|
|
2628
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
2629
3016
|
const events = [];
|
|
2630
3017
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
2631
3018
|
events.push(event);
|
|
@@ -2651,7 +3038,6 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2651
3038
|
ratchetDispatchOutcome: null,
|
|
2652
3039
|
ratchetDispatchRetryCount: 0,
|
|
2653
3040
|
};
|
|
2654
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
2655
3041
|
const events = [];
|
|
2656
3042
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
2657
3043
|
events.push(event);
|
|
@@ -2681,8 +3067,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2681
3067
|
prState: 'OPEN',
|
|
2682
3068
|
prNumber: 32,
|
|
2683
3069
|
});
|
|
2684
|
-
vi.mocked(
|
|
2685
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
3070
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
2686
3071
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2687
3072
|
status: 'started',
|
|
2688
3073
|
sessionId: 'ratchet-session-32',
|
|
@@ -2723,8 +3108,7 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2723
3108
|
prState: 'OPEN',
|
|
2724
3109
|
prNumber: 33,
|
|
2725
3110
|
});
|
|
2726
|
-
vi.mocked(
|
|
2727
|
-
vi.mocked(agentSessionAccessor.findByWorkspaceId).mockResolvedValue([]);
|
|
3111
|
+
vi.mocked(mockSessionBridge.findSessionsByWorkspaceId).mockResolvedValue([]);
|
|
2728
3112
|
vi.mocked(fixerSessionService.acquireAndDispatch).mockResolvedValue({
|
|
2729
3113
|
status: 'started',
|
|
2730
3114
|
sessionId: 'ratchet-session-33',
|
|
@@ -2751,7 +3135,6 @@ describe('ratchet service (state-change + idle dispatch)', () => {
|
|
|
2751
3135
|
ratchetDispatchRetryCount: 0,
|
|
2752
3136
|
};
|
|
2753
3137
|
vi.spyOn(unsafeCoerce(ratchetService), 'fetchPRState').mockResolvedValue(null);
|
|
2754
|
-
vi.mocked(workspaceAccessor.update).mockResolvedValue({});
|
|
2755
3138
|
const events = [];
|
|
2756
3139
|
ratchetService.on(RATCHET_STATE_CHANGED, (event) => {
|
|
2757
3140
|
events.push(event);
|