factory-factory 0.2.3 → 0.2.5
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 +2 -2
- package/dist/client/assets/{_basePickBy-ClLqD23W.js → _basePickBy-BXw54oMQ.js} +1 -1
- package/dist/client/assets/{_baseUniq-DVVSJ599.js → _baseUniq-_2-lN-JZ.js} +1 -1
- package/dist/client/assets/{arc-DCPJ-atk.js → arc-DaCKgXo4.js} +1 -1
- package/dist/client/assets/{architectureDiagram-VXUJARFQ-dvBXEdHJ.js → architectureDiagram-VXUJARFQ-D5dlDvyJ.js} +1 -1
- package/dist/client/assets/{blockDiagram-VD42YOAC-BnlsKN_S.js → blockDiagram-VD42YOAC-CEAiD2S_.js} +1 -1
- package/dist/client/assets/{c4Diagram-YG6GDRKO-AMG1QOcD.js → c4Diagram-YG6GDRKO-DTNRx2b5.js} +1 -1
- package/dist/client/assets/channel-BusoDFL5.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-CvbHsudf.js → chunk-4BX2VUAB-yvp0WNZ0.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CtFa9sig.js → chunk-55IACEB6-Cse3ExNd.js} +1 -1
- package/dist/client/assets/{chunk-B4BG7PRW-sjqCuFZK.js → chunk-B4BG7PRW-Bl2GpPLn.js} +1 -1
- package/dist/client/assets/{chunk-DI55MBZ5-vsqDRqHG.js → chunk-DI55MBZ5-CV5Cqkss.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-lEVbnFWf.js → chunk-FMBD7UC4-CP3yjlO6.js} +1 -1
- package/dist/client/assets/{chunk-QN33PNHL-laYvT_kS.js → chunk-QN33PNHL-DUdJaEPB.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-Cs-LwO3R.js → chunk-QZHKN3VN-DYTUnPIc.js} +1 -1
- package/dist/client/assets/{chunk-TZMSLE5B-GQQ1aq3v.js → chunk-TZMSLE5B-CtWiqR24.js} +1 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-C3RMRasv.js +1 -0
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-C3RMRasv.js +1 -0
- package/dist/client/assets/clone-D6B-nWvg.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-Y_FrS_Az.js → cose-bilkent-S5V4N54A-B67RdhOB.js} +1 -1
- package/dist/client/assets/{dagre-6UL2VRFP-DQIwKP-6.js → dagre-6UL2VRFP-D9u_oxJL.js} +1 -1
- package/dist/client/assets/{diagram-PSM6KHXK-jFQ4tsW4.js → diagram-PSM6KHXK-DOWfPnpa.js} +1 -1
- package/dist/client/assets/{diagram-QEK2KX5R-0kFBcfBt.js → diagram-QEK2KX5R-CqJwZbAA.js} +1 -1
- package/dist/client/assets/{diagram-S2PKOQOG-Cx_fwFHF.js → diagram-S2PKOQOG-D0ri9ztm.js} +1 -1
- package/dist/client/assets/{erDiagram-Q2GNP2WA-CUgHzWnq.js → erDiagram-Q2GNP2WA-0cRKPUY7.js} +1 -1
- package/dist/client/assets/{flowDiagram-NV44I4VS-DBPSyGKN.js → flowDiagram-NV44I4VS-Cj_5-ww1.js} +1 -1
- package/dist/client/assets/{ganttDiagram-JELNMOA3-BPAxxsuh.js → ganttDiagram-JELNMOA3-Cwm2arni.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-NY62KEGX-BHLuayx7.js → gitGraphDiagram-NY62KEGX-DKyLuO26.js} +1 -1
- package/dist/client/assets/{graph-hSnQ7U0p.js → graph-BhRkLhV1.js} +1 -1
- package/dist/client/assets/{index-CwTQdVJd.js → index-1HR_eYGL.js} +220 -182
- package/dist/client/assets/index-DHENAn70.css +1 -0
- package/dist/client/assets/{infoDiagram-WHAUD3N6-DqA4KMDO.js → infoDiagram-WHAUD3N6-DuzPbELj.js} +1 -1
- package/dist/client/assets/{journeyDiagram-XKPGCS4Q-DlVpIfsm.js → journeyDiagram-XKPGCS4Q-BfearpNr.js} +1 -1
- package/dist/client/assets/{kanban-definition-3W4ZIXB7-Bn7zJ_Qs.js → kanban-definition-3W4ZIXB7-R5KMtAj4.js} +1 -1
- package/dist/client/assets/{layout-BgfjjiLB.js → layout-B-tL36G2.js} +1 -1
- package/dist/client/assets/{linear-pgYyXM7v.js → linear-CvIBiHN-.js} +1 -1
- package/dist/client/assets/{mindmap-definition-VGOIOE7T-CU2bFQ_O.js → mindmap-definition-VGOIOE7T-CHYN0wBz.js} +1 -1
- package/dist/client/assets/{pieDiagram-ADFJNKIX-CdkFaWPc.js → pieDiagram-ADFJNKIX-LkA8WwD-.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-AYHSOK5B-gp1mJ5Yc.js → quadrantDiagram-AYHSOK5B-B5s8Qc9j.js} +1 -1
- package/dist/client/assets/{requirementDiagram-UZGBJVZJ-BO59auEv.js → requirementDiagram-UZGBJVZJ-BMLpjBJA.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-TZEHDZUN-BrZ8rlwL.js → sankeyDiagram-TZEHDZUN-BIj9RGlp.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WL72ISMW-LojphsDR.js → sequenceDiagram-WL72ISMW-uGM-Jh_O.js} +1 -1
- package/dist/client/assets/{stateDiagram-FKZM4ZOC-8bPGJ9iG.js → stateDiagram-FKZM4ZOC-CQQhnUok.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BUJPEM7D.js +1 -0
- package/dist/client/assets/{terminal-instance-YWv2YE4B.js → terminal-instance-DpK3PfW4.js} +1 -1
- package/dist/client/assets/{timeline-definition-IT6M3QCI-1mTwPI08.js → timeline-definition-IT6M3QCI-BusXMYfI.js} +1 -1
- package/dist/client/assets/{treemap-KMMF4GRG-VwmVQuy1.js → treemap-KMMF4GRG-XF3-w8dz.js} +1 -1
- package/dist/client/assets/{xychartDiagram-PRI3JC2R-zPQ-EL8y.js → xychartDiagram-PRI3JC2R-DhKTXxb3.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/prisma/generated/enums.d.ts +0 -1
- package/dist/prisma/generated/enums.d.ts.map +1 -1
- package/dist/prisma/generated/enums.js +0 -1
- package/dist/prisma/generated/enums.js.map +1 -1
- package/dist/prisma/generated/internal/class.js +2 -2
- package/dist/prisma/generated/internal/class.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.d.ts +0 -1
- package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.js +0 -1
- package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +0 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +0 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/prisma/generated/models/UserSettings.d.ts +1 -29
- package/dist/prisma/generated/models/UserSettings.d.ts.map +1 -1
- package/dist/prompts/ratchet/dispatch.md +31 -0
- package/dist/prompts/workflows/ratchet.md +22 -36
- package/dist/src/backend/app-context.d.ts +4 -0
- package/dist/src/backend/app-context.d.ts.map +1 -1
- package/dist/src/backend/app-context.js +4 -0
- package/dist/src/backend/app-context.js.map +1 -1
- package/dist/src/backend/claude/protocol.d.ts +3 -0
- package/dist/src/backend/claude/protocol.d.ts.map +1 -1
- package/dist/src/backend/claude/protocol.js +63 -10
- package/dist/src/backend/claude/protocol.js.map +1 -1
- package/dist/src/backend/claude/protocol.test.js +188 -0
- package/dist/src/backend/claude/protocol.test.js.map +1 -1
- package/dist/src/backend/claude/registry.d.ts.map +1 -1
- package/dist/src/backend/claude/registry.js +12 -1
- package/dist/src/backend/claude/registry.js.map +1 -1
- package/dist/src/backend/claude/session.d.ts.map +1 -1
- package/dist/src/backend/claude/session.js +40 -6
- package/dist/src/backend/claude/session.js.map +1 -1
- package/dist/src/backend/claude/session.test.js +46 -0
- package/dist/src/backend/claude/session.test.js.map +1 -1
- package/dist/src/backend/claude/types.d.ts +28 -3
- package/dist/src/backend/claude/types.d.ts.map +1 -1
- package/dist/src/backend/claude/types.js +28 -0
- package/dist/src/backend/claude/types.js.map +1 -1
- package/dist/src/backend/interceptors/pr-detection.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/pr-detection.interceptor.js +19 -23
- package/dist/src/backend/interceptors/pr-detection.interceptor.js.map +1 -1
- package/dist/src/backend/prompts/markdown-loader.d.ts +22 -0
- package/dist/src/backend/prompts/markdown-loader.d.ts.map +1 -0
- package/dist/src/backend/prompts/markdown-loader.js +77 -0
- package/dist/src/backend/prompts/markdown-loader.js.map +1 -0
- package/dist/src/backend/prompts/markdown-loader.test.d.ts +2 -0
- package/dist/src/backend/prompts/markdown-loader.test.d.ts.map +1 -0
- package/dist/src/backend/prompts/markdown-loader.test.js +190 -0
- package/dist/src/backend/prompts/markdown-loader.test.js.map +1 -0
- package/dist/src/backend/prompts/quick-actions.d.ts.map +1 -1
- package/dist/src/backend/prompts/quick-actions.js +34 -92
- package/dist/src/backend/prompts/quick-actions.js.map +1 -1
- package/dist/src/backend/prompts/ratchet-dispatch.d.ts +3 -0
- package/dist/src/backend/prompts/ratchet-dispatch.d.ts.map +1 -0
- package/dist/src/backend/prompts/ratchet-dispatch.js +53 -0
- package/dist/src/backend/prompts/ratchet-dispatch.js.map +1 -0
- package/dist/src/backend/prompts/ratchet-dispatch.test.d.ts +2 -0
- package/dist/src/backend/prompts/ratchet-dispatch.test.d.ts.map +1 -0
- package/dist/src/backend/prompts/ratchet-dispatch.test.js +34 -0
- package/dist/src/backend/prompts/ratchet-dispatch.test.js.map +1 -0
- package/dist/src/backend/prompts/workflows.d.ts.map +1 -1
- package/dist/src/backend/prompts/workflows.js +23 -76
- package/dist/src/backend/prompts/workflows.js.map +1 -1
- package/dist/src/backend/resource_accessors/user-settings.accessor.d.ts +0 -1
- package/dist/src/backend/resource_accessors/user-settings.accessor.d.ts.map +1 -1
- package/dist/src/backend/resource_accessors/user-settings.accessor.js.map +1 -1
- package/dist/src/backend/resource_accessors/workspace.accessor.d.ts +4 -3
- package/dist/src/backend/resource_accessors/workspace.accessor.d.ts.map +1 -1
- package/dist/src/backend/resource_accessors/workspace.accessor.js +4 -2
- package/dist/src/backend/resource_accessors/workspace.accessor.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 +1 -30
- package/dist/src/backend/routers/websocket/chat.handler.js.map +1 -1
- package/dist/src/backend/services/chat-event-forwarder.service.d.ts.map +1 -1
- package/dist/src/backend/services/chat-event-forwarder.service.js +9 -13
- package/dist/src/backend/services/chat-event-forwarder.service.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.d.ts +14 -0
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.d.ts.map +1 -0
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.js +81 -0
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.js.map +1 -0
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.test.d.ts +2 -0
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.test.d.ts.map +1 -0
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.test.js +315 -0
- package/dist/src/backend/services/chat-message-handlers/attachment-processing.test.js.map +1 -0
- package/dist/src/backend/services/chat-message-handlers/handlers/get-history.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/get-history.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/get-history.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/get-queue.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/get-queue.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/get-queue.handler.js +7 -3
- package/dist/src/backend/services/chat-message-handlers/handlers/get-queue.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/handlers.test.js +156 -6
- package/dist/src/backend/services/chat-message-handlers/handlers/handlers.test.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/list-sessions.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/list-sessions.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/list-sessions.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/load-session.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/load-session.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/load-session.handler.js +41 -31
- package/dist/src/backend/services/chat-message-handlers/handlers/load-session.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/permission-response.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/permission-response.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/permission-response.handler.js +1 -2
- package/dist/src/backend/services/chat-message-handlers/handlers/permission-response.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/question-response.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/question-response.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/question-response.handler.js +1 -2
- package/dist/src/backend/services/chat-message-handlers/handlers/question-response.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/queue-message.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/queue-message.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/queue-message.handler.js +6 -7
- package/dist/src/backend/services/chat-message-handlers/handlers/queue-message.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/remove-queued-message.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/remove-queued-message.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/remove-queued-message.handler.js +1 -2
- package/dist/src/backend/services/chat-message-handlers/handlers/remove-queued-message.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/rewind-files.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/rewind-files.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/rewind-files.handler.js +8 -9
- package/dist/src/backend/services/chat-message-handlers/handlers/rewind-files.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/set-model.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/set-model.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/set-model.handler.js +4 -5
- package/dist/src/backend/services/chat-message-handlers/handlers/set-model.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/set-thinking-budget.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/set-thinking-budget.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/set-thinking-budget.handler.js +4 -5
- package/dist/src/backend/services/chat-message-handlers/handlers/set-thinking-budget.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/start.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/start.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/start.handler.js +4 -2
- package/dist/src/backend/services/chat-message-handlers/handlers/start.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/stop.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/stop.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/stop.handler.js +7 -2
- package/dist/src/backend/services/chat-message-handlers/handlers/stop.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/user-input.handler.d.ts +2 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/user-input.handler.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/handlers/user-input.handler.js +1 -2
- package/dist/src/backend/services/chat-message-handlers/handlers/user-input.handler.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/registry.d.ts +5 -1
- package/dist/src/backend/services/chat-message-handlers/registry.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers/registry.js.map +1 -1
- package/dist/src/backend/services/chat-message-handlers.service.d.ts +0 -2
- package/dist/src/backend/services/chat-message-handlers.service.d.ts.map +1 -1
- package/dist/src/backend/services/chat-message-handlers.service.js +6 -68
- package/dist/src/backend/services/chat-message-handlers.service.js.map +1 -1
- package/dist/src/backend/services/chat-transport-adapter.service.d.ts +2 -0
- package/dist/src/backend/services/chat-transport-adapter.service.d.ts.map +1 -1
- package/dist/src/backend/services/chat-transport-adapter.service.js +32 -1
- package/dist/src/backend/services/chat-transport-adapter.service.js.map +1 -1
- package/dist/src/backend/services/chat-transport-adapter.service.test.js +14 -0
- package/dist/src/backend/services/chat-transport-adapter.service.test.js.map +1 -1
- package/dist/src/backend/services/data-backup.service.d.ts +3 -144
- package/dist/src/backend/services/data-backup.service.d.ts.map +1 -1
- package/dist/src/backend/services/data-backup.service.js +119 -115
- package/dist/src/backend/services/data-backup.service.js.map +1 -1
- package/dist/src/backend/services/data-backup.service.test.d.ts +2 -0
- package/dist/src/backend/services/data-backup.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/data-backup.service.test.js +602 -0
- package/dist/src/backend/services/data-backup.service.test.js.map +1 -0
- package/dist/src/backend/services/file-lock.service.d.ts.map +1 -1
- package/dist/src/backend/services/file-lock.service.js +3 -5
- package/dist/src/backend/services/file-lock.service.js.map +1 -1
- package/dist/src/backend/services/file-lock.service.test.js +55 -0
- package/dist/src/backend/services/file-lock.service.test.js.map +1 -1
- package/dist/src/backend/services/github-cli.service.d.ts.map +1 -1
- package/dist/src/backend/services/github-cli.service.js +118 -19
- package/dist/src/backend/services/github-cli.service.js.map +1 -1
- package/dist/src/backend/services/github-cli.service.test.js +126 -0
- package/dist/src/backend/services/github-cli.service.test.js.map +1 -1
- package/dist/src/backend/services/index.d.ts +1 -0
- package/dist/src/backend/services/index.d.ts.map +1 -1
- package/dist/src/backend/services/index.js +1 -0
- package/dist/src/backend/services/index.js.map +1 -1
- package/dist/src/backend/services/message-state-machine.d.ts.map +1 -1
- package/dist/src/backend/services/message-state-machine.js +11 -5
- package/dist/src/backend/services/message-state-machine.js.map +1 -1
- package/dist/src/backend/services/message-state.service.d.ts +16 -18
- package/dist/src/backend/services/message-state.service.d.ts.map +1 -1
- package/dist/src/backend/services/message-state.service.js +8 -14
- package/dist/src/backend/services/message-state.service.js.map +1 -1
- package/dist/src/backend/services/message-state.service.test.js +36 -45
- package/dist/src/backend/services/message-state.service.test.js.map +1 -1
- package/dist/src/backend/services/pr-snapshot.service.d.ts +9 -1
- package/dist/src/backend/services/pr-snapshot.service.d.ts.map +1 -1
- package/dist/src/backend/services/pr-snapshot.service.js +53 -3
- package/dist/src/backend/services/pr-snapshot.service.js.map +1 -1
- package/dist/src/backend/services/pr-snapshot.service.test.js +102 -47
- package/dist/src/backend/services/pr-snapshot.service.test.js.map +1 -1
- package/dist/src/backend/services/ratchet.service.d.ts +14 -71
- package/dist/src/backend/services/ratchet.service.d.ts.map +1 -1
- package/dist/src/backend/services/ratchet.service.js +198 -439
- package/dist/src/backend/services/ratchet.service.js.map +1 -1
- package/dist/src/backend/services/ratchet.service.test.js +210 -358
- package/dist/src/backend/services/ratchet.service.test.js.map +1 -1
- package/dist/src/backend/services/run-script-state-machine.service.d.ts +27 -0
- package/dist/src/backend/services/run-script-state-machine.service.d.ts.map +1 -0
- package/dist/src/backend/services/run-script-state-machine.service.js +149 -0
- package/dist/src/backend/services/run-script-state-machine.service.js.map +1 -0
- package/dist/src/backend/services/run-script-state-machine.service.test.d.ts +2 -0
- package/dist/src/backend/services/run-script-state-machine.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/run-script-state-machine.service.test.js +453 -0
- package/dist/src/backend/services/run-script-state-machine.service.test.js.map +1 -0
- package/dist/src/backend/services/run-script.service.d.ts +0 -7
- package/dist/src/backend/services/run-script.service.d.ts.map +1 -1
- package/dist/src/backend/services/run-script.service.js +145 -76
- package/dist/src/backend/services/run-script.service.js.map +1 -1
- package/dist/src/backend/services/scheduler.service.d.ts.map +1 -1
- package/dist/src/backend/services/scheduler.service.js +16 -7
- package/dist/src/backend/services/scheduler.service.js.map +1 -1
- package/dist/src/backend/services/scheduler.service.test.js +41 -5
- package/dist/src/backend/services/scheduler.service.test.js.map +1 -1
- package/dist/src/backend/services/session-runtime-store.service.d.ts +38 -0
- package/dist/src/backend/services/session-runtime-store.service.d.ts.map +1 -0
- package/dist/src/backend/services/session-runtime-store.service.js +111 -0
- package/dist/src/backend/services/session-runtime-store.service.js.map +1 -0
- package/dist/src/backend/services/session-runtime-store.service.test.d.ts +2 -0
- package/dist/src/backend/services/session-runtime-store.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/session-runtime-store.service.test.js +15 -0
- package/dist/src/backend/services/session-runtime-store.service.test.js.map +1 -0
- package/dist/src/backend/services/session.repository.d.ts +2 -0
- package/dist/src/backend/services/session.repository.d.ts.map +1 -1
- package/dist/src/backend/services/session.repository.js +3 -0
- package/dist/src/backend/services/session.repository.js.map +1 -1
- package/dist/src/backend/services/session.service.d.ts +0 -1
- package/dist/src/backend/services/session.service.d.ts.map +1 -1
- package/dist/src/backend/services/session.service.js +18 -23
- package/dist/src/backend/services/session.service.js.map +1 -1
- package/dist/src/backend/services/session.service.test.js +210 -12
- package/dist/src/backend/services/session.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace-creation.service.test.js +0 -2
- package/dist/src/backend/services/workspace-creation.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace-flow-state.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace-flow-state.service.js +0 -1
- package/dist/src/backend/services/workspace-flow-state.service.js.map +1 -1
- package/dist/src/backend/services/workspace-query.service.d.ts +1 -0
- package/dist/src/backend/services/workspace-query.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace-query.service.js +8 -0
- package/dist/src/backend/services/workspace-query.service.js.map +1 -1
- package/dist/src/backend/services/worktree-lifecycle.service.d.ts.map +1 -1
- package/dist/src/backend/services/worktree-lifecycle.service.js +139 -19
- package/dist/src/backend/services/worktree-lifecycle.service.js.map +1 -1
- package/dist/src/backend/services/worktree-lifecycle.service.test.js +48 -1
- package/dist/src/backend/services/worktree-lifecycle.service.test.js.map +1 -1
- package/dist/src/backend/trpc/admin.trpc.d.ts +130 -7
- package/dist/src/backend/trpc/admin.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/admin.trpc.js +2 -1
- package/dist/src/backend/trpc/admin.trpc.js.map +1 -1
- package/dist/src/backend/trpc/github.trpc.d.ts +14 -0
- package/dist/src/backend/trpc/github.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/github.trpc.js +28 -0
- package/dist/src/backend/trpc/github.trpc.js.map +1 -1
- package/dist/src/backend/trpc/index.d.ts +149 -20
- package/dist/src/backend/trpc/index.d.ts.map +1 -1
- package/dist/src/backend/trpc/session.trpc.d.ts +3 -3
- package/dist/src/backend/trpc/user-settings.trpc.d.ts +0 -3
- package/dist/src/backend/trpc/user-settings.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/user-settings.trpc.js +0 -1
- package/dist/src/backend/trpc/user-settings.trpc.js.map +1 -1
- package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts +0 -7
- package/dist/src/backend/trpc/workspace/run-script.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace.trpc.d.ts +2 -7
- package/dist/src/backend/trpc/workspace.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/workspace.trpc.js +13 -1
- package/dist/src/backend/trpc/workspace.trpc.js.map +1 -1
- package/dist/src/shared/ci-status.d.ts +9 -0
- package/dist/src/shared/ci-status.d.ts.map +1 -0
- package/dist/src/shared/ci-status.js +44 -0
- package/dist/src/shared/ci-status.js.map +1 -0
- package/dist/src/shared/claude/index.d.ts +1 -0
- package/dist/src/shared/claude/index.d.ts.map +1 -1
- package/dist/src/shared/claude/index.js +1 -0
- package/dist/src/shared/claude/index.js.map +1 -1
- package/dist/src/shared/claude/protocol.d.ts +6 -3
- package/dist/src/shared/claude/protocol.d.ts.map +1 -1
- package/dist/src/shared/claude/protocol.js.map +1 -1
- package/dist/src/shared/schemas/export-data.schema.d.ts +865 -0
- package/dist/src/shared/schemas/export-data.schema.d.ts.map +1 -0
- package/dist/src/shared/schemas/export-data.schema.js +167 -0
- package/dist/src/shared/schemas/export-data.schema.js.map +1 -0
- package/dist/src/shared/schemas/persisted-stores.schema.d.ts +19 -0
- package/dist/src/shared/schemas/persisted-stores.schema.d.ts.map +1 -0
- package/dist/src/shared/schemas/persisted-stores.schema.js +17 -0
- package/dist/src/shared/schemas/persisted-stores.schema.js.map +1 -0
- package/dist/src/shared/session-runtime.d.ts +17 -0
- package/dist/src/shared/session-runtime.d.ts.map +1 -0
- package/dist/src/shared/session-runtime.js +9 -0
- package/dist/src/shared/session-runtime.js.map +1 -0
- package/dist/src/shared/websocket/chat-message.schema.d.ts +24 -11
- package/dist/src/shared/websocket/chat-message.schema.d.ts.map +1 -1
- package/dist/src/shared/websocket/chat-message.schema.js +4 -1
- package/dist/src/shared/websocket/chat-message.schema.js.map +1 -1
- package/dist/src/shared/websocket/index.d.ts +1 -1
- package/dist/src/shared/websocket/index.d.ts.map +1 -1
- package/dist/src/shared/websocket/index.js.map +1 -1
- package/dist/src/shared/workspace-sidebar-status.d.ts +20 -0
- package/dist/src/shared/workspace-sidebar-status.d.ts.map +1 -0
- package/dist/src/shared/workspace-sidebar-status.js +73 -0
- package/dist/src/shared/workspace-sidebar-status.js.map +1 -0
- package/dist/tsconfig.backend.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/prisma/migrations/20260206170000_remove_merge_conflict_state/migration.sql +7 -0
- package/prisma/migrations/20260206174726_remove_ratchet_auto_fix_conflicts/migration.sql +33 -0
- package/prisma/schema.prisma +0 -2
- package/prompts/ratchet/dispatch.md +31 -0
- package/prompts/workflows/ratchet.md +22 -36
- package/dist/client/assets/channel-DWeb1p1N.js +0 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-DkYgN_SG.js +0 -1
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-DkYgN_SG.js +0 -1
- package/dist/client/assets/clone-WKF0ejf5.js +0 -1
- package/dist/client/assets/index-DCpIgwSv.css +0 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BFf_HK07.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CIStatus, RatchetState, SessionStatus } from '../../../prisma/generated/client.js';
|
|
2
2
|
import pLimit from 'p-limit';
|
|
3
|
+
import { buildRatchetDispatchPrompt } from '../prompts/ratchet-dispatch.js';
|
|
3
4
|
import { claudeSessionAccessor } from '../resource_accessors/claude-session.accessor.js';
|
|
4
|
-
import { userSettingsAccessor } from '../resource_accessors/user-settings.accessor.js';
|
|
5
5
|
import { workspaceAccessor } from '../resource_accessors/workspace.accessor.js';
|
|
6
6
|
import { fixerSessionService } from './fixer-session.service.js';
|
|
7
7
|
import { githubCLIService } from './github-cli.service.js';
|
|
@@ -12,10 +12,12 @@ const logger = createLogger('ratchet');
|
|
|
12
12
|
const RATCHET_POLL_INTERVAL_MS = 60_000;
|
|
13
13
|
const MAX_CONCURRENT_CHECKS = 5;
|
|
14
14
|
const RATCHET_WORKFLOW = 'ratchet';
|
|
15
|
+
const AUTHENTICATED_USERNAME_CACHE_TTL_MS = 5 * 60_000;
|
|
15
16
|
class RatchetService {
|
|
16
17
|
isShuttingDown = false;
|
|
17
18
|
monitorLoop = null;
|
|
18
19
|
checkLimit = pLimit(MAX_CONCURRENT_CHECKS);
|
|
20
|
+
cachedAuthenticatedUsername = null;
|
|
19
21
|
start() {
|
|
20
22
|
if (this.monitorLoop) {
|
|
21
23
|
return;
|
|
@@ -53,22 +55,13 @@ class RatchetService {
|
|
|
53
55
|
if (this.isShuttingDown) {
|
|
54
56
|
return { checked: 0, stateChanges: 0, actionsTriggered: 0, results: [] };
|
|
55
57
|
}
|
|
56
|
-
const userSettings = await userSettingsAccessor.get();
|
|
57
|
-
const settings = {
|
|
58
|
-
autoFixCi: userSettings.ratchetAutoFixCi,
|
|
59
|
-
autoFixConflicts: userSettings.ratchetAutoFixConflicts,
|
|
60
|
-
autoFixReviews: userSettings.ratchetAutoFixReviews,
|
|
61
|
-
autoMerge: userSettings.ratchetAutoMerge,
|
|
62
|
-
allowedReviewers: userSettings.ratchetAllowedReviewers ?? [],
|
|
63
|
-
};
|
|
64
58
|
const workspaces = await workspaceAccessor.findWithPRsForRatchet();
|
|
65
59
|
if (workspaces.length === 0) {
|
|
66
60
|
return { checked: 0, stateChanges: 0, actionsTriggered: 0, results: [] };
|
|
67
61
|
}
|
|
68
|
-
|
|
69
|
-
const results = await Promise.all(workspaces.map((workspace) => this.checkLimit(() => this.processWorkspace(workspace, settings))));
|
|
62
|
+
const results = await Promise.all(workspaces.map((workspace) => this.checkLimit(() => this.processWorkspace(workspace))));
|
|
70
63
|
const stateChanges = results.filter((r) => r.previousState !== r.newState).length;
|
|
71
|
-
const actionsTriggered = results.filter((r) => r.action.type === 'TRIGGERED_FIXER'
|
|
64
|
+
const actionsTriggered = results.filter((r) => r.action.type === 'TRIGGERED_FIXER').length;
|
|
72
65
|
if (stateChanges > 0 || actionsTriggered > 0) {
|
|
73
66
|
logger.info('Ratchet check completed', {
|
|
74
67
|
checked: workspaces.length,
|
|
@@ -86,17 +79,9 @@ class RatchetService {
|
|
|
86
79
|
if (!workspace) {
|
|
87
80
|
return null;
|
|
88
81
|
}
|
|
89
|
-
|
|
90
|
-
const settings = {
|
|
91
|
-
autoFixCi: userSettings.ratchetAutoFixCi,
|
|
92
|
-
autoFixConflicts: userSettings.ratchetAutoFixConflicts,
|
|
93
|
-
autoFixReviews: userSettings.ratchetAutoFixReviews,
|
|
94
|
-
autoMerge: userSettings.ratchetAutoMerge,
|
|
95
|
-
allowedReviewers: userSettings.ratchetAllowedReviewers ?? [],
|
|
96
|
-
};
|
|
97
|
-
return this.processWorkspace(workspace, settings);
|
|
82
|
+
return this.processWorkspace(workspace);
|
|
98
83
|
}
|
|
99
|
-
async processWorkspace(workspace
|
|
84
|
+
async processWorkspace(workspace) {
|
|
100
85
|
if (this.isShuttingDown) {
|
|
101
86
|
return {
|
|
102
87
|
workspaceId: workspace.id,
|
|
@@ -106,7 +91,8 @@ class RatchetService {
|
|
|
106
91
|
};
|
|
107
92
|
}
|
|
108
93
|
try {
|
|
109
|
-
const
|
|
94
|
+
const authenticatedUsername = await this.getAuthenticatedUsernameCached();
|
|
95
|
+
const prStateInfo = await this.fetchPRState(workspace, authenticatedUsername);
|
|
110
96
|
if (!prStateInfo) {
|
|
111
97
|
return {
|
|
112
98
|
workspaceId: workspace.id,
|
|
@@ -115,37 +101,16 @@ class RatchetService {
|
|
|
115
101
|
action: { type: 'ERROR', error: 'Failed to fetch PR state' },
|
|
116
102
|
};
|
|
117
103
|
}
|
|
118
|
-
const newState = this.determineRatchetState(prStateInfo);
|
|
119
104
|
const previousState = workspace.ratchetState;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
from: previousState,
|
|
124
|
-
to: newState,
|
|
125
|
-
prNumber: prStateInfo.prNumber,
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
const latestWorkspace = await workspaceAccessor.findById(workspace.id);
|
|
129
|
-
const shouldTakeAction = latestWorkspace?.ratchetEnabled ?? workspace.ratchetEnabled;
|
|
130
|
-
const action = shouldTakeAction
|
|
131
|
-
? await this.executeRatchetAction(workspace, newState, prStateInfo, settings)
|
|
105
|
+
const newState = this.determineRatchetState(prStateInfo);
|
|
106
|
+
const action = workspace.ratchetEnabled
|
|
107
|
+
? await this.evaluateAndDispatch(workspace, prStateInfo)
|
|
132
108
|
: { type: 'DISABLED', reason: 'Workspace ratcheting disabled' };
|
|
133
|
-
|
|
134
|
-
const shouldRecordCiRunId = shouldTakeAction &&
|
|
135
|
-
prStateInfo.ciStatus === CIStatus.FAILURE &&
|
|
136
|
-
!!prStateInfo.ciRunId &&
|
|
137
|
-
(action.type === 'NOTIFIED_ACTIVE_FIXER' ||
|
|
138
|
-
(action.type === 'TRIGGERED_FIXER' && action.promptSent));
|
|
139
|
-
await workspaceAccessor.update(workspace.id, {
|
|
140
|
-
ratchetState: shouldTakeAction ? newState : RatchetState.IDLE,
|
|
141
|
-
ratchetLastCheckedAt: now,
|
|
142
|
-
...(shouldRecordCiRunId ? { ratchetLastCiRunId: prStateInfo.ciRunId } : {}),
|
|
143
|
-
...(prStateInfo.hasNewReviewComments ? { prReviewLastCheckedAt: now } : {}),
|
|
144
|
-
});
|
|
109
|
+
await this.updateWorkspaceAfterCheck(workspace, prStateInfo, action, workspace.ratchetEnabled ? newState : RatchetState.IDLE);
|
|
145
110
|
return {
|
|
146
111
|
workspaceId: workspace.id,
|
|
147
112
|
previousState,
|
|
148
|
-
newState:
|
|
113
|
+
newState: workspace.ratchetEnabled ? newState : RatchetState.IDLE,
|
|
149
114
|
action,
|
|
150
115
|
};
|
|
151
116
|
}
|
|
@@ -162,6 +127,95 @@ class RatchetService {
|
|
|
162
127
|
};
|
|
163
128
|
}
|
|
164
129
|
}
|
|
130
|
+
async evaluateAndDispatch(workspace, prStateInfo) {
|
|
131
|
+
if (prStateInfo.prState === 'MERGED') {
|
|
132
|
+
return { type: 'COMPLETED' };
|
|
133
|
+
}
|
|
134
|
+
if (prStateInfo.prState !== 'OPEN') {
|
|
135
|
+
return { type: 'WAITING', reason: 'PR is not open' };
|
|
136
|
+
}
|
|
137
|
+
if (this.shouldSkipCleanPR(workspace, prStateInfo)) {
|
|
138
|
+
return {
|
|
139
|
+
type: 'WAITING',
|
|
140
|
+
reason: 'PR is clean (green CI and no new review activity)',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const activeRatchetSession = await this.getActiveRatchetSession(workspace);
|
|
144
|
+
if (activeRatchetSession) {
|
|
145
|
+
return activeRatchetSession;
|
|
146
|
+
}
|
|
147
|
+
if (!this.hasStateChangedSinceLastDispatch(workspace, prStateInfo)) {
|
|
148
|
+
return { type: 'WAITING', reason: 'PR state unchanged since last ratchet dispatch' };
|
|
149
|
+
}
|
|
150
|
+
const hasOtherActiveSession = await this.hasNonRatchetActiveSession(workspace.id);
|
|
151
|
+
if (hasOtherActiveSession) {
|
|
152
|
+
return {
|
|
153
|
+
type: 'WAITING',
|
|
154
|
+
reason: 'Workspace is not idle (active non-ratchet chat session)',
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return this.triggerFixer(workspace, prStateInfo);
|
|
158
|
+
}
|
|
159
|
+
shouldSkipCleanPR(workspace, prStateInfo) {
|
|
160
|
+
if (prStateInfo.ciStatus !== CIStatus.SUCCESS || prStateInfo.hasChangesRequested) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
return !this.hasNewReviewActivitySinceLastDispatch(workspace, prStateInfo);
|
|
164
|
+
}
|
|
165
|
+
hasNewReviewActivitySinceLastDispatch(workspace, prStateInfo) {
|
|
166
|
+
if (prStateInfo.latestReviewActivityAtMs === null) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (!workspace.prReviewLastCheckedAt) {
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
return prStateInfo.latestReviewActivityAtMs > workspace.prReviewLastCheckedAt.getTime();
|
|
173
|
+
}
|
|
174
|
+
hasStateChangedSinceLastDispatch(workspace, prStateInfo) {
|
|
175
|
+
return workspace.ratchetLastCiRunId !== prStateInfo.snapshotKey;
|
|
176
|
+
}
|
|
177
|
+
async updateWorkspaceAfterCheck(workspace, prStateInfo, action, nextState) {
|
|
178
|
+
const now = new Date();
|
|
179
|
+
const dispatched = action.type === 'TRIGGERED_FIXER' && action.promptSent;
|
|
180
|
+
await workspaceAccessor.update(workspace.id, {
|
|
181
|
+
ratchetState: nextState,
|
|
182
|
+
ratchetLastCheckedAt: now,
|
|
183
|
+
...(dispatched
|
|
184
|
+
? {
|
|
185
|
+
ratchetLastCiRunId: prStateInfo.snapshotKey,
|
|
186
|
+
prReviewLastCheckedAt: now,
|
|
187
|
+
}
|
|
188
|
+
: {}),
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async getActiveRatchetSession(workspace) {
|
|
192
|
+
if (!workspace.ratchetActiveSessionId) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const session = await claudeSessionAccessor.findById(workspace.ratchetActiveSessionId);
|
|
196
|
+
if (!session) {
|
|
197
|
+
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
if (session.status !== SessionStatus.RUNNING) {
|
|
201
|
+
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
if (!sessionService.isSessionRunning(session.id)) {
|
|
205
|
+
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
return { type: 'FIXER_ACTIVE', sessionId: workspace.ratchetActiveSessionId };
|
|
209
|
+
}
|
|
210
|
+
async hasNonRatchetActiveSession(workspaceId) {
|
|
211
|
+
const sessions = await claudeSessionAccessor.findByWorkspaceId(workspaceId);
|
|
212
|
+
return sessions.some((session) => {
|
|
213
|
+
if (session.workflow === RATCHET_WORKFLOW) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
return (session.status === SessionStatus.RUNNING || sessionService.isSessionRunning(session.id));
|
|
217
|
+
});
|
|
218
|
+
}
|
|
165
219
|
resolveRatchetPrContext(workspace) {
|
|
166
220
|
const prInfo = githubCLIService.extractPRInfo(workspace.prUrl);
|
|
167
221
|
if (!prInfo) {
|
|
@@ -181,7 +235,7 @@ class RatchetService {
|
|
|
181
235
|
prNumber,
|
|
182
236
|
};
|
|
183
237
|
}
|
|
184
|
-
async fetchPRState(workspace,
|
|
238
|
+
async fetchPRState(workspace, authenticatedUsername) {
|
|
185
239
|
const prContext = this.resolveRatchetPrContext(workspace);
|
|
186
240
|
if (!prContext) {
|
|
187
241
|
return null;
|
|
@@ -196,52 +250,14 @@ class RatchetService {
|
|
|
196
250
|
conclusion: check.conclusion ?? undefined,
|
|
197
251
|
})) ?? null;
|
|
198
252
|
const ciStatus = githubCLIService.computeCIStatus(statusCheckRollup);
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const conclusion = String(check.conclusion || check.status);
|
|
203
|
-
if (conclusion === 'FAILURE' ||
|
|
204
|
-
conclusion === 'ACTION_REQUIRED' ||
|
|
205
|
-
conclusion === 'ERROR') {
|
|
206
|
-
failedChecks.push({
|
|
207
|
-
name: check.name || 'Unknown check',
|
|
208
|
-
conclusion,
|
|
209
|
-
detailsUrl: check.detailsUrl,
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
const ciRunId = this.extractFailedCiSignature(failedChecks);
|
|
215
|
-
const hasChangesRequested = prDetails.reviews.some((r) => r.state === 'CHANGES_REQUESTED');
|
|
216
|
-
const lastCheckedAt = workspace.prReviewLastCheckedAt?.getTime() ?? 0;
|
|
217
|
-
const filterByReviewer = allowedReviewers.length > 0;
|
|
218
|
-
const newReviewComments = reviewComments.filter((comment) => {
|
|
219
|
-
const createdTime = new Date(comment.createdAt).getTime();
|
|
220
|
-
const updatedTime = new Date(comment.updatedAt).getTime();
|
|
221
|
-
const isNewOrEdited = createdTime > lastCheckedAt || updatedTime > lastCheckedAt;
|
|
222
|
-
const isAllowedReviewer = !filterByReviewer || allowedReviewers.includes(comment.author.login);
|
|
223
|
-
return isNewOrEdited && isAllowedReviewer;
|
|
224
|
-
});
|
|
225
|
-
const newPRComments = prDetails.comments.filter((comment) => {
|
|
226
|
-
const createdTime = new Date(comment.createdAt).getTime();
|
|
227
|
-
const updatedTime = new Date(comment.updatedAt).getTime();
|
|
228
|
-
const isNewOrEdited = createdTime > lastCheckedAt || updatedTime > lastCheckedAt;
|
|
229
|
-
const isAllowedReviewer = !filterByReviewer || allowedReviewers.includes(comment.author.login);
|
|
230
|
-
return isNewOrEdited && isAllowedReviewer;
|
|
231
|
-
});
|
|
232
|
-
const hasNewReviewComments = newReviewComments.length > 0 || newPRComments.length > 0;
|
|
253
|
+
const hasChangesRequested = prDetails.reviewDecision === 'CHANGES_REQUESTED';
|
|
254
|
+
const latestReviewActivityAtMs = this.computeLatestReviewActivityAtMs(prDetails, reviewComments, authenticatedUsername);
|
|
255
|
+
const snapshotKey = this.computeDispatchSnapshotKey(ciStatus, hasChangesRequested, latestReviewActivityAtMs, prDetails.statusCheckRollup);
|
|
233
256
|
return {
|
|
234
257
|
ciStatus,
|
|
235
|
-
|
|
258
|
+
snapshotKey,
|
|
236
259
|
hasChangesRequested,
|
|
237
|
-
|
|
238
|
-
failedChecks,
|
|
239
|
-
ciRunId,
|
|
240
|
-
reviews: prDetails.reviews,
|
|
241
|
-
comments: prDetails.comments,
|
|
242
|
-
reviewComments,
|
|
243
|
-
newReviewComments,
|
|
244
|
-
newPRComments,
|
|
260
|
+
latestReviewActivityAtMs,
|
|
245
261
|
prState: prDetails.state,
|
|
246
262
|
prNumber: prDetails.number,
|
|
247
263
|
};
|
|
@@ -254,175 +270,94 @@ class RatchetService {
|
|
|
254
270
|
return null;
|
|
255
271
|
}
|
|
256
272
|
}
|
|
273
|
+
computeDispatchSnapshotKey(ciStatus, hasChangesRequested, latestReviewActivityAtMs, statusChecks) {
|
|
274
|
+
const ciKey = this.computeCiSnapshotKey(ciStatus, statusChecks);
|
|
275
|
+
const reviewKey = `${hasChangesRequested ? 'changes-requested' : 'no-changes-requested'}:${latestReviewActivityAtMs ?? 'none'}`;
|
|
276
|
+
return `${ciKey}|${reviewKey}`;
|
|
277
|
+
}
|
|
278
|
+
computeCiSnapshotKey(ciStatus, statusChecks) {
|
|
279
|
+
if (ciStatus !== CIStatus.FAILURE) {
|
|
280
|
+
return `ci:${ciStatus}`;
|
|
281
|
+
}
|
|
282
|
+
const failedChecks = statusChecks?.filter((check) => {
|
|
283
|
+
const conclusion = check.conclusion?.toUpperCase();
|
|
284
|
+
return (conclusion === 'FAILURE' ||
|
|
285
|
+
conclusion === 'TIMED_OUT' ||
|
|
286
|
+
conclusion === 'CANCELLED' ||
|
|
287
|
+
conclusion === 'ERROR' ||
|
|
288
|
+
conclusion === 'ACTION_REQUIRED');
|
|
289
|
+
}) ?? [];
|
|
290
|
+
if (failedChecks.length === 0) {
|
|
291
|
+
return 'ci:FAILURE:unknown';
|
|
292
|
+
}
|
|
293
|
+
const signature = failedChecks
|
|
294
|
+
.map((check) => {
|
|
295
|
+
const runIdMatch = check.detailsUrl?.match(/\/actions\/runs\/(\d+)/);
|
|
296
|
+
const runId = runIdMatch?.[1] ?? 'no-run-id';
|
|
297
|
+
return `${check.name ?? 'unknown'}:${check.conclusion ?? 'UNKNOWN'}:${runId}`;
|
|
298
|
+
})
|
|
299
|
+
.sort()
|
|
300
|
+
.join('|');
|
|
301
|
+
return `ci:FAILURE:${signature}`;
|
|
302
|
+
}
|
|
303
|
+
computeLatestReviewActivityAtMs(prDetails, reviewComments, authenticatedUsername) {
|
|
304
|
+
const entries = [
|
|
305
|
+
...prDetails.reviews.map((review) => ({
|
|
306
|
+
authorLogin: review.author.login,
|
|
307
|
+
timestamp: review.submittedAt,
|
|
308
|
+
})),
|
|
309
|
+
...prDetails.comments.map((comment) => ({
|
|
310
|
+
authorLogin: comment.author.login,
|
|
311
|
+
timestamp: comment.updatedAt,
|
|
312
|
+
})),
|
|
313
|
+
...reviewComments.map((reviewComment) => ({
|
|
314
|
+
authorLogin: reviewComment.author.login,
|
|
315
|
+
timestamp: reviewComment.updatedAt,
|
|
316
|
+
})),
|
|
317
|
+
];
|
|
318
|
+
const timestamps = entries
|
|
319
|
+
.filter((entry) => !this.isIgnoredReviewAuthor(entry.authorLogin, authenticatedUsername))
|
|
320
|
+
.map((entry) => Date.parse(entry.timestamp))
|
|
321
|
+
.filter((timestamp) => Number.isFinite(timestamp));
|
|
322
|
+
return timestamps.length > 0 ? Math.max(...timestamps) : null;
|
|
323
|
+
}
|
|
324
|
+
isIgnoredReviewAuthor(authorLogin, authenticatedUsername) {
|
|
325
|
+
if (!authenticatedUsername) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
return authorLogin === authenticatedUsername;
|
|
329
|
+
}
|
|
330
|
+
async getAuthenticatedUsernameCached() {
|
|
331
|
+
const nowMs = Date.now();
|
|
332
|
+
if (this.cachedAuthenticatedUsername && this.cachedAuthenticatedUsername.expiresAtMs > nowMs) {
|
|
333
|
+
return this.cachedAuthenticatedUsername.value;
|
|
334
|
+
}
|
|
335
|
+
const username = await githubCLIService.getAuthenticatedUsername();
|
|
336
|
+
this.cachedAuthenticatedUsername = {
|
|
337
|
+
value: username,
|
|
338
|
+
expiresAtMs: nowMs + AUTHENTICATED_USERNAME_CACHE_TTL_MS,
|
|
339
|
+
};
|
|
340
|
+
return username;
|
|
341
|
+
}
|
|
257
342
|
determineRatchetState(pr) {
|
|
258
343
|
if (pr.prState === 'MERGED') {
|
|
259
344
|
return RatchetState.MERGED;
|
|
260
345
|
}
|
|
261
|
-
if (pr.
|
|
346
|
+
if (pr.prState !== 'OPEN') {
|
|
347
|
+
return RatchetState.IDLE;
|
|
348
|
+
}
|
|
349
|
+
if (pr.ciStatus === CIStatus.PENDING || pr.ciStatus === CIStatus.UNKNOWN) {
|
|
262
350
|
return RatchetState.CI_RUNNING;
|
|
263
351
|
}
|
|
264
352
|
if (pr.ciStatus === CIStatus.FAILURE) {
|
|
265
353
|
return RatchetState.CI_FAILED;
|
|
266
354
|
}
|
|
267
|
-
if (pr.
|
|
268
|
-
return RatchetState.CI_RUNNING;
|
|
269
|
-
}
|
|
270
|
-
if (pr.mergeStateStatus === 'CONFLICTING') {
|
|
271
|
-
return RatchetState.MERGE_CONFLICT;
|
|
272
|
-
}
|
|
273
|
-
if (pr.hasChangesRequested || pr.hasNewReviewComments) {
|
|
355
|
+
if (pr.hasChangesRequested) {
|
|
274
356
|
return RatchetState.REVIEW_PENDING;
|
|
275
357
|
}
|
|
276
358
|
return RatchetState.READY;
|
|
277
359
|
}
|
|
278
|
-
async
|
|
279
|
-
const existingFixerResult = await this.handleExistingFixerSession(workspace, state, prStateInfo);
|
|
280
|
-
if (existingFixerResult) {
|
|
281
|
-
return existingFixerResult;
|
|
282
|
-
}
|
|
283
|
-
return this.handleStateWithoutActiveFixer(workspace, state, prStateInfo, settings);
|
|
284
|
-
}
|
|
285
|
-
async handleExistingFixerSession(workspace, state, prStateInfo) {
|
|
286
|
-
if (!workspace.ratchetActiveSessionId) {
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
const session = await claudeSessionAccessor.findById(workspace.ratchetActiveSessionId);
|
|
290
|
-
const client = sessionService.getClient(workspace.ratchetActiveSessionId);
|
|
291
|
-
if (!session) {
|
|
292
|
-
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
293
|
-
return null;
|
|
294
|
-
}
|
|
295
|
-
if (session.status === SessionStatus.IDLE) {
|
|
296
|
-
if (!client) {
|
|
297
|
-
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
298
|
-
}
|
|
299
|
-
return null;
|
|
300
|
-
}
|
|
301
|
-
if (session.status !== SessionStatus.RUNNING || !client) {
|
|
302
|
-
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
303
|
-
return null;
|
|
304
|
-
}
|
|
305
|
-
const shouldNotify = this.shouldNotifyActiveFixer(state, workspace.ratchetLastNotifiedState, prStateInfo.ciRunId, workspace.ratchetLastCiRunId);
|
|
306
|
-
if (!shouldNotify) {
|
|
307
|
-
return { type: 'FIXER_ACTIVE', sessionId: workspace.ratchetActiveSessionId };
|
|
308
|
-
}
|
|
309
|
-
const delivered = await this.notifyActiveFixer(workspace, state, prStateInfo, client);
|
|
310
|
-
if (delivered) {
|
|
311
|
-
return {
|
|
312
|
-
type: 'NOTIFIED_ACTIVE_FIXER',
|
|
313
|
-
sessionId: workspace.ratchetActiveSessionId,
|
|
314
|
-
issue: state,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
logger.warn('Failed to notify active fixer; clearing stale reference and retrying', {
|
|
318
|
-
workspaceId: workspace.id,
|
|
319
|
-
sessionId: workspace.ratchetActiveSessionId,
|
|
320
|
-
state,
|
|
321
|
-
});
|
|
322
|
-
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
323
|
-
return null;
|
|
324
|
-
}
|
|
325
|
-
async handleStateWithoutActiveFixer(workspace, state, prStateInfo, settings) {
|
|
326
|
-
switch (state) {
|
|
327
|
-
case RatchetState.IDLE:
|
|
328
|
-
return { type: 'WAITING', reason: 'No PR or ratchet not active' };
|
|
329
|
-
case RatchetState.CI_RUNNING:
|
|
330
|
-
return { type: 'WAITING', reason: 'CI is running' };
|
|
331
|
-
case RatchetState.CI_FAILED:
|
|
332
|
-
if (!settings.autoFixCi) {
|
|
333
|
-
return { type: 'DISABLED', reason: 'CI auto-fix disabled' };
|
|
334
|
-
}
|
|
335
|
-
return await this.triggerFixer(workspace, 'ci', prStateInfo, settings);
|
|
336
|
-
case RatchetState.MERGE_CONFLICT:
|
|
337
|
-
if (!settings.autoFixConflicts) {
|
|
338
|
-
return { type: 'DISABLED', reason: 'Conflict resolution disabled' };
|
|
339
|
-
}
|
|
340
|
-
return await this.triggerFixer(workspace, 'merge', prStateInfo, settings);
|
|
341
|
-
case RatchetState.REVIEW_PENDING:
|
|
342
|
-
if (!settings.autoFixReviews) {
|
|
343
|
-
return { type: 'DISABLED', reason: 'Review auto-fix disabled' };
|
|
344
|
-
}
|
|
345
|
-
return await this.triggerFixer(workspace, 'review', prStateInfo, settings);
|
|
346
|
-
case RatchetState.READY:
|
|
347
|
-
if (settings.autoMerge) {
|
|
348
|
-
logger.info('PR ready for merge (auto-merge not yet implemented)', {
|
|
349
|
-
workspaceId: workspace.id,
|
|
350
|
-
prNumber: workspace.prNumber,
|
|
351
|
-
});
|
|
352
|
-
return { type: 'READY_FOR_MERGE' };
|
|
353
|
-
}
|
|
354
|
-
return { type: 'READY_FOR_MERGE' };
|
|
355
|
-
case RatchetState.MERGED:
|
|
356
|
-
return { type: 'COMPLETED' };
|
|
357
|
-
default:
|
|
358
|
-
return { type: 'WAITING', reason: `Unknown state: ${state}` };
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
shouldNotifyActiveFixer(currentState, lastNotifiedState, currentCiRunId, lastCiRunId) {
|
|
362
|
-
if (currentState === RatchetState.CI_FAILED &&
|
|
363
|
-
currentCiRunId &&
|
|
364
|
-
currentCiRunId !== lastCiRunId) {
|
|
365
|
-
return true;
|
|
366
|
-
}
|
|
367
|
-
if (currentState === lastNotifiedState) {
|
|
368
|
-
return false;
|
|
369
|
-
}
|
|
370
|
-
const priorityStates = [RatchetState.CI_FAILED, RatchetState.MERGE_CONFLICT];
|
|
371
|
-
return priorityStates.includes(currentState);
|
|
372
|
-
}
|
|
373
|
-
async notifyActiveFixer(workspace, state, prStateInfo, client) {
|
|
374
|
-
if (!workspace.ratchetActiveSessionId) {
|
|
375
|
-
logger.warn('notifyActiveFixer called without active session ID', {
|
|
376
|
-
workspaceId: workspace.id,
|
|
377
|
-
});
|
|
378
|
-
return false;
|
|
379
|
-
}
|
|
380
|
-
let message = '';
|
|
381
|
-
if (state === RatchetState.CI_FAILED) {
|
|
382
|
-
message = `⚠️ **CI Failed**
|
|
383
|
-
|
|
384
|
-
The CI checks have failed. This may be due to your recent changes.
|
|
385
|
-
|
|
386
|
-
**Failed checks:**
|
|
387
|
-
${prStateInfo.failedChecks.map((c) => `- **${c.name}**: ${c.conclusion}${c.detailsUrl ? ` ([logs](${c.detailsUrl}))` : ''}`).join('\n')}
|
|
388
|
-
|
|
389
|
-
Please investigate and fix the CI failure before continuing with your current task.
|
|
390
|
-
Use \`gh pr checks ${prStateInfo.prNumber}\` to see current status.
|
|
391
|
-
Use \`gh run view <run-id> --log-failed\` to see detailed logs.`;
|
|
392
|
-
}
|
|
393
|
-
else if (state === RatchetState.MERGE_CONFLICT) {
|
|
394
|
-
message = `⚠️ **Merge Conflict Detected**
|
|
395
|
-
|
|
396
|
-
The branch now has merge conflicts with the base branch.
|
|
397
|
-
Please resolve the conflicts before continuing.
|
|
398
|
-
|
|
399
|
-
Run \`git fetch origin && git merge origin/main\` to see the conflicts.`;
|
|
400
|
-
}
|
|
401
|
-
if (message) {
|
|
402
|
-
try {
|
|
403
|
-
await client.sendMessage(message);
|
|
404
|
-
logger.info('Notified active fixer about state change', {
|
|
405
|
-
workspaceId: workspace.id,
|
|
406
|
-
sessionId: workspace.ratchetActiveSessionId,
|
|
407
|
-
state,
|
|
408
|
-
});
|
|
409
|
-
await workspaceAccessor.update(workspace.id, {
|
|
410
|
-
ratchetLastNotifiedState: state,
|
|
411
|
-
});
|
|
412
|
-
return true;
|
|
413
|
-
}
|
|
414
|
-
catch (error) {
|
|
415
|
-
logger.warn('Failed to notify fixer about state change', {
|
|
416
|
-
workspaceId: workspace.id,
|
|
417
|
-
state,
|
|
418
|
-
error,
|
|
419
|
-
});
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
return false;
|
|
424
|
-
}
|
|
425
|
-
async triggerFixer(workspace, fixerType, prStateInfo, settings) {
|
|
360
|
+
async triggerFixer(workspace, prStateInfo) {
|
|
426
361
|
try {
|
|
427
362
|
const result = await fixerSessionService.acquireAndDispatch({
|
|
428
363
|
workspaceId: workspace.id,
|
|
@@ -430,30 +365,31 @@ Run \`git fetch origin && git merge origin/main\` to see the conflicts.`;
|
|
|
430
365
|
sessionName: 'Ratchet',
|
|
431
366
|
runningIdleAction: 'restart',
|
|
432
367
|
dispatchMode: 'start_empty_and_send',
|
|
433
|
-
buildPrompt: () =>
|
|
368
|
+
buildPrompt: () => buildRatchetDispatchPrompt(workspace.prUrl, prStateInfo.prNumber),
|
|
434
369
|
beforeStart: ({ sessionId, prompt }) => {
|
|
435
370
|
messageStateService.injectCommittedUserMessage(sessionId, prompt);
|
|
436
371
|
},
|
|
437
372
|
});
|
|
438
373
|
if (result.status === 'started') {
|
|
439
|
-
const
|
|
374
|
+
const promptSent = result.promptSent ?? true;
|
|
375
|
+
if (!promptSent) {
|
|
376
|
+
logger.warn('Ratchet session started but prompt delivery failed', {
|
|
377
|
+
workspaceId: workspace.id,
|
|
378
|
+
sessionId: result.sessionId,
|
|
379
|
+
});
|
|
380
|
+
await workspaceAccessor.update(workspace.id, { ratchetActiveSessionId: null });
|
|
381
|
+
if (sessionService.isSessionRunning(result.sessionId)) {
|
|
382
|
+
await sessionService.stopClaudeSession(result.sessionId);
|
|
383
|
+
}
|
|
384
|
+
return { type: 'ERROR', error: 'Failed to deliver initial ratchet prompt' };
|
|
385
|
+
}
|
|
440
386
|
await workspaceAccessor.update(workspace.id, {
|
|
441
387
|
ratchetActiveSessionId: result.sessionId,
|
|
442
|
-
...(shouldMarkNotified && {
|
|
443
|
-
ratchetLastNotifiedState: this.determineRatchetState(prStateInfo),
|
|
444
|
-
}),
|
|
445
|
-
});
|
|
446
|
-
logger.info('Ratchet fixer session started', {
|
|
447
|
-
workspaceId: workspace.id,
|
|
448
|
-
sessionId: result.sessionId,
|
|
449
|
-
fixerType,
|
|
450
|
-
prNumber: prStateInfo.prNumber,
|
|
451
388
|
});
|
|
452
389
|
return {
|
|
453
390
|
type: 'TRIGGERED_FIXER',
|
|
454
391
|
sessionId: result.sessionId,
|
|
455
|
-
|
|
456
|
-
promptSent: shouldMarkNotified,
|
|
392
|
+
promptSent,
|
|
457
393
|
};
|
|
458
394
|
}
|
|
459
395
|
if (result.status === 'already_active') {
|
|
@@ -469,187 +405,10 @@ Run \`git fetch origin && git merge origin/main\` to see the conflicts.`;
|
|
|
469
405
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
470
406
|
logger.error('Failed to trigger ratchet fixer', error, {
|
|
471
407
|
workspaceId: workspace.id,
|
|
472
|
-
fixerType,
|
|
473
408
|
});
|
|
474
409
|
return { type: 'ERROR', error: errorMessage };
|
|
475
410
|
}
|
|
476
411
|
}
|
|
477
|
-
buildInitialPrompt(fixerType, prUrl, prStateInfo, settings) {
|
|
478
|
-
const prNumber = prStateInfo.prNumber;
|
|
479
|
-
switch (fixerType) {
|
|
480
|
-
case 'ci':
|
|
481
|
-
return this.buildCIFixPrompt(prNumber, prUrl, prStateInfo);
|
|
482
|
-
case 'merge':
|
|
483
|
-
return this.buildMergeFixPrompt(prNumber, prUrl);
|
|
484
|
-
case 'review':
|
|
485
|
-
return this.buildReviewFixPrompt(prNumber, prUrl, prStateInfo, settings);
|
|
486
|
-
default:
|
|
487
|
-
return `Please investigate the issue with PR #${prNumber}.`;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
buildCIFixPrompt(prNumber, prUrl, prStateInfo) {
|
|
491
|
-
let prompt = `## CI Failure Alert
|
|
492
|
-
|
|
493
|
-
The CI checks for PR #${prNumber} have failed.
|
|
494
|
-
|
|
495
|
-
**PR URL:** ${prUrl}
|
|
496
|
-
|
|
497
|
-
`;
|
|
498
|
-
if (prStateInfo.failedChecks.length > 0) {
|
|
499
|
-
prompt += `### Failed Checks\n\n`;
|
|
500
|
-
for (const check of prStateInfo.failedChecks) {
|
|
501
|
-
prompt += `- **${check.name}**: ${check.conclusion}`;
|
|
502
|
-
if (check.detailsUrl) {
|
|
503
|
-
prompt += ` ([logs](${check.detailsUrl}))`;
|
|
504
|
-
}
|
|
505
|
-
prompt += `\n`;
|
|
506
|
-
}
|
|
507
|
-
prompt += `\n`;
|
|
508
|
-
}
|
|
509
|
-
prompt += `### Next Steps
|
|
510
|
-
|
|
511
|
-
1. Use \`gh pr checks ${prNumber}\` to see the current check status
|
|
512
|
-
2. Use \`gh run view <run-id> --log-failed\` to see detailed failure logs
|
|
513
|
-
3. Identify the root cause and implement a fix
|
|
514
|
-
4. Run tests locally to verify: \`pnpm test\`
|
|
515
|
-
5. Run type checking: \`pnpm typecheck\`
|
|
516
|
-
6. Run linting: \`pnpm check:fix\`
|
|
517
|
-
7. Commit and push your changes
|
|
518
|
-
|
|
519
|
-
Please investigate and fix these CI failures.`;
|
|
520
|
-
return prompt;
|
|
521
|
-
}
|
|
522
|
-
buildMergeFixPrompt(prNumber, prUrl) {
|
|
523
|
-
return `## Merge Conflict Alert
|
|
524
|
-
|
|
525
|
-
PR #${prNumber} has merge conflicts with the base branch.
|
|
526
|
-
|
|
527
|
-
**PR URL:** ${prUrl}
|
|
528
|
-
|
|
529
|
-
### Next Steps
|
|
530
|
-
|
|
531
|
-
1. Fetch the latest changes: \`git fetch origin\`
|
|
532
|
-
2. Merge the base branch: \`git merge origin/main\`
|
|
533
|
-
3. Resolve any conflicts in the affected files
|
|
534
|
-
4. For each conflict:
|
|
535
|
-
- Understand both sides of the change
|
|
536
|
-
- Preserve functionality from both when possible
|
|
537
|
-
- If unsure, prefer the main branch changes
|
|
538
|
-
5. After resolving, run tests: \`pnpm test\`
|
|
539
|
-
6. Run type checking: \`pnpm typecheck\`
|
|
540
|
-
7. Commit the merge: \`git commit -m "Merge main into feature branch"\`
|
|
541
|
-
8. Push your changes: \`git push\`
|
|
542
|
-
|
|
543
|
-
Please resolve these merge conflicts.`;
|
|
544
|
-
}
|
|
545
|
-
filterByAllowedReviewers(items, allowedReviewers) {
|
|
546
|
-
if (allowedReviewers.length === 0) {
|
|
547
|
-
return items;
|
|
548
|
-
}
|
|
549
|
-
return items.filter((item) => allowedReviewers.includes(item.author.login));
|
|
550
|
-
}
|
|
551
|
-
formatReviewsSection(reviews) {
|
|
552
|
-
if (reviews.length === 0) {
|
|
553
|
-
return '';
|
|
554
|
-
}
|
|
555
|
-
const lines = ['### Reviews Requesting Changes\n\n'];
|
|
556
|
-
for (const review of reviews) {
|
|
557
|
-
lines.push(`**${review.author.login}** (${new Date(review.submittedAt).toLocaleDateString()}):\n`);
|
|
558
|
-
if (review.body) {
|
|
559
|
-
lines.push(`> ${review.body.split('\n').join('\n> ')}\n`);
|
|
560
|
-
}
|
|
561
|
-
lines.push('\n');
|
|
562
|
-
}
|
|
563
|
-
return lines.join('');
|
|
564
|
-
}
|
|
565
|
-
formatCodeCommentsSection(comments) {
|
|
566
|
-
if (comments.length === 0) {
|
|
567
|
-
return '';
|
|
568
|
-
}
|
|
569
|
-
const lines = ['### Review Comments on Code\n\n'];
|
|
570
|
-
for (const comment of comments) {
|
|
571
|
-
const location = comment.line ? `:${comment.line}` : '';
|
|
572
|
-
lines.push(`**${comment.author.login}** on \`${comment.path}\`${location}:\n`);
|
|
573
|
-
lines.push(`> ${comment.body.split('\n').join('\n> ')}\n`);
|
|
574
|
-
lines.push(`> [View comment](${comment.url})\n\n`);
|
|
575
|
-
}
|
|
576
|
-
return lines.join('');
|
|
577
|
-
}
|
|
578
|
-
formatPRCommentsSection(comments) {
|
|
579
|
-
if (comments.length === 0) {
|
|
580
|
-
return '';
|
|
581
|
-
}
|
|
582
|
-
const lines = ['### PR Comments\n\n'];
|
|
583
|
-
for (const comment of comments) {
|
|
584
|
-
lines.push(`**${comment.author.login}** (${new Date(comment.createdAt).toLocaleDateString()}):\n`);
|
|
585
|
-
lines.push(`> ${comment.body.split('\n').join('\n> ')}\n\n`);
|
|
586
|
-
}
|
|
587
|
-
return lines.join('');
|
|
588
|
-
}
|
|
589
|
-
buildReviewFixPrompt(prNumber, prUrl, prStateInfo, settings) {
|
|
590
|
-
const parts = [
|
|
591
|
-
`## PR Review Comments Alert
|
|
592
|
-
|
|
593
|
-
New review comments have been received on PR #${prNumber}.
|
|
594
|
-
|
|
595
|
-
**PR URL:** ${prUrl}
|
|
596
|
-
|
|
597
|
-
`,
|
|
598
|
-
];
|
|
599
|
-
const changesRequestedReviews = prStateInfo.reviews.filter((r) => r.state === 'CHANGES_REQUESTED');
|
|
600
|
-
const filteredReviews = this.filterByAllowedReviewers(changesRequestedReviews, settings.allowedReviewers);
|
|
601
|
-
parts.push(this.formatReviewsSection(filteredReviews));
|
|
602
|
-
parts.push(this.formatCodeCommentsSection(prStateInfo.newReviewComments));
|
|
603
|
-
parts.push(this.formatPRCommentsSection(prStateInfo.newPRComments));
|
|
604
|
-
const reviewerSet = new Set([
|
|
605
|
-
...filteredReviews.map((r) => r.author.login),
|
|
606
|
-
...prStateInfo.newReviewComments.map((c) => c.author.login),
|
|
607
|
-
...prStateInfo.newPRComments.map((c) => c.author.login),
|
|
608
|
-
]);
|
|
609
|
-
const reviewerMentions = Array.from(reviewerSet)
|
|
610
|
-
.map((r) => `@${r}`)
|
|
611
|
-
.join(' ');
|
|
612
|
-
parts.push(`### Instructions
|
|
613
|
-
|
|
614
|
-
**IMPORTANT: Execute autonomously. Do not ask the user for input or confirmation. Complete all steps without waiting.**
|
|
615
|
-
|
|
616
|
-
1. **Analyze each comment** - Determine what changes are requested. If a comment is purely informational (e.g., automated coverage reports with no action items), note it and move on.
|
|
617
|
-
|
|
618
|
-
2. **Implement fixes** - Address each actionable comment systematically. Make focused changes that directly address the feedback.
|
|
619
|
-
|
|
620
|
-
3. **Verify changes**:
|
|
621
|
-
\`\`\`bash
|
|
622
|
-
pnpm test && pnpm typecheck && pnpm check:fix
|
|
623
|
-
\`\`\`
|
|
624
|
-
|
|
625
|
-
4. **Commit and push**:
|
|
626
|
-
\`\`\`bash
|
|
627
|
-
git add -A && git commit -m "Address review comments" && git push
|
|
628
|
-
\`\`\`
|
|
629
|
-
|
|
630
|
-
5. **Post re-review request** - After pushing, notify the reviewers:
|
|
631
|
-
\`\`\`bash
|
|
632
|
-
gh pr comment ${prNumber} --body "${reviewerMentions} I've addressed the review comments. Please re-review when you have a chance."
|
|
633
|
-
\`\`\`
|
|
634
|
-
|
|
635
|
-
**Do not ask the user what to do. Analyze the comments, implement fixes, push, and request re-review.**`);
|
|
636
|
-
return parts.join('');
|
|
637
|
-
}
|
|
638
|
-
extractFailedCiSignature(failedChecks) {
|
|
639
|
-
if (failedChecks.length === 0) {
|
|
640
|
-
return null;
|
|
641
|
-
}
|
|
642
|
-
const failedEntries = [];
|
|
643
|
-
for (const check of failedChecks) {
|
|
644
|
-
const runIdMatch = check.detailsUrl?.match(/\/actions\/runs\/(\d+)/);
|
|
645
|
-
const runId = runIdMatch?.[1] ?? 'no-run-id';
|
|
646
|
-
failedEntries.push(`${check.name}:${runId}`);
|
|
647
|
-
}
|
|
648
|
-
if (failedEntries.length === 0) {
|
|
649
|
-
return null;
|
|
650
|
-
}
|
|
651
|
-
return failedEntries.sort().join('|');
|
|
652
|
-
}
|
|
653
412
|
}
|
|
654
413
|
export const ratchetService = new RatchetService();
|
|
655
414
|
//# sourceMappingURL=ratchet.service.js.map
|