specrails-desktop 2.29.0 → 2.29.2
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/client/dist/assets/ActivityFeedPage-ClpD5CFj.js +1 -0
- package/client/dist/assets/AgentBrowserCapture-CSPs9Ofc.js +1 -0
- package/client/dist/assets/AgentModeCodePane-DwcyklA5.js +2 -0
- package/client/dist/assets/AgentModeJobsPane-C69bqlMa.js +1 -0
- package/client/dist/assets/AgentsPage-pRiRr9-W.js +86 -0
- package/client/dist/assets/AnalyticsPage-C14exKsC.js +1 -0
- package/client/dist/assets/BarChart-nBOMNfiy.js +33 -0
- package/client/dist/assets/CodePage-CK76JKm9.js +2 -0
- package/client/dist/assets/DesktopAnalyticsPage-Cnv0f3XQ.js +1 -0
- package/client/dist/assets/DocsDialog-CHUm_Ym0.js +11 -0
- package/client/dist/assets/DocsPage-COI-oDok.js +11 -0
- package/client/dist/assets/ExportDropdown-BrtfWzEG.js +1 -0
- package/client/dist/assets/IntegrationsPage-Bs00_tl4.js +1 -0
- package/client/dist/assets/InteractiveJobComposer-CypM7R1F.js +19 -0
- package/client/dist/assets/JobDetailModal-B_W0H9dw.js +1 -0
- package/client/dist/assets/JobDetailPage-CeeXOoKS.js +1 -0
- package/client/dist/assets/JobsPage-CwhJG9jw.js +1 -0
- package/client/dist/assets/LoopBuilderPage-C51t1WOM.js +7 -0
- package/client/dist/assets/LoopPreviewModal-Y2HgtIJu.js +1 -0
- package/client/dist/assets/LoopsPage-Bvn1Kw5V.js +1 -0
- package/client/dist/assets/MinimizedChatsContext-DiFvZDPW.js +1 -0
- package/client/dist/assets/PluginsPage-BGPRJpdf.js +2 -0
- package/client/dist/assets/ProjectSettingsDialog-D_GTyGLc.js +1 -0
- package/client/dist/assets/TemplatePreviewModal-szwBhd7h.js +1 -0
- package/client/dist/assets/TicketDetailModal-9UEyK974.js +14 -0
- package/client/dist/assets/Trans-B_vKZ-Hb.js +1 -0
- package/client/dist/assets/activity-DiyjsgQV.js +1 -0
- package/client/dist/assets/addon-image-BRmmRHgQ.js +1 -0
- package/client/dist/assets/addon-ligatures-qIZUPvRV.js +2 -0
- package/client/dist/assets/{addon-webgl-DMbGeI_u.js → addon-webgl-C2d7lriQ.js} +3 -3
- package/client/dist/assets/addspec-Rw8uVBC1.js +1 -0
- package/client/dist/assets/agent-4rmXoo_p.js +1 -0
- package/client/dist/assets/agent-BxZuNGih.js +1 -0
- package/client/dist/assets/agent-C3uXOYv_.js +1 -0
- package/client/dist/assets/agent-CA8Y4wbw.js +1 -0
- package/client/dist/assets/agent-CASKrhG12.js +1 -0
- package/client/dist/assets/agent-Cv-jud5n2.js +1 -0
- package/client/dist/assets/agent-DitUxYh2.js +1 -0
- package/client/dist/assets/agent-Doow4X7o.js +1 -0
- package/client/dist/assets/agents-DhG7mg6-.js +1 -0
- package/client/dist/assets/agentstudio-BIUe1Im2.js +1 -0
- package/client/dist/assets/aiedit-iIjz2_Qk.js +1 -0
- package/client/dist/assets/analytics-DZ8Aoq3I.js +1 -0
- package/client/dist/assets/api-B2M7CtDw.js +1 -0
- package/client/dist/assets/arrow-left-CpIR4j7G.js +1 -0
- package/client/dist/assets/arrow-up-right-9DoMn7fD.js +1 -0
- package/client/dist/assets/attachments-B53PG733.js +1 -0
- package/client/dist/assets/brain-DI9lHkKY.js +1 -0
- package/client/dist/assets/browser-CXUcnTMI.js +1 -0
- package/client/dist/assets/button-BUIIBQPT.js +1 -0
- package/client/dist/assets/chat-BGD7MXAy.js +1 -0
- package/client/dist/assets/chevron-right-CViMxucY.js +1 -0
- package/client/dist/assets/chunk-KS7C4IRE-Cx5sqopX.js +3 -0
- package/client/dist/assets/circle-x-CMYsN4ZH.js +1 -0
- package/client/dist/assets/code-BDXEM4ml.js +1 -0
- package/client/dist/assets/commands-DyUZQ1FI.js +1 -0
- package/client/dist/assets/common-CD1QHriA2.js +1 -0
- package/client/dist/assets/common-CwwPaRxx.js +1 -0
- package/client/dist/assets/common-DVQuhs-m.js +1 -0
- package/client/dist/assets/common-Dg2jaX7d.js +1 -0
- package/client/dist/assets/common-DuBwj6tK.js +1 -0
- package/client/dist/assets/common-MRj9MHcc.js +1 -0
- package/client/dist/assets/common-O4ZpnMLp.js +1 -0
- package/client/dist/assets/common-fyeF0v7C2.js +1 -0
- package/client/dist/assets/createLucideIcon-Bjbbp_KS.js +1 -0
- package/client/dist/assets/{css.worker-Wv5dxAWO.js → css.worker-yKcq13f2.js} +13 -13
- package/client/dist/assets/{cssMode-DBHbkBvI.js → cssMode-BM4z9OX0.js} +1 -1
- package/client/dist/assets/dashboard-B_NkSHYm.js +1 -0
- package/client/dist/assets/dashboard-ClBb_3pq.js +1 -0
- package/client/dist/assets/dashboard-CpCmJvMB.js +1 -0
- package/client/dist/assets/dashboard-Czohu35O2.js +1 -0
- package/client/dist/assets/dashboard-DcjbD0UK.js +1 -0
- package/client/dist/assets/dashboard-Dvx5F3we.js +1 -0
- package/client/dist/assets/dashboard-R1bOPjBh2.js +1 -0
- package/client/dist/assets/dashboard-owcDucDi.js +1 -0
- package/client/dist/assets/dialog-CzIekCw0.js +45 -0
- package/client/dist/assets/dist-Cez5CRkX.js +1 -0
- package/client/dist/assets/dist-bVqfYmby.js +1 -0
- package/client/dist/assets/{dist-js-UjXbEWhN.js → dist-js-CcBCbb32.js} +1 -1
- package/client/dist/assets/{dist-js-BTAcxhPb.js → dist-js-VwztRkGj.js} +1 -1
- package/client/dist/assets/download-CFHyyHcw.js +1 -0
- package/client/dist/assets/editor.api2-4ndOupAA.js +872 -0
- package/client/dist/assets/{editor.main-C9J2ikJK.js → editor.main-DxrmGfoq.js} +2 -2
- package/client/dist/assets/editor.worker-tytyn86m.js +26 -0
- package/client/dist/assets/explore-DgBACn39.js +1 -0
- package/client/dist/assets/external-link-BcU5EWZp.js +1 -0
- package/client/dist/assets/file-text-CFT-xXKN.js +1 -0
- package/client/dist/assets/formatDistanceToNow-ByHIauTQ.js +1 -0
- package/client/dist/assets/{freemarker2-J5iIIIK-.js → freemarker2-CELlTDJ2.js} +1 -1
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-BxHAksaU.js +1 -0
- package/client/dist/assets/git-branch-BRM0F5GN.js +1 -0
- package/client/dist/assets/{handlebars-DSw1l_tw.js → handlebars-NEjHJ7o_.js} +1 -1
- package/client/dist/assets/{html-h2-wE1Lj.js → html-CA10zN5A.js} +1 -1
- package/client/dist/assets/{html.worker-CQP8QQsS.js → html.worker-DSJ9zmd7.js} +12 -12
- package/client/dist/assets/{htmlMode-Cc_ij7lW.js → htmlMode-89rPYiyq.js} +1 -1
- package/client/dist/assets/i18n-CgaRxpII.js +2 -0
- package/client/dist/assets/index-BflYQpWm.css +2 -0
- package/client/dist/assets/index-C1_-BTXy.js +72 -0
- package/client/dist/assets/integrations-mB-7zoyT.js +1 -0
- package/client/dist/assets/{javascript-C1q3xv6N.js → javascript-B1gDmwzS.js} +1 -1
- package/client/dist/assets/jira-CmKWERE0.js +1 -0
- package/client/dist/assets/jira-api-BgFIr8eD.js +1 -0
- package/client/dist/assets/job-time-BCL7wee9.js +1 -0
- package/client/dist/assets/jobs-B-sDHEay2.js +1 -0
- package/client/dist/assets/jobs-BCtGfgUA.js +1 -0
- package/client/dist/assets/jobs-BHR_EnDI.js +1 -0
- package/client/dist/assets/jobs-BMbZJjJJ.js +1 -0
- package/client/dist/assets/jobs-CVFD8rar.js +1 -0
- package/client/dist/assets/jobs-DoSaFzAa.js +1 -0
- package/client/dist/assets/jobs-DzSIR8V62.js +1 -0
- package/client/dist/assets/jobs-lk1_Dq1U.js +1 -0
- package/client/dist/assets/json.worker-Oa9UrkKE.js +58 -0
- package/client/dist/assets/{jsonMode-CeaCdEhr.js → jsonMode-xHLMfzhF.js} +1 -1
- package/client/dist/assets/jsx-runtime-zu2_FqZY.js +1 -0
- package/client/dist/assets/lib-C7Mhm-gT.js +7 -0
- package/client/dist/assets/lib-CGdyxIWg.js +29 -0
- package/client/dist/assets/{liquid-eFsVK0V-.js → liquid-BY6hCUXG.js} +1 -1
- package/client/dist/assets/loader-circle-DcygOQpC.js +1 -0
- package/client/dist/assets/loops-BzfXWEwO.js +1 -0
- package/client/dist/assets/{lspLanguageFeatures-DT3-bbhn.js → lspLanguageFeatures-ira2aEJh.js} +1 -1
- package/client/dist/assets/mcp-uDkXYu4L.js +1 -0
- package/client/dist/assets/{mdx-Fuwnh1cX.js → mdx-BNx0xr3N.js} +1 -1
- package/client/dist/assets/monaco.contribution-Bt92R3Vw.js +2 -0
- package/client/dist/assets/nav-myFaXRHD.js +1 -0
- package/client/dist/assets/pencil-C9RkrIPZ.js +1 -0
- package/client/dist/assets/play-DNlrawbS.js +1 -0
- package/client/dist/assets/plus-CsnjfkmX.js +1 -0
- package/client/dist/assets/preload-helper-Czpn1I53.js +1 -0
- package/client/dist/assets/{python-BgoEs6Cj.js → python-DLdbtmNw.js} +1 -1
- package/client/dist/assets/{razor-CM1sPMMq.js → razor-B9gdhAbR.js} +1 -1
- package/client/dist/assets/react-dom-DiWzBDP9.js +1 -0
- package/client/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
- package/client/dist/assets/save-28sIlCdr.js +1 -0
- package/client/dist/assets/search-Cq_gE3Ik.js +1 -0
- package/client/dist/assets/settings-B0ypw9uw.js +1 -0
- package/client/dist/assets/{settings-Bp24JHlv2.js → settings-B9ilOSYO.js} +1 -1
- package/client/dist/assets/{settings-Bx2ObkTR2.js → settings-BqlWHRHA.js} +1 -1
- package/client/dist/assets/{settings-C_T0-j9d.js → settings-D8dlqt4d.js} +1 -1
- package/client/dist/assets/{settings-DhaFKpcw2.js → settings-DAZqjX2a2.js} +1 -1
- package/client/dist/assets/{settings-B_v3zgJf.js → settings-DRh39v1S2.js} +1 -1
- package/client/dist/assets/{settings-BemR_e3F.js → settings-Mj1OJbfd2.js} +1 -1
- package/client/dist/assets/{settings-BvIwQ3A1.js → settings-lRReaSYm.js} +1 -1
- package/client/dist/assets/setup-CmK87LuS.js +1 -0
- package/client/dist/assets/sparkles-DrY8hb0X.js +1 -0
- package/client/dist/assets/specs-DII0C8gw.js +1 -0
- package/client/dist/assets/spending-C4p06nen.js +1 -0
- package/client/dist/assets/terminal-BFRZnMPP.js +1 -0
- package/client/dist/assets/tickets-B8BuAaj5.js +1 -0
- package/client/dist/assets/tickets-B_yh4qQk.js +1 -0
- package/client/dist/assets/tickets-Bs37scwY2.js +1 -0
- package/client/dist/assets/tickets-CFk2n2Or.js +1 -0
- package/client/dist/assets/tickets-DQp7JS2R2.js +1 -0
- package/client/dist/assets/tickets-D_yDquEw.js +1 -0
- package/client/dist/assets/tickets-DpmdE8tv2.js +1 -0
- package/client/dist/assets/tickets-pAUJkDTu.js +1 -0
- package/client/dist/assets/trash-2-BOU3WdZZ.js +1 -0
- package/client/dist/assets/triangle-alert-H9T4jAmh.js +1 -0
- package/client/dist/assets/{ts.worker-METxwbDZ.js → ts.worker-BtjBFNHX.js} +48 -33
- package/client/dist/assets/{tsMode-BmT8WogI.js → tsMode-DEjSThU9.js} +1 -1
- package/client/dist/assets/{typescript-CQrQPsoW.js → typescript-CRRnD2Ts.js} +1 -1
- package/client/dist/assets/upload-DYMjAQ6M.js +1 -0
- package/client/dist/assets/useBrowserCaptureSession-2OqX0vap.js +1 -0
- package/client/dist/assets/useDesktop-X8YB9xzv.js +1 -0
- package/client/dist/assets/useSharedWebSocket-DaPh7QBL.js +1 -0
- package/client/dist/assets/utils-BC4DHlz2.js +1 -0
- package/client/dist/assets/value-s-gzBeyF.js +1 -0
- package/client/dist/assets/{workers-U0UXyLUf.js → workers-uOo7WLaa.js} +1 -1
- package/client/dist/assets/x-CBMI9ejn.js +1 -0
- package/client/dist/assets/{xml-WRxJs8_I.js → xml-EDREH2X7.js} +1 -1
- package/client/dist/assets/{yaml-CjpSTjJU.js → yaml-BjaDVX1E.js} +1 -1
- package/client/dist/assets/zap-CHo3aCD1.js +1 -0
- package/client/dist/index.html +73 -32
- package/docs/guide/en/integrations/5-mcp-server.md +2 -2
- package/docs/internals/safe-pr-review-flow.md +190 -132
- package/docs/mcp.md +15 -5
- package/package.json +11 -7
- package/server/dist/active-pr-continuation.js +16 -1
- package/server/dist/agent-chat-manager.js +360 -181
- package/server/dist/agent-cwd-manager.js +52 -8
- package/server/dist/agent-generator.js +90 -48
- package/server/dist/agent-mcp-config.js +69 -36
- package/server/dist/agent-operator-prompt.js +3 -2
- package/server/dist/agent-refine-manager.js +47 -6
- package/server/dist/agent-tier.js +13 -11
- package/server/dist/artifact-registry.js +33 -2
- package/server/dist/auth.js +5 -4
- package/server/dist/browser-capture-manager.js +92 -29
- package/server/dist/chat-manager.js +302 -46
- package/server/dist/contract-refine-runner.js +19 -6
- package/server/dist/db.js +665 -8
- package/server/dist/desktop-router.js +1 -2
- package/server/dist/headroom-manager.js +1310 -121
- package/server/dist/headroom-routing.js +120 -2
- package/server/dist/index.js +48 -13
- package/server/dist/interactive-job-session.js +237 -82
- package/server/dist/jira/jira-adf.js +10 -0
- package/server/dist/jira/jira-db.js +15 -3
- package/server/dist/jira/jira-sync-manager.js +182 -13
- package/server/dist/job-listing.js +140 -0
- package/server/dist/job-spawn-idempotency.js +67 -0
- package/server/dist/loop-run-manager.js +508 -98
- package/server/dist/loop-runs-store.js +266 -13
- package/server/dist/mcp/agent-capability.js +71 -0
- package/server/dist/mcp/guide.js +5 -2
- package/server/dist/mcp/mcp-server.js +5 -10
- package/server/dist/mcp/mcp-token.js +5 -5
- package/server/dist/mcp/tools/jobs.js +20 -13
- package/server/dist/mcp/tools/types.js +20 -42
- package/server/dist/mobile/mobile-router.js +1 -1
- package/server/dist/pr-lifecycle.js +77 -0
- package/server/dist/pr-publisher.js +94 -27
- package/server/dist/process-admission.js +82 -0
- package/server/dist/project-registry.js +572 -174
- package/server/dist/project-router-git.js +13 -2
- package/server/dist/project-router-jobs.js +111 -55
- package/server/dist/project-router-tickets.js +32 -2
- package/server/dist/providers/claude-adapter.js +21 -13
- package/server/dist/queue-manager.js +2332 -623
- package/server/dist/rail-isolated-launch.js +1141 -280
- package/server/dist/rail-isolation.js +4 -2
- package/server/dist/rail-pr-decision.js +756 -270
- package/server/dist/rail-pr-delivery.js +2 -1
- package/server/dist/rail-pr-store.js +317 -18
- package/server/dist/rail-pr-ticket-effects.js +328 -0
- package/server/dist/rail-worktree-release.js +28 -6
- package/server/dist/rails-router.js +149 -112
- package/server/dist/rails-store.js +106 -3
- package/server/dist/ticket-store.js +23 -1
- package/server/dist/transient-children.js +13 -0
- package/server/dist/util/cli-prompt.js +42 -8
- package/server/dist/util/secure-token-file.js +84 -0
- package/server/dist/worktree-manager.js +70 -21
- package/client/dist/assets/ActivityFeedPage-Be-6L0Ld.js +0 -1
- package/client/dist/assets/AgentBrowserCapture-CpZ-dd8O.js +0 -1
- package/client/dist/assets/AgentIntegrationsModal-DO1pN_Ez.js +0 -1
- package/client/dist/assets/AgentModeCodePane-DLltTOqp.js +0 -2
- package/client/dist/assets/AgentModeJobsPane-Dp5YvmW0.js +0 -1
- package/client/dist/assets/AgentsPage-ehHuVUds.js +0 -86
- package/client/dist/assets/AnalyticsPage-C4Ik95FX.js +0 -1
- package/client/dist/assets/BarChart-DVZgrhJd.js +0 -33
- package/client/dist/assets/CodePage-D4OCMfxL.js +0 -2
- package/client/dist/assets/DesktopAnalyticsPage-2Xf-52x2.js +0 -1
- package/client/dist/assets/DocsDialog-CHihLjWd.js +0 -11
- package/client/dist/assets/DocsPage-1vEk7XbH.js +0 -11
- package/client/dist/assets/ExportDropdown-DLHFQxVn.js +0 -1
- package/client/dist/assets/IntegrationsPage-CCb2YuyJ.js +0 -1
- package/client/dist/assets/InteractiveJobComposer-CxJJEnjw.js +0 -19
- package/client/dist/assets/JobDetailModal-CJI7qRkm.js +0 -1
- package/client/dist/assets/JobDetailPage-DwA9bbwx.js +0 -1
- package/client/dist/assets/JobsPage-BDIyFfd5.js +0 -1
- package/client/dist/assets/LoopBuilderPage-CpBaW59t.js +0 -7
- package/client/dist/assets/LoopPreviewModal-CwpKcv0Y.js +0 -1
- package/client/dist/assets/LoopsPage-BO0Pa8oz.js +0 -1
- package/client/dist/assets/PluginsPage-BBGTBpGh.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-M9zGQo0l.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-eBI0zL5P.js +0 -1
- package/client/dist/assets/activity-Dbl71S-E.js +0 -1
- package/client/dist/assets/addon-image-CwoZj17F.js +0 -1
- package/client/dist/assets/addon-ligatures-CWDrED80.js +0 -2
- package/client/dist/assets/addspec-DrXqP8ip.js +0 -1
- package/client/dist/assets/agent-BEXYxDbs.js +0 -1
- package/client/dist/assets/agent-BoXSzaBk2.js +0 -1
- package/client/dist/assets/agent-C2-rROL52.js +0 -1
- package/client/dist/assets/agent-CeRTdGT12.js +0 -1
- package/client/dist/assets/agent-DZ8zTrQT.js +0 -1
- package/client/dist/assets/agent-DqyzT33X.js +0 -1
- package/client/dist/assets/agent-fQI_6tsA.js +0 -1
- package/client/dist/assets/agent-tJdAobaM.js +0 -1
- package/client/dist/assets/agents-CGDn_3kB.js +0 -1
- package/client/dist/assets/agentstudio-Dxe_94PK.js +0 -1
- package/client/dist/assets/aiedit-DrfHQnlz.js +0 -1
- package/client/dist/assets/analytics-CxDYcBl9.js +0 -1
- package/client/dist/assets/attachments-DvxQbBTC.js +0 -1
- package/client/dist/assets/brain-DecvjjPU.js +0 -1
- package/client/dist/assets/browser-DM8G151q.js +0 -1
- package/client/dist/assets/chat-0dg5hOo_.js +0 -1
- package/client/dist/assets/chunk-BNv3lrIs.js +0 -1
- package/client/dist/assets/code-B62fClk-.js +0 -1
- package/client/dist/assets/commands-DCJ-R9E4.js +0 -1
- package/client/dist/assets/common-BfQD173j.js +0 -1
- package/client/dist/assets/common-CF8iGXrG.js +0 -1
- package/client/dist/assets/common-Cfmwcrl52.js +0 -1
- package/client/dist/assets/common-D2cimsul.js +0 -1
- package/client/dist/assets/common-DH7fjyL1.js +0 -1
- package/client/dist/assets/common-DXrmj6WD.js +0 -1
- package/client/dist/assets/common-DZbXlmq72.js +0 -1
- package/client/dist/assets/common-DtXmzX2o2.js +0 -1
- package/client/dist/assets/dashboard-5C2FOZQX.js +0 -1
- package/client/dist/assets/dashboard-B6iQ-IL_.js +0 -1
- package/client/dist/assets/dashboard-BFfnCtq52.js +0 -1
- package/client/dist/assets/dashboard-BIC8KtRf2.js +0 -1
- package/client/dist/assets/dashboard-CEgg9NAr.js +0 -1
- package/client/dist/assets/dashboard-CiOyDh9L.js +0 -1
- package/client/dist/assets/dashboard-D6x5OnNj2.js +0 -1
- package/client/dist/assets/dashboard-DBuLfWo9.js +0 -1
- package/client/dist/assets/editor.api2-C3B0tp2x.js +0 -872
- package/client/dist/assets/editor.worker-Bd9IXS8d.js +0 -26
- package/client/dist/assets/explore-_XyU5e7R.js +0 -1
- package/client/dist/assets/index-BVbgKXUu.css +0 -2
- package/client/dist/assets/index-OBDI7bHm.js +0 -158
- package/client/dist/assets/integrations-By80EBkf.js +0 -1
- package/client/dist/assets/jira-DeIjwCK3.js +0 -1
- package/client/dist/assets/jobs-BFIdeDTw.js +0 -1
- package/client/dist/assets/jobs-BJ-Gcao22.js +0 -1
- package/client/dist/assets/jobs-DAGiPVIS2.js +0 -1
- package/client/dist/assets/jobs-DAU8C_tZ.js +0 -1
- package/client/dist/assets/jobs-Da0GaaSc.js +0 -1
- package/client/dist/assets/jobs-DrYmsKy5.js +0 -1
- package/client/dist/assets/jobs-P3unxtxo2.js +0 -1
- package/client/dist/assets/jobs-p360zdf1.js +0 -1
- package/client/dist/assets/json.worker-DzV-CpCQ.js +0 -58
- package/client/dist/assets/lib-C5ZxrPSR.js +0 -7
- package/client/dist/assets/loops-CO6q75W8.js +0 -1
- package/client/dist/assets/mcp-HwBbQDk0.js +0 -1
- package/client/dist/assets/monaco.contribution-Desq7oq4.js +0 -2
- package/client/dist/assets/nav-BTg8s-cD.js +0 -1
- package/client/dist/assets/preload-helper-DSXbuxSR.js +0 -1
- package/client/dist/assets/settings-BYCMtxOz.js +0 -1
- package/client/dist/assets/setup-D2CmgAro.js +0 -1
- package/client/dist/assets/specs-PGIOzMtc.js +0 -1
- package/client/dist/assets/terminal-CFt56A5f.js +0 -1
- package/client/dist/assets/tickets-BHv3ewvq.js +0 -1
- package/client/dist/assets/tickets-BIxU86j12.js +0 -1
- package/client/dist/assets/tickets-C2BhwzwR.js +0 -1
- package/client/dist/assets/tickets-D1IeX2EW.js +0 -1
- package/client/dist/assets/tickets-DZut8Ryt.js +0 -1
- package/client/dist/assets/tickets-LfK6LzKl2.js +0 -1
- package/client/dist/assets/tickets-dQfsc7Ph.js +0 -1
- package/client/dist/assets/tickets-sVun0I6v.js +0 -1
- package/client/dist/assets/upload-lgjKJgrl.js +0 -1
- package/client/dist/assets/value-Bc0_jlJA.js +0 -1
- /package/client/dist/assets/{abap-D0E4FfVW.js → abap-08VXUWAP.js} +0 -0
- /package/client/dist/assets/{activity-BbWiDfn-2.js → activity-B-rp4h_v.js} +0 -0
- /package/client/dist/assets/{activity-DvECTYGt.js → activity-C6kJpm9q2.js} +0 -0
- /package/client/dist/assets/{activity-D3Ic-HTS.js → activity-CGx4kb_j.js} +0 -0
- /package/client/dist/assets/{activity-BZZlEG3a.js → activity-CnoX2bH7.js} +0 -0
- /package/client/dist/assets/{activity-DtzRy92x.js → activity-DAyekdlt2.js} +0 -0
- /package/client/dist/assets/{activity-FleOlK0l2.js → activity-DCxtpT7j.js} +0 -0
- /package/client/dist/assets/{activity-DFbvNqhE2.js → activity-JzwRaWPD.js} +0 -0
- /package/client/dist/assets/{addspec-CFxGvmJR2.js → addspec-BXjvkh5q.js} +0 -0
- /package/client/dist/assets/{addspec-NBbcTbLc.js → addspec-C4bwrmpi.js} +0 -0
- /package/client/dist/assets/{addspec-BKrH2Ucz.js → addspec-CArHXUDM.js} +0 -0
- /package/client/dist/assets/{addspec-CR8MB5Fr2.js → addspec-DTKJcXiR.js} +0 -0
- /package/client/dist/assets/{addspec-B_LQMHW3.js → addspec-DbNBbrha2.js} +0 -0
- /package/client/dist/assets/{addspec-DaA-CbTt.js → addspec-htHGZHOe2.js} +0 -0
- /package/client/dist/assets/{addspec-Bw_YQwo62.js → addspec-lr_LP6jk.js} +0 -0
- /package/client/dist/assets/{agents-BHgn--3j.js → agents-6ZOJXWVk2.js} +0 -0
- /package/client/dist/assets/{agents-VsyFhGOS2.js → agents-BZ0XQKjg.js} +0 -0
- /package/client/dist/assets/{agents-HFCqQH0Z.js → agents-BqWklnHR.js} +0 -0
- /package/client/dist/assets/{agents-B_qGaB0F.js → agents-Bz-thHkB2.js} +0 -0
- /package/client/dist/assets/{agents-CP8_ezYG.js → agents-CJclElx6.js} +0 -0
- /package/client/dist/assets/{agents-B9pFSJQI2.js → agents-D_l9L0VA.js} +0 -0
- /package/client/dist/assets/{agents-CV-_xBvX2.js → agents-u_C0jPB5.js} +0 -0
- /package/client/dist/assets/{agentstudio-BEp7Sb46.js → agentstudio-BF19hbXj.js} +0 -0
- /package/client/dist/assets/{agentstudio-Br3WD7Xs.js → agentstudio-BLGvxWBx2.js} +0 -0
- /package/client/dist/assets/{agentstudio-BOjG6tgJ.js → agentstudio-D9UKiWTj2.js} +0 -0
- /package/client/dist/assets/{agentstudio-D2A5peWV2.js → agentstudio-Drs37nIM.js} +0 -0
- /package/client/dist/assets/{agentstudio-CuTt3ZGe2.js → agentstudio-nEnKkcXM.js} +0 -0
- /package/client/dist/assets/{agentstudio-RsxnZtUA.js → agentstudio-pyFcSBKy.js} +0 -0
- /package/client/dist/assets/{agentstudio-RfZavULt2.js → agentstudio-zfTzQh3U.js} +0 -0
- /package/client/dist/assets/{aiedit-DnBzjlVz2.js → aiedit-B0KUbpB6.js} +0 -0
- /package/client/dist/assets/{aiedit-D0Syl-mC.js → aiedit-BoG24nlg2.js} +0 -0
- /package/client/dist/assets/{aiedit-CcugGPbS.js → aiedit-CjlSRQVP.js} +0 -0
- /package/client/dist/assets/{aiedit-DrIjSojo.js → aiedit-DCjA7jLJ.js} +0 -0
- /package/client/dist/assets/{aiedit-CV520D4W2.js → aiedit-DNXxq_Dr.js} +0 -0
- /package/client/dist/assets/{aiedit-26p5A_HY2.js → aiedit-DQ-0_pvE.js} +0 -0
- /package/client/dist/assets/{aiedit-a-Z-g5iC.js → aiedit-olnv3QSt2.js} +0 -0
- /package/client/dist/assets/{analytics-DEe5BMz8.js → analytics-BC7mwR4s.js} +0 -0
- /package/client/dist/assets/{analytics-4HvXb0Vn2.js → analytics-BiNg8edP.js} +0 -0
- /package/client/dist/assets/{analytics-CpSTNfui.js → analytics-C0s_T2GN.js} +0 -0
- /package/client/dist/assets/{analytics-4-eskbtX.js → analytics-CdsAPAwZ2.js} +0 -0
- /package/client/dist/assets/{analytics-Bpe41fnX2.js → analytics-Cr1_q-lC.js} +0 -0
- /package/client/dist/assets/{analytics-DcOITHla2.js → analytics-IEsKZvpW2.js} +0 -0
- /package/client/dist/assets/{analytics-Bd9rHGjV.js → analytics-SRPf84OT.js} +0 -0
- /package/client/dist/assets/{apex-D_X_8J4d.js → apex-BWPQTe0t.js} +0 -0
- /package/client/dist/assets/{atom-one-dark-BMDPFwRZ.js → atom-one-dark-qiGhVQxg.js} +0 -0
- /package/client/dist/assets/{attachments-CgOQ9K-6.js → attachments-D0wXXt9T2.js} +0 -0
- /package/client/dist/assets/{attachments-DlEQu56g2.js → attachments-DenIjuVI.js} +0 -0
- /package/client/dist/assets/{attachments-CA2f3qL3.js → attachments-DhO7LPfy.js} +0 -0
- /package/client/dist/assets/{attachments-D2jwJXQ42.js → attachments-DoH5w0x4.js} +0 -0
- /package/client/dist/assets/{attachments-CHDbhKeH.js → attachments-Q9yNtiEM.js} +0 -0
- /package/client/dist/assets/{attachments-CKAY5aYG2.js → attachments-V_WZAYXx2.js} +0 -0
- /package/client/dist/assets/{attachments-jVdKzAXn.js → attachments-eaeScpjM.js} +0 -0
- /package/client/dist/assets/{auth-DpZq5p1e.js → auth-D_5bQv5W.js} +0 -0
- /package/client/dist/assets/{azcli-PZLnZ3jH.js → azcli-Bc_sGQ0U.js} +0 -0
- /package/client/dist/assets/{bat-KlBOxpO4.js → bat-i0X4ZdIN.js} +0 -0
- /package/client/dist/assets/{bicep-CgG9oF3V.js → bicep-B5-_aFwp.js} +0 -0
- /package/client/dist/assets/{browser-Cl-FwPXs.js → browser-C25DkQiO.js} +0 -0
- /package/client/dist/assets/{browser-JsiohNmW.js → browser-CiJ7-L32.js} +0 -0
- /package/client/dist/assets/{browser-BbJ_q_OT2.js → browser-CvgDySd9.js} +0 -0
- /package/client/dist/assets/{browser-BQFDxrRq.js → browser-CyR1Kp3m2.js} +0 -0
- /package/client/dist/assets/{browser-Do2jf8_N.js → browser-DwZljcRh2.js} +0 -0
- /package/client/dist/assets/{browser-C4VJ5CW12.js → browser-DxP-alBK.js} +0 -0
- /package/client/dist/assets/{browser-kA31eYhu2.js → browser-rRCwi7Y7.js} +0 -0
- /package/client/dist/assets/{cameligo-6R45j6Ph.js → cameligo-DMUM7wLl.js} +0 -0
- /package/client/dist/assets/{chat-BalviUAD.js → chat-2rIB8HhT.js} +0 -0
- /package/client/dist/assets/{chat-Ds8GvCnv.js → chat-BR8oe53x2.js} +0 -0
- /package/client/dist/assets/{chat-D5xEtsf3.js → chat-Bua03tty.js} +0 -0
- /package/client/dist/assets/{chat-SaG-ng1x2.js → chat-CZpAQan1.js} +0 -0
- /package/client/dist/assets/{chat-CJddjN3D2.js → chat-CdY5SGvS.js} +0 -0
- /package/client/dist/assets/{chat-n43nZGvn.js → chat-DZyu3ImY2.js} +0 -0
- /package/client/dist/assets/{chat-BMWD_Rx12.js → chat-D_I7nU5K.js} +0 -0
- /package/client/dist/assets/{clojure-CLAAMO7J.js → clojure-Cm7r79vr.js} +0 -0
- /package/client/dist/assets/{clsx-CNmW0Nip.js → clsx-CjueKrWZ.js} +0 -0
- /package/client/dist/assets/{code-C9U6M5-e2.js → code-76gS0IdL.js} +0 -0
- /package/client/dist/assets/{code-BotxM43N2.js → code-C1VwxlML.js} +0 -0
- /package/client/dist/assets/{code-HDK4P6Rx.js → code-CnMZyJpr.js} +0 -0
- /package/client/dist/assets/{code-DUe1Bouz.js → code-D20ef9Cf2.js} +0 -0
- /package/client/dist/assets/{code-Bit_z2Xd2.js → code-DdOXaWRY.js} +0 -0
- /package/client/dist/assets/{code-F_KjccGf.js → code-Duohuf9l.js} +0 -0
- /package/client/dist/assets/{code-CIPmDEd0.js → code-geHmknB92.js} +0 -0
- /package/client/dist/assets/{coffee-AruSygo-.js → coffee-Ba7i2nA0.js} +0 -0
- /package/client/dist/assets/{commands-BFQZc9AG.js → commands-B9RZO4qS.js} +0 -0
- /package/client/dist/assets/{commands-BMkC5-ki.js → commands-BEwbAjtD2.js} +0 -0
- /package/client/dist/assets/{commands-KBbhsnw8.js → commands-Bbxu8kLU.js} +0 -0
- /package/client/dist/assets/{commands-CzFSoIiq2.js → commands-CDU3qv68.js} +0 -0
- /package/client/dist/assets/{commands-CWX9WmDX2.js → commands-CzezgtQj.js} +0 -0
- /package/client/dist/assets/{commands-BllkJauO.js → commands-DTQBF_q52.js} +0 -0
- /package/client/dist/assets/{commands-cKTaLwwV2.js → commands-hOtKuOXc.js} +0 -0
- /package/client/dist/assets/{cpp-DEE5r4Pw.js → cpp-C7h46wYY.js} +0 -0
- /package/client/dist/assets/{csharp-BVXJUvbK.js → csharp-BKxtCVv1.js} +0 -0
- /package/client/dist/assets/{csp-cXOF0JoV.js → csp-bTuwJoIa.js} +0 -0
- /package/client/dist/assets/{css-C_zQuAoy.js → css-DIMkf-bt.js} +0 -0
- /package/client/dist/assets/{cypher-t95m_Q-O.js → cypher-CVaqCwHa.js} +0 -0
- /package/client/dist/assets/{dart-B4r1Tg-e.js → dart-onAF5SnQ.js} +0 -0
- /package/client/dist/assets/{dockerfile-6mt7zHQw.js → dockerfile-DZFCIeNp.js} +0 -0
- /package/client/dist/assets/{ecl-DEY_Fz_Q.js → ecl-D05T4iGw.js} +0 -0
- /package/client/dist/assets/{elixir-R6-q1c5t.js → elixir-6RTg0lbw.js} +0 -0
- /package/client/dist/assets/{explore-CAc8Qzu32.js → explore-BG99VGpL.js} +0 -0
- /package/client/dist/assets/{explore-BO_OinBD.js → explore-C0TjprJW2.js} +0 -0
- /package/client/dist/assets/{explore-Bhy7WWXv.js → explore-C2dgEo7q.js} +0 -0
- /package/client/dist/assets/{explore-ELbrSZyQ2.js → explore-C8NDHbob.js} +0 -0
- /package/client/dist/assets/{explore-DW_YTkQh.js → explore-CWWgzQGR.js} +0 -0
- /package/client/dist/assets/{explore-DCZL9gRN2.js → explore-CcQXpdtS.js} +0 -0
- /package/client/dist/assets/{explore-BEpIs343.js → explore-DsXAgnmJ2.js} +0 -0
- /package/client/dist/assets/{flow9-CNQvHBOt.js → flow9-C5_-GSwl.js} +0 -0
- /package/client/dist/assets/{format-command-Db1viey1.js → format-command-Dfa1o2d-.js} +0 -0
- /package/client/dist/assets/{fsharp-vPZkFXwv.js → fsharp-C8Ef5oNN.js} +0 -0
- /package/client/dist/assets/{go-KUzBMYJ_.js → go-C-y9NEjX.js} +0 -0
- /package/client/dist/assets/{graphql-C3W0rCsD.js → graphql-fmXr3nnJ.js} +0 -0
- /package/client/dist/assets/{hcl-BOOMFSNX.js → hcl-CpzslTdj.js} +0 -0
- /package/client/dist/assets/{ini-CFat1WJr.js → ini-sBoK_t0W.js} +0 -0
- /package/client/dist/assets/{integrations-CG2dp3Kd.js → integrations-CH0zy1Mw2.js} +0 -0
- /package/client/dist/assets/{integrations-CUNe3t9l2.js → integrations-CIAjhd7L.js} +0 -0
- /package/client/dist/assets/{integrations-CWjh5VRk.js → integrations-CZdwOe8A.js} +0 -0
- /package/client/dist/assets/{integrations-RJfzXkPx2.js → integrations-Ct7omMld.js} +0 -0
- /package/client/dist/assets/{integrations-CAjq5tdW2.js → integrations-D6MSxy3-.js} +0 -0
- /package/client/dist/assets/{integrations-JOHSCvB3.js → integrations-DbZa-Zyc.js} +0 -0
- /package/client/dist/assets/{integrations-CP_aiV_8.js → integrations-b8pH-vfl2.js} +0 -0
- /package/client/dist/assets/{java-Dee-CNAM.js → java-BEtHBSE6.js} +0 -0
- /package/client/dist/assets/{jira-CQ7mrZde.js → jira-BySfUuQZ.js} +0 -0
- /package/client/dist/assets/{jira-DIRkZk9U.js → jira-Byw2C0F8.js} +0 -0
- /package/client/dist/assets/{jira-C5UjxHE4.js → jira-CNeYi06w2.js} +0 -0
- /package/client/dist/assets/{jira-ZdKb-50F2.js → jira-D11gPhxz.js} +0 -0
- /package/client/dist/assets/{jira-DTYu3hJi2.js → jira-D38Gj7AT.js} +0 -0
- /package/client/dist/assets/{jira-B5wszJ1-2.js → jira-gAvOyije.js} +0 -0
- /package/client/dist/assets/{jira-DtZpokjJ.js → jira-pRaL7JQo2.js} +0 -0
- /package/client/dist/assets/{julia-CGNlLYuU.js → julia-Bri6UV-V.js} +0 -0
- /package/client/dist/assets/{kotlin-CY7lhknJ.js → kotlin-BOotOW0E.js} +0 -0
- /package/client/dist/assets/{less-D0KN7hfJ.js → less-B9JPFI3C.js} +0 -0
- /package/client/dist/assets/{lexon-CuRJufPs.js → lexon-CfSJPG6W.js} +0 -0
- /package/client/dist/assets/{loops-DKzYFcq6.js → loops-CPpgMapU.js} +0 -0
- /package/client/dist/assets/{loops-Du-bNVpc2.js → loops-CWWbKuVL.js} +0 -0
- /package/client/dist/assets/{loops-DDs4KPu_.js → loops-Crc9It8o2.js} +0 -0
- /package/client/dist/assets/{loops-Bi4ywYGn.js → loops-DH2hZcbK2.js} +0 -0
- /package/client/dist/assets/{loops-DvGbSfxw2.js → loops-DS5TmvIU2.js} +0 -0
- /package/client/dist/assets/{loops-D3wdUkZV.js → loops-P2f0cN8-.js} +0 -0
- /package/client/dist/assets/{loops-BjK8lmoZ2.js → loops-fJV-9hH7.js} +0 -0
- /package/client/dist/assets/{lua-DHvH62Zf.js → lua-CsQS60Ue.js} +0 -0
- /package/client/dist/assets/{m3-tlthQ8Fo.js → m3-D-oSqn_W.js} +0 -0
- /package/client/dist/assets/{markdown-Dbx1LgUZ.js → markdown-Cimd5fb3.js} +0 -0
- /package/client/dist/assets/{mcp-DfmzoT5t.js → mcp-Czd_iyp02.js} +0 -0
- /package/client/dist/assets/{mcp-BG-OCJca2.js → mcp-D2pc5GGx.js} +0 -0
- /package/client/dist/assets/{mcp-CrWdq5db.js → mcp-D4ZjtIx32.js} +0 -0
- /package/client/dist/assets/{mcp-CbJ04oFS2.js → mcp-DIfBUv2D2.js} +0 -0
- /package/client/dist/assets/{mcp-Dd844F5_.js → mcp-DsTwmjST.js} +0 -0
- /package/client/dist/assets/{mcp-zSJ2TsJj.js → mcp-SMkn8boG.js} +0 -0
- /package/client/dist/assets/{mcp-DyULurYS2.js → mcp-fSfiVYAc.js} +0 -0
- /package/client/dist/assets/{mips-D_O3IUz_.js → mips-CIPQ_RoX.js} +0 -0
- /package/client/dist/assets/{msdax-C_ZmCnRt.js → msdax-DauUninz.js} +0 -0
- /package/client/dist/assets/{mysql-C-dCEYSX.js → mysql-SOo6toE5.js} +0 -0
- /package/client/dist/assets/{nav-DUuw9VIU2.js → nav-BRJBxaGt2.js} +0 -0
- /package/client/dist/assets/{nav-D0Erv9ZJ2.js → nav-CAGKv3_F.js} +0 -0
- /package/client/dist/assets/{nav-BY_4EWRv.js → nav-CNskRJKQ2.js} +0 -0
- /package/client/dist/assets/{nav-CVXtv0wX2.js → nav-DY93irBL.js} +0 -0
- /package/client/dist/assets/{nav-B2_ToNqS.js → nav-DhjvYgqt.js} +0 -0
- /package/client/dist/assets/{nav-S4HM94vW.js → nav-Gb-r4wop.js} +0 -0
- /package/client/dist/assets/{nav-BAMkVEId.js → nav-TvumAFD22.js} +0 -0
- /package/client/dist/assets/{objective-c-DZY9Aqxd.js → objective-c-FvmIjYaQ.js} +0 -0
- /package/client/dist/assets/{pascal-BVHLXoor.js → pascal-DrH0SRf2.js} +0 -0
- /package/client/dist/assets/{pascaligo-XdG_6u3k.js → pascaligo-D-ptJ9y-.js} +0 -0
- /package/client/dist/assets/{perl-b9QV0BcD.js → perl-oz_6vUea.js} +0 -0
- /package/client/dist/assets/{pgsql-Du5FDOgT.js → pgsql-DTj74zXo.js} +0 -0
- /package/client/dist/assets/{php-WJD0z2Z_.js → php-nr791fC2.js} +0 -0
- /package/client/dist/assets/{pla-CbciTf2w.js → pla-CopQ2nXW.js} +0 -0
- /package/client/dist/assets/{postiats-C1QxmvVq.js → postiats-43DmfD33.js} +0 -0
- /package/client/dist/assets/{powerquery-BEYDhPLZ.js → powerquery-D3hlyOfw.js} +0 -0
- /package/client/dist/assets/{powershell-CfaYw4XL.js → powershell-DmHpPYUd.js} +0 -0
- /package/client/dist/assets/{protobuf-pwZEDOYa.js → protobuf-C531GsRP.js} +0 -0
- /package/client/dist/assets/{pug-5ftqSPVe.js → pug-Z5eAx3Zn.js} +0 -0
- /package/client/dist/assets/{qsharp-uI6qZMq4.js → qsharp-DkqhCAOL.js} +0 -0
- /package/client/dist/assets/{r-BK54P1EG.js → r-BwWrilGY.js} +0 -0
- /package/client/dist/assets/{redis-DI0yd7kN.js → redis-ClamHrr6.js} +0 -0
- /package/client/dist/assets/{redshift-Dov26eyI.js → redshift-DT7zqm-g.js} +0 -0
- /package/client/dist/assets/{restructuredtext-QqJ_1dC-.js → restructuredtext-BYgofb2h.js} +0 -0
- /package/client/dist/assets/{ruby-5WjveeVb.js → ruby-DezsRK8O.js} +0 -0
- /package/client/dist/assets/{rust-BzVSfqFH.js → rust-DdL9SqIa.js} +0 -0
- /package/client/dist/assets/{sb-DMIUfT-3.js → sb-CcwsVR0C.js} +0 -0
- /package/client/dist/assets/{scala-CSKA7lqt.js → scala-DHpiXF5c.js} +0 -0
- /package/client/dist/assets/{scheme-CojOP2Qc.js → scheme-BeGwcela.js} +0 -0
- /package/client/dist/assets/{scss-DoBZGJG6.js → scss-gp-XZpBa.js} +0 -0
- /package/client/dist/assets/{setup-JeBwoXoM.js → setup-CGZjy2IF2.js} +0 -0
- /package/client/dist/assets/{setup-1vN48B-m2.js → setup-CXa0Sx16.js} +0 -0
- /package/client/dist/assets/{setup-BmJ0Kx16.js → setup-D2ktKKMF2.js} +0 -0
- /package/client/dist/assets/{setup-T_ApeQDV2.js → setup-DG2H7ha5.js} +0 -0
- /package/client/dist/assets/{setup-DQWsu2TR.js → setup-DK5bHDUq2.js} +0 -0
- /package/client/dist/assets/{setup-q0wRHUp1.js → setup-DrWlIQTZ.js} +0 -0
- /package/client/dist/assets/{setup-mXnzww4f.js → setup-rzHUVgAu.js} +0 -0
- /package/client/dist/assets/{shell-YOaE4udl.js → shell-CC2rA5mh.js} +0 -0
- /package/client/dist/assets/{solidity-l3jSyVLu.js → solidity-BEEn4gHE.js} +0 -0
- /package/client/dist/assets/{sophia-BhSGTaQJ.js → sophia-CRfGWb83.js} +0 -0
- /package/client/dist/assets/{sparql-qhk6QD9w.js → sparql-D_Lu-MrJ.js} +0 -0
- /package/client/dist/assets/{specs-BGRKhM8t.js → specs-BcyxaCwf2.js} +0 -0
- /package/client/dist/assets/{specs-GkiL-snY.js → specs-C1q9geAi.js} +0 -0
- /package/client/dist/assets/{specs-DbtIzV8a.js → specs-CLZKysq-2.js} +0 -0
- /package/client/dist/assets/{specs-Ce5y2iFc2.js → specs-DZMS9o54.js} +0 -0
- /package/client/dist/assets/{specs-CT8exGOy2.js → specs-Dm6zUI-R.js} +0 -0
- /package/client/dist/assets/{specs-C6J2zrLM.js → specs-V3TvhKLX.js} +0 -0
- /package/client/dist/assets/{specs-DZDoZsDq.js → specs-dV3Mq5Mu2.js} +0 -0
- /package/client/dist/assets/{sql-DoO3y21-.js → sql-NEE52Syq.js} +0 -0
- /package/client/dist/assets/{st-ChZAY8oG.js → st-DbInun42.js} +0 -0
- /package/client/dist/assets/{swift-D290Tr7_.js → swift-Bxkupp3x.js} +0 -0
- /package/client/dist/assets/{systemverilog-DsxzgJ-o.js → systemverilog-Bz4Y3fRF.js} +0 -0
- /package/client/dist/assets/{tcl-BKDUHAAR.js → tcl-DISqw1ZD.js} +0 -0
- /package/client/dist/assets/{terminal-BTpE7iki.js → terminal-BZiIu3rf.js} +0 -0
- /package/client/dist/assets/{terminal-DEyt0prF.js → terminal-C2NAd7BW2.js} +0 -0
- /package/client/dist/assets/{terminal-a6Uq8B0p.js → terminal-IahE4LW92.js} +0 -0
- /package/client/dist/assets/{terminal-DDk_bTw0.js → terminal-QpXZU2Bn2.js} +0 -0
- /package/client/dist/assets/{terminal-BNSg2lR7.js → terminal-ScjyXNxQ.js} +0 -0
- /package/client/dist/assets/{terminal-Cvabyzm42.js → terminal-d7GadXbN.js} +0 -0
- /package/client/dist/assets/{terminal-D0z12_sJ2.js → terminal-tITa81iz.js} +0 -0
- /package/client/dist/assets/{twig-UpZQaM8G.js → twig-De2hgUGE.js} +0 -0
- /package/client/dist/assets/{typespec-DzaKvN8i.js → typespec-B8J7ngcE.js} +0 -0
- /package/client/dist/assets/{vb-CZpbb7tk.js → vb-DV3o63ZY.js} +0 -0
- /package/client/dist/assets/{wgsl-CNt3OIvl.js → wgsl-DpFanUEy.js} +0 -0
package/server/dist/db.js
CHANGED
|
@@ -3,9 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.WORKTREE_ENV_NAME_RE = exports.DEFAULT_FREESTYLE_PRE_PROMPT = void 0;
|
|
6
|
+
exports.WORKTREE_ENV_NAME_RE = exports.DEFAULT_FREESTYLE_PRE_PROMPT = exports.JobRecoveryPendingError = void 0;
|
|
7
7
|
exports.initDb = initDb;
|
|
8
8
|
exports.createJob = createJob;
|
|
9
|
+
exports.upsertQueuedJob = upsertQueuedJob;
|
|
10
|
+
exports.deleteQueuedJob = deleteQueuedJob;
|
|
9
11
|
exports.markJobInteractive = markJobInteractive;
|
|
10
12
|
exports.accumulateInteractiveTurn = accumulateInteractiveTurn;
|
|
11
13
|
exports.finalizeInteractiveJob = finalizeInteractiveJob;
|
|
@@ -58,6 +60,63 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
58
60
|
const path_1 = __importDefault(require("path"));
|
|
59
61
|
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
60
62
|
const secure_fs_1 = require("./util/secure-fs");
|
|
63
|
+
/** Backfill only terminal Safe-PR rows whose ticket ownership is unambiguous.
|
|
64
|
+
* Eligibility is intentionally deferred to the outbox drainer, which freezes
|
|
65
|
+
* only candidates still parked at on_review in the external ticket JSON. */
|
|
66
|
+
function backfillTerminalRailPrTicketEffects(db) {
|
|
67
|
+
const terminalRows = db.prepare(`
|
|
68
|
+
SELECT id, ticket_ids, run_ids, decision, is_continuation,
|
|
69
|
+
supersedes_delivery_id, pr_url
|
|
70
|
+
FROM rail_pr_deliveries
|
|
71
|
+
WHERE decision = 'merged'
|
|
72
|
+
OR (decision = 'discarded' AND is_continuation = 0
|
|
73
|
+
AND supersedes_delivery_id IS NULL AND pr_url IS NULL)
|
|
74
|
+
`).all();
|
|
75
|
+
const insertEffect = db.prepare(`
|
|
76
|
+
INSERT OR IGNORE INTO rail_pr_ticket_effects (
|
|
77
|
+
delivery_id, ticket_ids, causal_owners, target_status, jira_action, pr_url
|
|
78
|
+
) VALUES (?, ?, ?, ?, ?, ?)
|
|
79
|
+
`);
|
|
80
|
+
const currentOwner = db.prepare(`
|
|
81
|
+
SELECT owner_id FROM ticket_outcome_ownership WHERE ticket_id = ?
|
|
82
|
+
`);
|
|
83
|
+
for (const row of terminalRows) {
|
|
84
|
+
let ticketIds = [];
|
|
85
|
+
let runIds = [];
|
|
86
|
+
try {
|
|
87
|
+
const parsed = JSON.parse(row.ticket_ids);
|
|
88
|
+
if (Array.isArray(parsed)) {
|
|
89
|
+
ticketIds = [...new Set(parsed.filter((id) => Number.isSafeInteger(id) && id > 0))];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch { /* malformed historical evidence is not safe to act on */ }
|
|
93
|
+
try {
|
|
94
|
+
const parsed = JSON.parse(row.run_ids);
|
|
95
|
+
if (Array.isArray(parsed)) {
|
|
96
|
+
runIds = [...new Set(parsed.filter((id) => typeof id === 'string' && id.length > 0))];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch { /* absent causal evidence means the historical effect is unsafe */ }
|
|
100
|
+
if (ticketIds.length === 0 || runIds.length === 0)
|
|
101
|
+
continue;
|
|
102
|
+
const allowedOwners = new Set(runIds);
|
|
103
|
+
const causalOwners = {};
|
|
104
|
+
ticketIds = ticketIds.filter((ticketId) => {
|
|
105
|
+
const owner = currentOwner.get(ticketId);
|
|
106
|
+
if (!owner || !allowedOwners.has(owner.owner_id))
|
|
107
|
+
return false;
|
|
108
|
+
causalOwners[String(ticketId)] = owner.owner_id;
|
|
109
|
+
return true;
|
|
110
|
+
});
|
|
111
|
+
if (ticketIds.length === 0)
|
|
112
|
+
continue;
|
|
113
|
+
const merged = row.decision === 'merged';
|
|
114
|
+
insertEffect.run(row.id, JSON.stringify(ticketIds), JSON.stringify(causalOwners), merged ? 'done' : 'todo',
|
|
115
|
+
// A v49 fresh discard has lost whether it meant Refine or a real
|
|
116
|
+
// discard. Recover the backlog status without inventing either cause.
|
|
117
|
+
merged ? 'merged' : 'backlog', merged ? row.pr_url : null);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
61
120
|
const MIGRATIONS = [
|
|
62
121
|
// Migration 1: initial schema
|
|
63
122
|
(db) => {
|
|
@@ -802,6 +861,550 @@ const MIGRATIONS = [
|
|
|
802
861
|
INSERT OR IGNORE INTO rail_meta (rail_index, name) VALUES (0, NULL), (1, NULL), (2, NULL);
|
|
803
862
|
`);
|
|
804
863
|
},
|
|
864
|
+
// Migration 40: durable idempotency ledger for billable job spawns. Clients
|
|
865
|
+
// can safely retry a timed-out POST (or double-submit) without enqueueing a
|
|
866
|
+
// second job. Entries are deliberately short-lived and pruned by the route;
|
|
867
|
+
// the ledger is not job history and therefore has no foreign key to jobs.
|
|
868
|
+
(db) => {
|
|
869
|
+
db.exec(`
|
|
870
|
+
CREATE TABLE IF NOT EXISTS job_spawn_requests (
|
|
871
|
+
idempotency_key TEXT PRIMARY KEY,
|
|
872
|
+
fingerprint TEXT NOT NULL,
|
|
873
|
+
job_id TEXT NOT NULL,
|
|
874
|
+
created_at_ms INTEGER NOT NULL,
|
|
875
|
+
expires_at_ms INTEGER NOT NULL
|
|
876
|
+
);
|
|
877
|
+
CREATE INDEX IF NOT EXISTS idx_job_spawn_requests_expires
|
|
878
|
+
ON job_spawn_requests(expires_at_ms);
|
|
879
|
+
`);
|
|
880
|
+
},
|
|
881
|
+
// Migration 41: durable outbox for jobs left RUNNING by an ungraceful
|
|
882
|
+
// process exit. QueueManager atomically snapshots each orphan here before it
|
|
883
|
+
// flips the job to failed, then checkpoints accounting and the terminal
|
|
884
|
+
// domain callback independently. A second crash can therefore resume either
|
|
885
|
+
// step without duplicating the ai_invocations ledger or losing the callback.
|
|
886
|
+
(db) => {
|
|
887
|
+
db.exec(`
|
|
888
|
+
CREATE TABLE IF NOT EXISTS orphan_job_recovery (
|
|
889
|
+
job_id TEXT PRIMARY KEY,
|
|
890
|
+
payload TEXT NOT NULL,
|
|
891
|
+
accounting_completed INTEGER NOT NULL DEFAULT 0 CHECK (accounting_completed IN (0, 1)),
|
|
892
|
+
callback_completed INTEGER NOT NULL DEFAULT 0 CHECK (callback_completed IN (0, 1)),
|
|
893
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
894
|
+
);
|
|
895
|
+
CREATE INDEX IF NOT EXISTS idx_orphan_job_recovery_pending
|
|
896
|
+
ON orphan_job_recovery(accounting_completed, callback_completed);
|
|
897
|
+
`);
|
|
898
|
+
},
|
|
899
|
+
// Migration 42: persist the provider actually selected for each job and add
|
|
900
|
+
// a third durable recovery checkpoint for queue/pipeline terminal invariants.
|
|
901
|
+
// Both ALTERs are guarded so developer databases that already applied the
|
|
902
|
+
// unreleased orphan-outbox migration can advance safely.
|
|
903
|
+
(db) => {
|
|
904
|
+
const jobCols = db.prepare(`PRAGMA table_info(jobs)`).all().map((r) => r.name);
|
|
905
|
+
if (!jobCols.includes('provider')) {
|
|
906
|
+
db.exec(`ALTER TABLE jobs ADD COLUMN provider TEXT`);
|
|
907
|
+
}
|
|
908
|
+
const recoveryCols = db.prepare(`PRAGMA table_info(orphan_job_recovery)`).all().map((r) => r.name);
|
|
909
|
+
if (!recoveryCols.includes('terminal_completed')) {
|
|
910
|
+
db.exec(`
|
|
911
|
+
ALTER TABLE orphan_job_recovery
|
|
912
|
+
ADD COLUMN terminal_completed INTEGER NOT NULL DEFAULT 0
|
|
913
|
+
CHECK (terminal_completed IN (0, 1))
|
|
914
|
+
`);
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
// Migration 43: durable pre-start queue. This is intentionally separate from
|
|
918
|
+
// jobs: a queue admission is not an execution and therefore has no truthful
|
|
919
|
+
// jobs.started_at value. createJob atomically promotes a row out of this table
|
|
920
|
+
// when the provider process actually starts.
|
|
921
|
+
(db) => {
|
|
922
|
+
db.exec(`
|
|
923
|
+
CREATE TABLE IF NOT EXISTS queued_jobs (
|
|
924
|
+
id TEXT PRIMARY KEY,
|
|
925
|
+
command TEXT NOT NULL,
|
|
926
|
+
queue_position INTEGER,
|
|
927
|
+
priority TEXT NOT NULL DEFAULT 'normal',
|
|
928
|
+
depends_on_job_id TEXT,
|
|
929
|
+
pipeline_id TEXT,
|
|
930
|
+
provider TEXT,
|
|
931
|
+
model TEXT,
|
|
932
|
+
profile_name TEXT,
|
|
933
|
+
profile_selection_set INTEGER NOT NULL DEFAULT 0
|
|
934
|
+
CHECK (profile_selection_set IN (0, 1)),
|
|
935
|
+
interactive INTEGER CHECK (interactive IN (0, 1)),
|
|
936
|
+
causal_ownership INTEGER NOT NULL DEFAULT 0
|
|
937
|
+
CHECK (causal_ownership IN (0, 1)),
|
|
938
|
+
enqueued_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
939
|
+
);
|
|
940
|
+
CREATE INDEX IF NOT EXISTS idx_queued_jobs_position
|
|
941
|
+
ON queued_jobs(queue_position);
|
|
942
|
+
`);
|
|
943
|
+
},
|
|
944
|
+
// Migration 44: persist which manager owns terminal recovery for each jobs
|
|
945
|
+
// row. Before this boundary QueueManager swept every RUNNING row, including
|
|
946
|
+
// LoopRunManager's backing rows, and recorded their already-accounted step
|
|
947
|
+
// spend again as surface='job'. Existing loop rows are classified by their
|
|
948
|
+
// durable loop_runs identity; every other historical job remains queue-owned.
|
|
949
|
+
(db) => {
|
|
950
|
+
const jobCols = db.prepare(`PRAGMA table_info(jobs)`).all().map((r) => r.name);
|
|
951
|
+
if (!jobCols.includes('owner')) {
|
|
952
|
+
db.exec(`
|
|
953
|
+
ALTER TABLE jobs
|
|
954
|
+
ADD COLUMN owner TEXT NOT NULL DEFAULT 'queue'
|
|
955
|
+
CHECK (owner IN ('queue', 'loop'))
|
|
956
|
+
`);
|
|
957
|
+
}
|
|
958
|
+
db.exec(`
|
|
959
|
+
UPDATE jobs
|
|
960
|
+
SET owner = 'loop',
|
|
961
|
+
provider = COALESCE(
|
|
962
|
+
jobs.provider,
|
|
963
|
+
(SELECT loop_runs.provider FROM loop_runs WHERE loop_runs.id = jobs.id)
|
|
964
|
+
)
|
|
965
|
+
WHERE EXISTS (SELECT 1 FROM loop_runs WHERE loop_runs.id = jobs.id);
|
|
966
|
+
CREATE INDEX IF NOT EXISTS idx_jobs_owner_status ON jobs(owner, status);
|
|
967
|
+
`);
|
|
968
|
+
},
|
|
969
|
+
// Migration 45: crash-consistent loop terminal/accounting outboxes and
|
|
970
|
+
// causal ownership for rail/ticket effects. `loop_runs.ticket_ids_json`
|
|
971
|
+
// replaces the old startup heuristic ("one active run means scope=all") with
|
|
972
|
+
// the exact launch set. The recovery tables intentionally have no FK to
|
|
973
|
+
// jobs: terminal history is independently deletable while recovery effects
|
|
974
|
+
// still have to finish.
|
|
975
|
+
(db) => {
|
|
976
|
+
const loopCols = db.prepare(`PRAGMA table_info(loop_runs)`).all().map((r) => r.name);
|
|
977
|
+
if (!loopCols.includes('ticket_ids_json')) {
|
|
978
|
+
db.exec(`ALTER TABLE loop_runs ADD COLUMN ticket_ids_json TEXT NOT NULL DEFAULT '[]'`);
|
|
979
|
+
}
|
|
980
|
+
if (!loopCols.includes('ticket_completion_status')) {
|
|
981
|
+
db.exec(`
|
|
982
|
+
ALTER TABLE loop_runs
|
|
983
|
+
ADD COLUMN ticket_completion_status TEXT NOT NULL DEFAULT 'done'
|
|
984
|
+
CHECK (ticket_completion_status IN ('done', 'on_review'))
|
|
985
|
+
`);
|
|
986
|
+
}
|
|
987
|
+
if (!loopCols.includes('causal_ownership')) {
|
|
988
|
+
db.exec(`
|
|
989
|
+
ALTER TABLE loop_runs
|
|
990
|
+
ADD COLUMN causal_ownership INTEGER NOT NULL DEFAULT 0
|
|
991
|
+
CHECK (causal_ownership IN (0, 1))
|
|
992
|
+
`);
|
|
993
|
+
}
|
|
994
|
+
db.exec(`
|
|
995
|
+
CREATE TABLE IF NOT EXISTS loop_terminal_recovery (
|
|
996
|
+
run_id TEXT PRIMARY KEY,
|
|
997
|
+
payload TEXT NOT NULL,
|
|
998
|
+
callback_completed INTEGER NOT NULL DEFAULT 0
|
|
999
|
+
CHECK (callback_completed IN (0, 1)),
|
|
1000
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1001
|
+
);
|
|
1002
|
+
|
|
1003
|
+
CREATE TABLE IF NOT EXISTS loop_step_recovery (
|
|
1004
|
+
run_id TEXT NOT NULL,
|
|
1005
|
+
step_key TEXT NOT NULL,
|
|
1006
|
+
invocation_id TEXT NOT NULL UNIQUE,
|
|
1007
|
+
payload TEXT NOT NULL,
|
|
1008
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1009
|
+
PRIMARY KEY (run_id, step_key)
|
|
1010
|
+
);
|
|
1011
|
+
CREATE INDEX IF NOT EXISTS idx_loop_step_recovery_run
|
|
1012
|
+
ON loop_step_recovery(run_id);
|
|
1013
|
+
|
|
1014
|
+
CREATE TABLE IF NOT EXISTS rail_ticket_ownership (
|
|
1015
|
+
rail_index INTEGER NOT NULL,
|
|
1016
|
+
ticket_id INTEGER NOT NULL,
|
|
1017
|
+
owner_id TEXT NOT NULL,
|
|
1018
|
+
generation INTEGER NOT NULL DEFAULT 1,
|
|
1019
|
+
claimed_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1020
|
+
PRIMARY KEY (rail_index, ticket_id)
|
|
1021
|
+
);
|
|
1022
|
+
CREATE INDEX IF NOT EXISTS idx_rail_ticket_owner
|
|
1023
|
+
ON rail_ticket_ownership(owner_id);
|
|
1024
|
+
|
|
1025
|
+
CREATE TABLE IF NOT EXISTS ticket_outcome_ownership (
|
|
1026
|
+
ticket_id INTEGER PRIMARY KEY,
|
|
1027
|
+
owner_id TEXT NOT NULL,
|
|
1028
|
+
generation INTEGER NOT NULL DEFAULT 1,
|
|
1029
|
+
claimed_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1030
|
+
);
|
|
1031
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_outcome_owner
|
|
1032
|
+
ON ticket_outcome_ownership(owner_id);
|
|
1033
|
+
|
|
1034
|
+
-- Builds from the pre-owner WIP may already have captured loop backing
|
|
1035
|
+
-- rows in QueueManager's outbox, or even checkpointed the resulting
|
|
1036
|
+
-- surface='job' invocation. Those rows are unambiguously wrong: a jobs
|
|
1037
|
+
-- id that is also a loop_runs id is exclusively loop-owned.
|
|
1038
|
+
DELETE FROM orphan_job_recovery
|
|
1039
|
+
WHERE job_id IN (SELECT id FROM loop_runs);
|
|
1040
|
+
DELETE FROM ai_invocations
|
|
1041
|
+
WHERE surface = 'job'
|
|
1042
|
+
AND EXISTS (
|
|
1043
|
+
SELECT 1 FROM loop_runs
|
|
1044
|
+
WHERE ai_invocations.surface_ref_id = loop_runs.id
|
|
1045
|
+
OR ai_invocations.surface_ref_id LIKE loop_runs.id || '#t%'
|
|
1046
|
+
);
|
|
1047
|
+
`);
|
|
1048
|
+
},
|
|
1049
|
+
// Migration 46: preserve every pre-spawn semantic override across restart.
|
|
1050
|
+
// Nullable provider/model/interactive encode "use the spawn-time default";
|
|
1051
|
+
// profile needs a separate presence bit because NULL itself means the
|
|
1052
|
+
// deliberate force-legacy selection when the bit is set.
|
|
1053
|
+
(db) => {
|
|
1054
|
+
const cols = new Set(db.prepare(`PRAGMA table_info(queued_jobs)`).all()
|
|
1055
|
+
.map((row) => row.name));
|
|
1056
|
+
if (!cols.has('provider')) {
|
|
1057
|
+
db.exec(`ALTER TABLE queued_jobs ADD COLUMN provider TEXT`);
|
|
1058
|
+
}
|
|
1059
|
+
if (!cols.has('model')) {
|
|
1060
|
+
db.exec(`ALTER TABLE queued_jobs ADD COLUMN model TEXT`);
|
|
1061
|
+
}
|
|
1062
|
+
if (!cols.has('profile_name')) {
|
|
1063
|
+
db.exec(`ALTER TABLE queued_jobs ADD COLUMN profile_name TEXT`);
|
|
1064
|
+
}
|
|
1065
|
+
if (!cols.has('profile_selection_set')) {
|
|
1066
|
+
db.exec(`
|
|
1067
|
+
ALTER TABLE queued_jobs
|
|
1068
|
+
ADD COLUMN profile_selection_set INTEGER NOT NULL DEFAULT 0
|
|
1069
|
+
CHECK (profile_selection_set IN (0, 1))
|
|
1070
|
+
`);
|
|
1071
|
+
}
|
|
1072
|
+
if (!cols.has('interactive')) {
|
|
1073
|
+
db.exec(`
|
|
1074
|
+
ALTER TABLE queued_jobs
|
|
1075
|
+
ADD COLUMN interactive INTEGER CHECK (interactive IN (0, 1))
|
|
1076
|
+
`);
|
|
1077
|
+
}
|
|
1078
|
+
if (!cols.has('causal_ownership')) {
|
|
1079
|
+
db.exec(`
|
|
1080
|
+
ALTER TABLE queued_jobs
|
|
1081
|
+
ADD COLUMN causal_ownership INTEGER NOT NULL DEFAULT 0
|
|
1082
|
+
CHECK (causal_ownership IN (0, 1))
|
|
1083
|
+
`);
|
|
1084
|
+
}
|
|
1085
|
+
const jobCols = new Set(db.prepare(`PRAGMA table_info(jobs)`).all()
|
|
1086
|
+
.map((row) => row.name));
|
|
1087
|
+
if (!jobCols.has('causal_ownership')) {
|
|
1088
|
+
db.exec(`
|
|
1089
|
+
ALTER TABLE jobs
|
|
1090
|
+
ADD COLUMN causal_ownership INTEGER NOT NULL DEFAULT 0
|
|
1091
|
+
CHECK (causal_ownership IN (0, 1))
|
|
1092
|
+
`);
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
// Migration 47: crash recovery reads the bounded newest provider frontier;
|
|
1096
|
+
// this composite index avoids sorting/scanning an unbounded transcript while
|
|
1097
|
+
// the queue is fail-stopped during startup.
|
|
1098
|
+
(db) => {
|
|
1099
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_events_job_seq ON events(job_id, seq)`);
|
|
1100
|
+
},
|
|
1101
|
+
// Migration 48: truthful Safe-PR settlement. Execution truth, delivery
|
|
1102
|
+
// readiness, continuation ownership and decision-operation ownership are
|
|
1103
|
+
// independent durable facts; the old decision/pr_state pair cannot explain
|
|
1104
|
+
// a successful run whose commit/ref/push later failed. Before enforcing the
|
|
1105
|
+
// intended one-active-generation-per-rail invariant, terminalize historical
|
|
1106
|
+
// duplicate rows deterministically (newest rowid wins) so an older iteration
|
|
1107
|
+
// can never resurface after the current one closes.
|
|
1108
|
+
(db) => {
|
|
1109
|
+
const cols = new Set(db.prepare(`PRAGMA table_info(rail_pr_deliveries)`).all()
|
|
1110
|
+
.map((row) => row.name));
|
|
1111
|
+
const add = (name, ddl) => {
|
|
1112
|
+
if (!cols.has(name))
|
|
1113
|
+
db.exec(`ALTER TABLE rail_pr_deliveries ADD COLUMN ${ddl}`);
|
|
1114
|
+
};
|
|
1115
|
+
add('implementation_outcome', `implementation_outcome TEXT NOT NULL DEFAULT 'unknown'`);
|
|
1116
|
+
add('delivery_outcome', `delivery_outcome TEXT NOT NULL DEFAULT 'unknown'`);
|
|
1117
|
+
add('status_code', `status_code TEXT`);
|
|
1118
|
+
add('status_detail', `status_detail TEXT`);
|
|
1119
|
+
add('delivery_sha', `delivery_sha TEXT`);
|
|
1120
|
+
add('is_continuation', `is_continuation INTEGER NOT NULL DEFAULT 0 CHECK (is_continuation IN (0, 1))`);
|
|
1121
|
+
add('supersedes_delivery_id', `supersedes_delivery_id TEXT`);
|
|
1122
|
+
add('operation', `operation TEXT`);
|
|
1123
|
+
add('operation_token', `operation_token TEXT`);
|
|
1124
|
+
add('operation_started_at_ms', `operation_started_at_ms INTEGER`);
|
|
1125
|
+
add('cleanup_warnings', `cleanup_warnings TEXT NOT NULL DEFAULT '[]'`);
|
|
1126
|
+
db.exec(`
|
|
1127
|
+
UPDATE rail_pr_deliveries
|
|
1128
|
+
SET implementation_outcome = CASE decision
|
|
1129
|
+
WHEN 'building' THEN 'running'
|
|
1130
|
+
WHEN 'implementation_failed' THEN 'failed'
|
|
1131
|
+
WHEN 'on_review' THEN 'succeeded'
|
|
1132
|
+
WHEN 'pr_draft' THEN 'succeeded'
|
|
1133
|
+
WHEN 'pr_ready' THEN 'succeeded'
|
|
1134
|
+
WHEN 'pr_failed' THEN 'succeeded'
|
|
1135
|
+
WHEN 'merged' THEN 'succeeded'
|
|
1136
|
+
ELSE implementation_outcome
|
|
1137
|
+
END
|
|
1138
|
+
WHERE implementation_outcome = 'unknown';
|
|
1139
|
+
|
|
1140
|
+
UPDATE rail_pr_deliveries
|
|
1141
|
+
SET delivery_outcome = CASE decision
|
|
1142
|
+
WHEN 'building' THEN 'pending'
|
|
1143
|
+
WHEN 'implementation_failed' THEN 'not_started'
|
|
1144
|
+
WHEN 'on_review' THEN 'ready'
|
|
1145
|
+
WHEN 'pr_draft' THEN 'delivered'
|
|
1146
|
+
WHEN 'pr_ready' THEN 'delivered'
|
|
1147
|
+
WHEN 'pr_failed' THEN 'retryable_failure'
|
|
1148
|
+
WHEN 'merged' THEN 'delivered'
|
|
1149
|
+
ELSE delivery_outcome
|
|
1150
|
+
END
|
|
1151
|
+
WHERE delivery_outcome = 'unknown';
|
|
1152
|
+
|
|
1153
|
+
UPDATE rail_pr_deliveries
|
|
1154
|
+
SET status_code = CASE decision
|
|
1155
|
+
WHEN 'building' THEN 'implementation_running'
|
|
1156
|
+
WHEN 'implementation_failed' THEN 'implementation_failed'
|
|
1157
|
+
WHEN 'on_review' THEN 'ready_for_review'
|
|
1158
|
+
WHEN 'pr_draft' THEN 'pr_draft_ready'
|
|
1159
|
+
WHEN 'pr_ready' THEN 'pr_ready'
|
|
1160
|
+
WHEN 'pr_failed' THEN 'delivery_failed'
|
|
1161
|
+
WHEN 'merged' THEN 'merged'
|
|
1162
|
+
ELSE status_code
|
|
1163
|
+
END
|
|
1164
|
+
WHERE status_code IS NULL;
|
|
1165
|
+
|
|
1166
|
+
UPDATE rail_pr_deliveries
|
|
1167
|
+
SET decision = 'superseded',
|
|
1168
|
+
status_code = 'superseded',
|
|
1169
|
+
updated_at = datetime('now')
|
|
1170
|
+
WHERE decision NOT IN ('merged', 'discarded', 'superseded')
|
|
1171
|
+
AND rowid NOT IN (
|
|
1172
|
+
SELECT MAX(rowid)
|
|
1173
|
+
FROM rail_pr_deliveries
|
|
1174
|
+
WHERE decision NOT IN ('merged', 'discarded', 'superseded')
|
|
1175
|
+
GROUP BY rail_index
|
|
1176
|
+
);
|
|
1177
|
+
|
|
1178
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_rail_pr_deliveries_one_active_per_rail
|
|
1179
|
+
ON rail_pr_deliveries(rail_index)
|
|
1180
|
+
WHERE decision NOT IN ('merged', 'discarded', 'superseded');
|
|
1181
|
+
`);
|
|
1182
|
+
},
|
|
1183
|
+
// Migration 49: repair the exact legacy false-failure shape that motivated
|
|
1184
|
+
// the orthogonal lifecycle. Older settlement code could write
|
|
1185
|
+
// decision='implementation_failed' after every loop had durably succeeded,
|
|
1186
|
+
// solely because commit/ref delivery failed. Reclassify only rows whose full
|
|
1187
|
+
// run set is present and terminal; ambiguous rows remain conservative. This
|
|
1188
|
+
// migration also makes truthful no-change acknowledgement (`completed`) a
|
|
1189
|
+
// terminal generation for the one-active-per-rail invariant.
|
|
1190
|
+
(db) => {
|
|
1191
|
+
const legacyRows = db.prepare(`
|
|
1192
|
+
SELECT id, run_ids, branches
|
|
1193
|
+
FROM rail_pr_deliveries
|
|
1194
|
+
WHERE decision = 'implementation_failed'
|
|
1195
|
+
`).all();
|
|
1196
|
+
const update = db.prepare(`
|
|
1197
|
+
UPDATE rail_pr_deliveries
|
|
1198
|
+
SET decision = 'pr_failed',
|
|
1199
|
+
implementation_outcome = ?,
|
|
1200
|
+
delivery_outcome = 'blocked',
|
|
1201
|
+
status_code = 'settlement_interrupted',
|
|
1202
|
+
status_detail = ?,
|
|
1203
|
+
branches = ?,
|
|
1204
|
+
updated_at = datetime('now')
|
|
1205
|
+
WHERE id = ? AND decision = 'implementation_failed'
|
|
1206
|
+
`);
|
|
1207
|
+
for (const row of legacyRows) {
|
|
1208
|
+
let runIds = [];
|
|
1209
|
+
try {
|
|
1210
|
+
const parsed = JSON.parse(row.run_ids);
|
|
1211
|
+
if (Array.isArray(parsed)) {
|
|
1212
|
+
runIds = [...new Set(parsed.filter((value) => typeof value === 'string' && value.length > 0))];
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
catch { /* malformed legacy evidence stays conservative */ }
|
|
1216
|
+
if (runIds.length === 0)
|
|
1217
|
+
continue;
|
|
1218
|
+
const placeholders = runIds.map(() => '?').join(',');
|
|
1219
|
+
const runs = db.prepare(`
|
|
1220
|
+
SELECT id, status, final_outcome
|
|
1221
|
+
FROM loop_runs
|
|
1222
|
+
WHERE id IN (${placeholders})
|
|
1223
|
+
`).all(...runIds);
|
|
1224
|
+
if (runs.length !== runIds.length || runs.some((run) => run.status !== 'completed'))
|
|
1225
|
+
continue;
|
|
1226
|
+
const outcomes = new Map(runs.map((run) => [run.id, run.final_outcome]));
|
|
1227
|
+
const succeeded = runIds.filter((runId) => outcomes.get(runId) === 'success').length;
|
|
1228
|
+
if (succeeded === 0)
|
|
1229
|
+
continue;
|
|
1230
|
+
let branches = [];
|
|
1231
|
+
try {
|
|
1232
|
+
const parsed = JSON.parse(row.branches);
|
|
1233
|
+
if (Array.isArray(parsed))
|
|
1234
|
+
branches = parsed;
|
|
1235
|
+
}
|
|
1236
|
+
catch { /* retain an empty evidence set rather than malformed JSON */ }
|
|
1237
|
+
const repairedBranches = branches.map((value, index) => {
|
|
1238
|
+
if (!value || typeof value !== 'object')
|
|
1239
|
+
return value;
|
|
1240
|
+
const unit = value;
|
|
1241
|
+
const runId = runIds[index];
|
|
1242
|
+
const implementationSucceeded = runId ? outcomes.get(runId) === 'success' : succeeded === runIds.length;
|
|
1243
|
+
return {
|
|
1244
|
+
...unit,
|
|
1245
|
+
...(runId ? { runId } : {}),
|
|
1246
|
+
implementationOutcome: implementationSucceeded ? 'succeeded' : 'failed',
|
|
1247
|
+
deliveryOutcome: implementationSucceeded ? 'blocked' : 'not_started',
|
|
1248
|
+
...(implementationSucceeded ? { failureCode: 'settlement_interrupted' } : {}),
|
|
1249
|
+
};
|
|
1250
|
+
});
|
|
1251
|
+
update.run(succeeded === runIds.length ? 'succeeded' : 'partially_succeeded', 'Recovered the successful implementation result from durable run logs; legacy delivery settlement was interrupted.', JSON.stringify(repairedBranches), row.id);
|
|
1252
|
+
}
|
|
1253
|
+
db.exec(`
|
|
1254
|
+
DROP INDEX IF EXISTS idx_rail_pr_deliveries_one_active_per_rail;
|
|
1255
|
+
CREATE UNIQUE INDEX idx_rail_pr_deliveries_one_active_per_rail
|
|
1256
|
+
ON rail_pr_deliveries(rail_index)
|
|
1257
|
+
WHERE decision NOT IN ('completed', 'merged', 'discarded', 'superseded');
|
|
1258
|
+
`);
|
|
1259
|
+
},
|
|
1260
|
+
// Migration 50: terminal Safe-PR decisions and their ticket-file mutation
|
|
1261
|
+
// cross SQLite/JSON boundaries. Persist an idempotent outbox row in the same
|
|
1262
|
+
// transaction as the terminal decision so a crash can never leave tickets
|
|
1263
|
+
// parked on_review with no legal action left to replay.
|
|
1264
|
+
(db) => {
|
|
1265
|
+
db.exec(`
|
|
1266
|
+
CREATE TABLE IF NOT EXISTS rail_pr_ticket_effects (
|
|
1267
|
+
delivery_id TEXT PRIMARY KEY,
|
|
1268
|
+
ticket_ids TEXT NOT NULL,
|
|
1269
|
+
causal_owners TEXT NOT NULL DEFAULT '{}',
|
|
1270
|
+
applied_ticket_ids TEXT,
|
|
1271
|
+
target_status TEXT NOT NULL CHECK (target_status IN ('todo', 'done')),
|
|
1272
|
+
jira_action TEXT NOT NULL CHECK (jira_action IN ('discard', 'merged', 'completed', 'refine', 'backlog')),
|
|
1273
|
+
pr_url TEXT,
|
|
1274
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
1275
|
+
last_error TEXT,
|
|
1276
|
+
tickets_applied_at TEXT,
|
|
1277
|
+
jira_enqueued_at TEXT,
|
|
1278
|
+
completed_at TEXT,
|
|
1279
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1280
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1281
|
+
);
|
|
1282
|
+
CREATE INDEX IF NOT EXISTS idx_rail_pr_ticket_effects_pending
|
|
1283
|
+
ON rail_pr_ticket_effects(completed_at)
|
|
1284
|
+
WHERE completed_at IS NULL;
|
|
1285
|
+
`);
|
|
1286
|
+
// Keep the migration restart-safe for development DBs that may have run an
|
|
1287
|
+
// earlier migration-50 draft before these phase columns were added. Shipped
|
|
1288
|
+
// migrations remain atomic, but additive guards make local upgrade testing
|
|
1289
|
+
// deterministic as well.
|
|
1290
|
+
const effectCols = new Set(db.prepare(`PRAGMA table_info(rail_pr_ticket_effects)`).all()
|
|
1291
|
+
.map((row) => row.name));
|
|
1292
|
+
if (!effectCols.has('applied_ticket_ids')) {
|
|
1293
|
+
db.exec(`ALTER TABLE rail_pr_ticket_effects ADD COLUMN applied_ticket_ids TEXT`);
|
|
1294
|
+
}
|
|
1295
|
+
if (!effectCols.has('tickets_applied_at')) {
|
|
1296
|
+
db.exec(`ALTER TABLE rail_pr_ticket_effects ADD COLUMN tickets_applied_at TEXT`);
|
|
1297
|
+
}
|
|
1298
|
+
if (!effectCols.has('jira_enqueued_at')) {
|
|
1299
|
+
db.exec(`ALTER TABLE rail_pr_ticket_effects ADD COLUMN jira_enqueued_at TEXT`);
|
|
1300
|
+
}
|
|
1301
|
+
if (!effectCols.has('causal_owners')) {
|
|
1302
|
+
db.exec(`ALTER TABLE rail_pr_ticket_effects ADD COLUMN causal_owners TEXT NOT NULL DEFAULT '{}'`);
|
|
1303
|
+
}
|
|
1304
|
+
},
|
|
1305
|
+
// Migration 51: a development build briefly shipped migration 50 without
|
|
1306
|
+
// phase columns and with a CHECK that allowed only discard/merged. A DB that
|
|
1307
|
+
// already records version 50 will never rerun its edited body, so rebuild the
|
|
1308
|
+
// table once, preserve every row, and install the complete action contract.
|
|
1309
|
+
// Migration 52 owns the causal historical backfill after both schemas exist.
|
|
1310
|
+
(db) => {
|
|
1311
|
+
const table = db.prepare(`
|
|
1312
|
+
SELECT sql FROM sqlite_master
|
|
1313
|
+
WHERE type = 'table' AND name = 'rail_pr_ticket_effects'
|
|
1314
|
+
`).get();
|
|
1315
|
+
const createFullTable = (name) => {
|
|
1316
|
+
db.exec(`
|
|
1317
|
+
CREATE TABLE ${name} (
|
|
1318
|
+
delivery_id TEXT PRIMARY KEY,
|
|
1319
|
+
ticket_ids TEXT NOT NULL,
|
|
1320
|
+
causal_owners TEXT NOT NULL DEFAULT '{}',
|
|
1321
|
+
applied_ticket_ids TEXT,
|
|
1322
|
+
target_status TEXT NOT NULL CHECK (target_status IN ('todo', 'done')),
|
|
1323
|
+
jira_action TEXT NOT NULL CHECK (jira_action IN ('discard', 'merged', 'completed', 'refine', 'backlog')),
|
|
1324
|
+
pr_url TEXT,
|
|
1325
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
1326
|
+
last_error TEXT,
|
|
1327
|
+
tickets_applied_at TEXT,
|
|
1328
|
+
jira_enqueued_at TEXT,
|
|
1329
|
+
completed_at TEXT,
|
|
1330
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1331
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1332
|
+
)
|
|
1333
|
+
`);
|
|
1334
|
+
};
|
|
1335
|
+
if (!table) {
|
|
1336
|
+
createFullTable('rail_pr_ticket_effects');
|
|
1337
|
+
}
|
|
1338
|
+
else {
|
|
1339
|
+
const cols = new Set(db.prepare(`PRAGMA table_info(rail_pr_ticket_effects)`).all()
|
|
1340
|
+
.map((row) => row.name));
|
|
1341
|
+
const sql = table.sql ?? '';
|
|
1342
|
+
const complete = ['causal_owners', 'applied_ticket_ids', 'tickets_applied_at', 'jira_enqueued_at']
|
|
1343
|
+
.every((column) => cols.has(column)) &&
|
|
1344
|
+
['completed', 'refine', 'backlog'].every((action) => sql.includes(`'${action}'`));
|
|
1345
|
+
if (!complete) {
|
|
1346
|
+
db.exec(`DROP TABLE IF EXISTS rail_pr_ticket_effects_v51`);
|
|
1347
|
+
createFullTable('rail_pr_ticket_effects_v51');
|
|
1348
|
+
const value = (column, fallback) => cols.has(column) ? column : fallback;
|
|
1349
|
+
db.exec(`
|
|
1350
|
+
INSERT INTO rail_pr_ticket_effects_v51 (
|
|
1351
|
+
delivery_id, ticket_ids, causal_owners, applied_ticket_ids, target_status,
|
|
1352
|
+
jira_action, pr_url, attempts, last_error, tickets_applied_at,
|
|
1353
|
+
jira_enqueued_at, completed_at, created_at, updated_at
|
|
1354
|
+
)
|
|
1355
|
+
SELECT
|
|
1356
|
+
${value('delivery_id', "''")},
|
|
1357
|
+
${value('ticket_ids', "'[]'")},
|
|
1358
|
+
${value('causal_owners', "'{}'")},
|
|
1359
|
+
${value('applied_ticket_ids', 'NULL')},
|
|
1360
|
+
${value('target_status', "'todo'")},
|
|
1361
|
+
${value('jira_action', "'backlog'")},
|
|
1362
|
+
${value('pr_url', 'NULL')},
|
|
1363
|
+
${value('attempts', '0')},
|
|
1364
|
+
${value('last_error', 'NULL')},
|
|
1365
|
+
${value('tickets_applied_at', 'NULL')},
|
|
1366
|
+
${value('jira_enqueued_at', 'NULL')},
|
|
1367
|
+
${value('completed_at', 'NULL')},
|
|
1368
|
+
${value('created_at', "datetime('now')")},
|
|
1369
|
+
${value('updated_at', "datetime('now')")}
|
|
1370
|
+
FROM rail_pr_ticket_effects;
|
|
1371
|
+
|
|
1372
|
+
DROP TABLE rail_pr_ticket_effects;
|
|
1373
|
+
ALTER TABLE rail_pr_ticket_effects_v51 RENAME TO rail_pr_ticket_effects;
|
|
1374
|
+
`);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
db.exec(`
|
|
1378
|
+
CREATE INDEX IF NOT EXISTS idx_rail_pr_ticket_effects_pending
|
|
1379
|
+
ON rail_pr_ticket_effects(completed_at)
|
|
1380
|
+
WHERE completed_at IS NULL
|
|
1381
|
+
`);
|
|
1382
|
+
},
|
|
1383
|
+
// Migration 52: bind every ticket effect to the SQLite ticket-generation
|
|
1384
|
+
// owner that created it. Historical terminal rows are backfilled only when
|
|
1385
|
+
// their run_ids still own the ticket; an old merge/discard can therefore
|
|
1386
|
+
// never mutate a newer iteration merely because it is also on_review.
|
|
1387
|
+
(db) => {
|
|
1388
|
+
// Some development builds recorded migration 45 before its ownership
|
|
1389
|
+
// table was added. Repair that incomplete historical shape before the
|
|
1390
|
+
// causal backfill so one damaged project DB cannot prevent app startup.
|
|
1391
|
+
db.exec(`
|
|
1392
|
+
CREATE TABLE IF NOT EXISTS ticket_outcome_ownership (
|
|
1393
|
+
ticket_id INTEGER PRIMARY KEY,
|
|
1394
|
+
owner_id TEXT NOT NULL,
|
|
1395
|
+
generation INTEGER NOT NULL DEFAULT 1,
|
|
1396
|
+
claimed_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1397
|
+
);
|
|
1398
|
+
CREATE INDEX IF NOT EXISTS idx_ticket_outcome_owner
|
|
1399
|
+
ON ticket_outcome_ownership(owner_id);
|
|
1400
|
+
`);
|
|
1401
|
+
const cols = new Set(db.prepare(`PRAGMA table_info(rail_pr_ticket_effects)`).all()
|
|
1402
|
+
.map((row) => row.name));
|
|
1403
|
+
if (!cols.has('causal_owners')) {
|
|
1404
|
+
db.exec(`ALTER TABLE rail_pr_ticket_effects ADD COLUMN causal_owners TEXT NOT NULL DEFAULT '{}'`);
|
|
1405
|
+
}
|
|
1406
|
+
backfillTerminalRailPrTicketEffects(db);
|
|
1407
|
+
},
|
|
805
1408
|
];
|
|
806
1409
|
function applyMigrations(db) {
|
|
807
1410
|
// Ensure the migrations table exists (migration 1 creates it, but we need
|
|
@@ -854,17 +1457,53 @@ function initDb(dbPath) {
|
|
|
854
1457
|
// transcripts and verbatim terminal command history). After migrations the
|
|
855
1458
|
// WAL/SHM files exist, so this covers them too.
|
|
856
1459
|
(0, secure_fs_1.secureDbFile)(dbPath);
|
|
857
|
-
// Orphan sweep: mark any running jobs as failed on startup
|
|
858
|
-
db.prepare("UPDATE jobs SET status = 'failed', finished_at = ? WHERE status = 'running'").run(new Date().toISOString());
|
|
859
1460
|
// Orphan sweep: cancel any in-flight proposals from a previous server session
|
|
860
1461
|
db.prepare("UPDATE proposals SET status = 'cancelled', updated_at = ? WHERE status IN ('exploring', 'refining')").run(new Date().toISOString());
|
|
861
1462
|
return db;
|
|
862
1463
|
}
|
|
863
1464
|
function createJob(db, job) {
|
|
864
|
-
//
|
|
865
|
-
//
|
|
866
|
-
|
|
867
|
-
|
|
1465
|
+
// Promotion is atomic: after a crash the job is either still replayable in
|
|
1466
|
+
// queued_jobs or is a running jobs row, never absent from both. INSERT OR
|
|
1467
|
+
// IGNORE preserves idempotency for legacy/restored jobs that already exist.
|
|
1468
|
+
const promote = db.transaction(() => {
|
|
1469
|
+
db.prepare('INSERT OR IGNORE INTO jobs (id, command, started_at, status, provider, owner, priority, depends_on_job_id, pipeline_id, interactive, causal_ownership) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)').run(job.id, job.command, job.started_at, 'running', job.provider ?? null, job.owner ?? 'queue', job.priority ?? 'normal', job.depends_on_job_id ?? null, job.pipeline_id ?? null, job.interactive ? 1 : 0, job.causal_ownership ? 1 : 0);
|
|
1470
|
+
db.prepare('UPDATE jobs SET status = ?, started_at = ?, provider = ?, owner = ?, interactive = ?, causal_ownership = ? WHERE id = ?').run('running', job.started_at, job.provider ?? null, job.owner ?? 'queue', job.interactive ? 1 : 0, job.causal_ownership ? 1 : 0, job.id);
|
|
1471
|
+
db.prepare('DELETE FROM queued_jobs WHERE id = ?').run(job.id);
|
|
1472
|
+
});
|
|
1473
|
+
promote();
|
|
1474
|
+
}
|
|
1475
|
+
/** Idempotently persist a job that has been admitted but has not started. */
|
|
1476
|
+
function upsertQueuedJob(db, job) {
|
|
1477
|
+
db.prepare(`
|
|
1478
|
+
INSERT INTO queued_jobs (
|
|
1479
|
+
id, command, queue_position, priority, depends_on_job_id, pipeline_id,
|
|
1480
|
+
provider, model, profile_name, profile_selection_set, interactive,
|
|
1481
|
+
causal_ownership
|
|
1482
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1483
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
1484
|
+
command = excluded.command,
|
|
1485
|
+
queue_position = excluded.queue_position,
|
|
1486
|
+
priority = excluded.priority,
|
|
1487
|
+
depends_on_job_id = excluded.depends_on_job_id,
|
|
1488
|
+
pipeline_id = excluded.pipeline_id,
|
|
1489
|
+
provider = excluded.provider,
|
|
1490
|
+
model = excluded.model,
|
|
1491
|
+
profile_name = excluded.profile_name,
|
|
1492
|
+
profile_selection_set = excluded.profile_selection_set,
|
|
1493
|
+
interactive = excluded.interactive,
|
|
1494
|
+
causal_ownership = excluded.causal_ownership
|
|
1495
|
+
`).run(job.id, job.command, job.queue_position, job.priority, job.depends_on_job_id ?? null, job.pipeline_id ?? null, job.provider ?? null, job.model ?? null, job.profile_name ?? null, job.profile_selection_set ? 1 : 0, job.interactive == null ? null : (job.interactive ? 1 : 0), job.causal_ownership ? 1 : 0);
|
|
1496
|
+
}
|
|
1497
|
+
/** Remove a queued admission after cancellation/skip. Idempotent.
|
|
1498
|
+
*
|
|
1499
|
+
* Migration 43 deliberately keeps a read fallback for pre-migration builds
|
|
1500
|
+
* that represented queued work in `jobs`. Remove that legacy representation
|
|
1501
|
+
* too, but only while it is still queued: promotion changes the status to
|
|
1502
|
+
* running before calling this helper, and terminal history must never be
|
|
1503
|
+
* deleted here. */
|
|
1504
|
+
function deleteQueuedJob(db, jobId) {
|
|
1505
|
+
db.prepare('DELETE FROM queued_jobs WHERE id = ?').run(jobId);
|
|
1506
|
+
db.prepare("DELETE FROM jobs WHERE id = ? AND status = 'queued'").run(jobId);
|
|
868
1507
|
}
|
|
869
1508
|
/**
|
|
870
1509
|
* Flip a job row's `interactive` flag AFTER creation. Used by the loop engine
|
|
@@ -972,6 +1611,15 @@ function getJobEvents(db, jobId) {
|
|
|
972
1611
|
.prepare('SELECT * FROM events WHERE job_id = ? ORDER BY seq ASC')
|
|
973
1612
|
.all(jobId);
|
|
974
1613
|
}
|
|
1614
|
+
class JobRecoveryPendingError extends Error {
|
|
1615
|
+
jobId;
|
|
1616
|
+
constructor(jobId) {
|
|
1617
|
+
super('Job recovery is still pending; retry deletion after recovery completes');
|
|
1618
|
+
this.jobId = jobId;
|
|
1619
|
+
this.name = 'JobRecoveryPendingError';
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
exports.JobRecoveryPendingError = JobRecoveryPendingError;
|
|
975
1623
|
function deleteJob(db, jobId) {
|
|
976
1624
|
// M7: jobs.depends_on_job_id REFERENCES jobs(id) with no ON DELETE action and
|
|
977
1625
|
// foreign_keys=ON, so deleting a pipeline parent throws 'FOREIGN KEY
|
|
@@ -979,6 +1627,11 @@ function deleteJob(db, jobId) {
|
|
|
979
1627
|
// references first, in the same transaction as the delete, so it always
|
|
980
1628
|
// succeeds (children keep running; they just lose the now-irrelevant pointer).
|
|
981
1629
|
const tx = db.transaction((id) => {
|
|
1630
|
+
const pendingLoopStep = db.prepare(`SELECT 1 FROM loop_step_recovery WHERE run_id = ? LIMIT 1`).get(id);
|
|
1631
|
+
const pendingQueueRecovery = db.prepare(`SELECT 1 FROM orphan_job_recovery WHERE job_id = ? LIMIT 1`).get(id);
|
|
1632
|
+
if (pendingLoopStep || pendingQueueRecovery) {
|
|
1633
|
+
throw new JobRecoveryPendingError(id);
|
|
1634
|
+
}
|
|
982
1635
|
db.prepare('UPDATE jobs SET depends_on_job_id = NULL WHERE depends_on_job_id = ?').run(id);
|
|
983
1636
|
// B41: events/job_phases cascade on the jobs FK, but telemetry_blobs/
|
|
984
1637
|
// telemetry_summaries (keyed `jobId`), job_profiles and file_provenance
|
|
@@ -993,7 +1646,11 @@ function deleteJob(db, jobId) {
|
|
|
993
1646
|
tx(jobId);
|
|
994
1647
|
}
|
|
995
1648
|
function purgeJobs(db, opts) {
|
|
996
|
-
const conditions = [
|
|
1649
|
+
const conditions = [
|
|
1650
|
+
"status IN ('completed', 'failed', 'canceled', 'zombie_terminated', 'skipped')",
|
|
1651
|
+
'NOT EXISTS (SELECT 1 FROM loop_step_recovery WHERE loop_step_recovery.run_id = jobs.id)',
|
|
1652
|
+
'NOT EXISTS (SELECT 1 FROM orphan_job_recovery WHERE orphan_job_recovery.job_id = jobs.id)',
|
|
1653
|
+
];
|
|
997
1654
|
const params = [];
|
|
998
1655
|
if (opts?.from) {
|
|
999
1656
|
conditions.push('started_at >= ?');
|