specrails-desktop 2.64.2 → 2.65.0
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 +1 -1
- package/cli/dist/status.js +3 -0
- package/client/dist/assets/ActivityFeedPage-ByVKYII-.js +1 -0
- package/client/dist/assets/AgentBrowserCapture-BGUTjhUr.js +1 -0
- package/client/dist/assets/AgentModeAnalyticsPane-CtOLDDjB.js +2 -0
- package/client/dist/assets/AgentModeCodePane-CDhUKarT.js +2 -0
- package/client/dist/assets/AgentModeJobsPane-BAa_oEHJ.js +1 -0
- package/client/dist/assets/AgentsPage-D32hG4Ve.js +120 -0
- package/client/dist/assets/AnalyticsPage-BU50zeG6.js +5 -0
- package/client/dist/assets/BudgetCard-DP_jxwaD.js +55 -0
- package/client/dist/assets/CodePage-jiYnKGpp.js +3 -0
- package/client/dist/assets/CostValue-Bvn8674q.js +1 -0
- package/client/dist/assets/DesktopAnalyticsPage-CF__H4e3.js +1 -0
- package/client/dist/assets/DocView-RrAp70zp.js +11 -0
- package/client/dist/assets/DocsDialog-DkqHU-JF.js +1 -0
- package/client/dist/assets/DocsPage-C6X089zC.js +1 -0
- package/client/dist/assets/ExportDropdown-C5-o8y3K.js +1 -0
- package/client/dist/assets/HelpHint-Crf9_uoR.js +1 -0
- package/client/dist/assets/IntegrationsPage-aflU3KHK.js +1 -0
- package/client/dist/assets/InteractiveJobComposer-CEMMhyyJ.js +19 -0
- package/client/dist/assets/JobDetailModal-BVJ6hyRs.js +1 -0
- package/client/dist/assets/JobDetailPage-DHzBUmox.js +1 -0
- package/client/dist/assets/JobsPage-o-LAqkwC.js +1 -0
- package/client/dist/assets/LoopBuilderPage-DbSVmXBM.js +1 -0
- package/client/dist/assets/LoopPreviewModal-DbJcVyN1.js +1 -0
- package/client/dist/assets/{LoopWindowSurface-DE0v2K1p.js → LoopWindowSurface-Co1ZK26V.js} +1 -1
- package/client/dist/assets/LoopsPage-C4lgkPXB.js +2 -0
- package/client/dist/assets/MinimizedChatsContext-742ypO8n.js +1 -0
- package/client/dist/assets/PluginsPage-Acks9ges.js +2 -0
- package/client/dist/assets/RailTrack-BfLmBzBh.js +1 -0
- package/client/dist/assets/{RepositoryScopeSelector-2eSqR9WK.js → RepositoryScopeSelector-DcxbKI9w.js} +1 -1
- package/client/dist/assets/ReviewPacketPage-CAVSIOAJ.js +7 -0
- package/client/dist/assets/TemplatePreviewModal-C23SYCTm.js +1 -0
- package/client/dist/assets/TicketDetailModalContext-B-Gtm6Ob.js +23 -0
- package/client/dist/assets/Trans-C6J0cLyh.js +1 -0
- package/client/dist/assets/a11y-prefs-BqoP5goK.js +1 -0
- package/client/dist/assets/activity-BBWfoUOG.js +1 -0
- package/client/dist/assets/activity-BM_skann.js +1 -0
- package/client/dist/assets/activity-Cevl82ke.js +1 -0
- package/client/dist/assets/activity-CmACk5W5.js +1 -0
- package/client/dist/assets/activity-D9LBw3PQ.js +1 -0
- package/client/dist/assets/activity-Dspbb9lz.js +1 -0
- package/client/dist/assets/activity-FPjYIjv9.js +1 -0
- package/client/dist/assets/activity-nLCKMUKt.js +1 -0
- package/client/dist/assets/addspec-BI4jDMhA.js +1 -0
- package/client/dist/assets/addspec-BldTv7Tl.js +1 -0
- package/client/dist/assets/addspec-Cdq-2EcC.js +1 -0
- package/client/dist/assets/addspec-DH5M16BQ.js +1 -0
- package/client/dist/assets/addspec-DOFo9pD5.js +1 -0
- package/client/dist/assets/addspec-DPkwhdmL.js +1 -0
- package/client/dist/assets/addspec-Dzy12Pv3.js +1 -0
- package/client/dist/assets/addspec-skTs6EEW.js +1 -0
- package/client/dist/assets/agent-B_UEUy7Y.js +1 -0
- package/client/dist/assets/agent-BarjlhTA.js +1 -0
- package/client/dist/assets/agent-BfqIITo5.js +1 -0
- package/client/dist/assets/agent-Bt9a7Kyj.js +1 -0
- package/client/dist/assets/agent-C3689RwP.js +1 -0
- package/client/dist/assets/agent-CrmboTAi.js +1 -0
- package/client/dist/assets/agent-DcsoTnuE.js +1 -0
- package/client/dist/assets/agent-GDZoYwd4.js +1 -0
- package/client/dist/assets/{agentRuntime-es2ymSl-.js → agentRuntime-BYH70bKY.js} +1 -1
- package/client/dist/assets/agentRuntime-BijLh8I9.js +1 -0
- package/client/dist/assets/{agentRuntime-BzuwQQgn.js → agentRuntime-BvyuETPe.js} +1 -1
- package/client/dist/assets/{agentRuntime-BDvbJMmS.js → agentRuntime-C2WI6HQh.js} +1 -1
- package/client/dist/assets/{agentRuntime-BKJfv5YD.js → agentRuntime-CZPIlQsr.js} +1 -1
- package/client/dist/assets/{agentRuntime-DiCldqGG.js → agentRuntime-D2dDvCyJ.js} +1 -1
- package/client/dist/assets/agentRuntime-DWZedEbn.js +1 -0
- package/client/dist/assets/agentRuntime-DkIruUNw.js +1 -0
- package/client/dist/assets/agents-35_PDKx9.js +1 -0
- package/client/dist/assets/agents-8fZnHhEQ.js +1 -0
- package/client/dist/assets/agents-Bgimtw8z.js +1 -0
- package/client/dist/assets/agents-C4P160Us.js +1 -0
- package/client/dist/assets/agents-Clg67zbp.js +1 -0
- package/client/dist/assets/agents-DJfF4o6G.js +1 -0
- package/client/dist/assets/agents-Dc9-Y5cw.js +1 -0
- package/client/dist/assets/agents-EN1Zl4YZ.js +1 -0
- package/client/dist/assets/agentstudio-Bm4-NYaG.js +1 -0
- package/client/dist/assets/agentstudio-CD1fuj2o.js +1 -0
- package/client/dist/assets/agentstudio-CQGWFSst.js +1 -0
- package/client/dist/assets/agentstudio-CqVSb65S.js +1 -0
- package/client/dist/assets/agentstudio-DIE_HjsX.js +1 -0
- package/client/dist/assets/agentstudio-D_OmQK-k.js +1 -0
- package/client/dist/assets/agentstudio-Djz9aUfb.js +1 -0
- package/client/dist/assets/agentstudio-Qa3v9o5J.js +1 -0
- package/client/dist/assets/{aiedit-DNXxq_Dr.js → aiedit-1VzLs37W.js} +1 -1
- package/client/dist/assets/{aiedit-DCjA7jLJ.js → aiedit-BNp6GSik.js} +1 -1
- package/client/dist/assets/{aiedit-BoG24nlg.js → aiedit-BOY5xRPi.js} +1 -1
- package/client/dist/assets/{aiedit-iIjz2_Qk.js → aiedit-BrqMZvbc.js} +1 -1
- package/client/dist/assets/{aiedit-CjlSRQVP.js → aiedit-CVgtl7hm.js} +1 -1
- package/client/dist/assets/{aiedit-DQ-0_pvE.js → aiedit-CrFW9Jd2.js} +1 -1
- package/client/dist/assets/{aiedit-olnv3QSt.js → aiedit-YE2lILp7.js} +1 -1
- package/client/dist/assets/{aiedit-B0KUbpB6.js → aiedit-iA_R1AVQ.js} +1 -1
- package/client/dist/assets/analytics-3w0t-4ic.js +1 -0
- package/client/dist/assets/analytics-BRi4KQD6.js +1 -0
- package/client/dist/assets/analytics-BtjAqzke.js +1 -0
- package/client/dist/assets/analytics-COSQ1h47.js +1 -0
- package/client/dist/assets/analytics-CP2HjESk.js +1 -0
- package/client/dist/assets/analytics-DY65TC62.js +1 -0
- package/client/dist/assets/analytics-Den_vvxn.js +1 -0
- package/client/dist/assets/analytics-LmBS96O8.js +1 -0
- package/client/dist/assets/api-DOGbyfTO.js +2 -0
- package/client/dist/assets/builder-BMVvSr4v.js +1 -0
- package/client/dist/assets/builder-BN-MuLZt.js +1 -0
- package/client/dist/assets/builder-BQOZi4CF.js +1 -0
- package/client/dist/assets/builder-BjUPjsyu.js +1 -0
- package/client/dist/assets/builder-BoBtN18T.js +1 -0
- package/client/dist/assets/builder-C5g5NhxL.js +1 -0
- package/client/dist/assets/builder-RUHXw3yx.js +1 -0
- package/client/dist/assets/builder-fyS_AiyC.js +1 -0
- package/client/dist/assets/button-CHPkroew.js +1 -0
- package/client/dist/assets/chat-C9L5T7KI.js +1 -0
- package/client/dist/assets/chevron-right-CwMAj0w_.js +1 -0
- package/client/dist/assets/chevron-up-BAMuP0XD.js +1 -0
- package/client/dist/assets/chunk-OB3PAWPO-BBaq6pUk.js +3 -0
- package/client/dist/assets/code-4le5IIbf.js +1 -0
- package/client/dist/assets/code-B-jCVIbm.js +1 -0
- package/client/dist/assets/code-BRfrn5ix.js +1 -0
- package/client/dist/assets/code-CC9NCrDM.js +1 -0
- package/client/dist/assets/code-CK6pm8wY.js +1 -0
- package/client/dist/assets/code-DDiOzd6c.js +1 -0
- package/client/dist/assets/code-tGifiyf5.js +1 -0
- package/client/dist/assets/code-xkn8kQTg.js +1 -0
- package/client/dist/assets/commands-Bv1QshHR.js +1 -0
- package/client/dist/assets/commands-BvxTxboW.js +1 -0
- package/client/dist/assets/commands-C5ORR0fO.js +1 -0
- package/client/dist/assets/commands-CBKMFSTV.js +1 -0
- package/client/dist/assets/commands-CFJIRsJv.js +1 -0
- package/client/dist/assets/commands-D9o3ZcXl.js +1 -0
- package/client/dist/assets/commands-DNox0Edk.js +1 -0
- package/client/dist/assets/commands-DmIUMLdV.js +1 -0
- package/client/dist/assets/common-5H4TkaoI.js +1 -0
- package/client/dist/assets/common-9S3OdPjx.js +1 -0
- package/client/dist/assets/common-BqnwIcjs.js +1 -0
- package/client/dist/assets/common-CQP3VafS.js +1 -0
- package/client/dist/assets/common-CZnAfkB2.js +1 -0
- package/client/dist/assets/common-D5sNttV4.js +1 -0
- package/client/dist/assets/common-k_qX9nlv.js +1 -0
- package/client/dist/assets/common-s4HIi9XI.js +1 -0
- package/client/dist/assets/compass-B7guwBlY.js +1 -0
- package/client/dist/assets/confirm-dialog-ChZdHL3Q.js +1 -0
- package/client/dist/assets/copy-DOPlLymH.js +1 -0
- package/client/dist/assets/core-BozBzB6Y.js +1 -0
- package/client/dist/assets/dashboard-6zGLGcEz.js +1 -0
- package/client/dist/assets/dashboard-8Gi0FBDq.js +1 -0
- package/client/dist/assets/dashboard-B7E5YrSy.js +1 -0
- package/client/dist/assets/dashboard-BhdKV8xK.js +1 -0
- package/client/dist/assets/dashboard-Bu3zzH_s.js +1 -0
- package/client/dist/assets/dashboard-Ce_6rELA.js +1 -0
- package/client/dist/assets/dashboard-DWY-oz8P.js +1 -0
- package/client/dist/assets/dashboard-gUzlWk0o.js +1 -0
- package/client/dist/assets/date-input-Cdlr8kHz.js +1 -0
- package/client/dist/assets/dialog-C23lB2iP.js +5 -0
- package/client/dist/assets/dist-Di-oOFkX.js +1 -0
- package/client/dist/assets/dist-js-CBmS6MsJ.js +1 -0
- package/client/dist/assets/{dist-js-Rlh4FLH5.js → dist-js-DaJmKapi.js} +1 -1
- package/client/dist/assets/dropdown-menu-Bfp2CK6H.js +1 -0
- package/client/dist/assets/empty-state-D5w9OWj-.js +1 -0
- package/client/dist/assets/es2015-DfnECntk.js +41 -0
- package/client/dist/assets/esm-BKF6CE7v.js +1 -0
- package/client/dist/assets/event-BEnMLqAi.js +1 -0
- package/client/dist/assets/explore--NOz9LCN.js +1 -0
- package/client/dist/assets/explore-B2ulH6dO.js +1 -0
- package/client/dist/assets/explore-BD-QiLdg.js +1 -0
- package/client/dist/assets/explore-BOqd4_1j.js +1 -0
- package/client/dist/assets/explore-Be_Zh5zu.js +1 -0
- package/client/dist/assets/explore-CLjzPSKo.js +1 -0
- package/client/dist/assets/explore-D_-vHm29.js +1 -0
- package/client/dist/assets/explore-yEQTF6ro.js +1 -0
- package/client/dist/assets/file-text-CNXzL3wj.js +1 -0
- package/client/dist/assets/format-BODoFIw6.js +1 -0
- package/client/dist/assets/formatDistanceToNow-DLMIOS0N.js +1 -0
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-O61feXch.js +1 -0
- package/client/dist/assets/git-compare-arrows-Cu6tICCq.js +1 -0
- package/client/dist/assets/humanise-command-CB4ybLwq.js +1 -0
- package/client/dist/assets/inbox-BLZ8cm6_.js +1 -0
- package/client/dist/assets/inbox-BQ3VmNYY.js +1 -0
- package/client/dist/assets/inbox-BdcXWCuT.js +1 -0
- package/client/dist/assets/inbox-CF1PHjns.js +1 -0
- package/client/dist/assets/inbox-CFNPDhso.js +1 -0
- package/client/dist/assets/inbox-DIttK_NW.js +1 -0
- package/client/dist/assets/inbox-Dfdv1Ykl.js +1 -0
- package/client/dist/assets/inbox-JS1inmeO.js +1 -0
- package/client/dist/assets/index-4UWY7Xyz.css +2 -0
- package/client/dist/assets/index-DHzB0T26.js +120 -0
- package/client/dist/assets/integrations-BcKgzgPD.js +1 -0
- package/client/dist/assets/integrations-BmX_XyJq.js +1 -0
- package/client/dist/assets/integrations-CHpwMjlY.js +1 -0
- package/client/dist/assets/integrations-CT3kr8e-.js +1 -0
- package/client/dist/assets/integrations-C_5XAkgz.js +1 -0
- package/client/dist/assets/integrations-Ct9zLX7N.js +1 -0
- package/client/dist/assets/integrations-DEYemxUv.js +1 -0
- package/client/dist/assets/integrations-DWvsB_WB.js +1 -0
- package/client/dist/assets/{jira-Cq6yvN4q.js → jira-B_ERkFRv.js} +1 -1
- package/client/dist/assets/jira-Bn-A5lwD.js +1 -0
- package/client/dist/assets/jira-C71Ybnhp.js +1 -0
- package/client/dist/assets/jira-CkwjeJz6.js +1 -0
- package/client/dist/assets/jira-D9pSLXjI.js +1 -0
- package/client/dist/assets/jira-DBRS_lcp.js +1 -0
- package/client/dist/assets/jira-DHS6CsKh.js +1 -0
- package/client/dist/assets/jira-MInHRUb1.js +1 -0
- package/client/dist/assets/jira-api-DHme7Upx.js +1 -0
- package/client/dist/assets/jobs-BMLTDo63.js +1 -0
- package/client/dist/assets/jobs-BO8q4Mi1.js +1 -0
- package/client/dist/assets/jobs-Ck8uOWMM.js +1 -0
- package/client/dist/assets/jobs-CyFfPCpg.js +1 -0
- package/client/dist/assets/jobs-DT5s4fZ6.js +1 -0
- package/client/dist/assets/jobs-DZAgVPcD.js +1 -0
- package/client/dist/assets/jobs-b5gPYaKr.js +1 -0
- package/client/dist/assets/jobs-xsZK1440.js +1 -0
- package/client/dist/assets/launch-forecast-BTa-p3RP.js +1 -0
- package/client/dist/assets/{loop-layout-DtxX27Jz.css → loop-layout-DLioOiRN.css} +1 -1
- package/client/dist/assets/loop-layout-Sl9cfTvs.js +7 -0
- package/client/dist/assets/loops-BEEOVJDR.js +1 -0
- package/client/dist/assets/loops-BcrQ2vk7.js +1 -0
- package/client/dist/assets/loops-BjWxzJIZ.js +1 -0
- package/client/dist/assets/loops-BogV595N.js +1 -0
- package/client/dist/assets/loops-CU0BLZiz.js +1 -0
- package/client/dist/assets/loops-CrNBgi1G.js +1 -0
- package/client/dist/assets/loops-CwalwS_i.js +1 -0
- package/client/dist/assets/loops-_TDVN-fX.js +1 -0
- package/client/dist/assets/mcp-BNs8gxoL.js +1 -0
- package/client/dist/assets/mcp-BvRh_xO5.js +1 -0
- package/client/dist/assets/mcp-C2F1pghi.js +1 -0
- package/client/dist/assets/mcp-D9RLKAs2.js +1 -0
- package/client/dist/assets/mcp-DAghcsR0.js +1 -0
- package/client/dist/assets/mcp-DWWAPi1G.js +1 -0
- package/client/dist/assets/mcp-DbGSFC3f.js +1 -0
- package/client/dist/assets/mcp-FelCicrv.js +1 -0
- package/client/dist/assets/narration-C3NBkAR4.js +1 -0
- package/client/dist/assets/narration-CkoJq-Lf.js +1 -0
- package/client/dist/assets/narration-Cr0NeW9K.js +1 -0
- package/client/dist/assets/narration-DJUXOs-W.js +1 -0
- package/client/dist/assets/narration-DgL8TMvN.js +1 -0
- package/client/dist/assets/narration-DjBafgv0.js +1 -0
- package/client/dist/assets/narration-Dle6Iv0c.js +1 -0
- package/client/dist/assets/narration-MYlfktga.js +1 -0
- package/client/dist/assets/nav-BSQ8KW1c.js +1 -0
- package/client/dist/assets/nav-BauVof8Z.js +1 -0
- package/client/dist/assets/nav-BfOAH1se.js +1 -0
- package/client/dist/assets/nav-D3bOsipX.js +1 -0
- package/client/dist/assets/nav-DOMMhlLx.js +1 -0
- package/client/dist/assets/nav-DPzVlgZU.js +1 -0
- package/client/dist/assets/nav-DZJbFbah.js +1 -0
- package/client/dist/assets/nav-D_5aojd2.js +1 -0
- package/client/dist/assets/notify-error-BsWANx1T.js +1 -0
- package/client/dist/assets/onboarding-BdZQnNm3.js +1 -0
- package/client/dist/assets/onboarding-CJQEv1vp.js +1 -0
- package/client/dist/assets/onboarding-CWJGYUW3.js +1 -0
- package/client/dist/assets/onboarding-ChfYN7dA.js +1 -0
- package/client/dist/assets/onboarding-CjvDUR3V.js +1 -0
- package/client/dist/assets/onboarding-I6vS-zTB.js +1 -0
- package/client/dist/assets/onboarding-dgC_9dTB.js +1 -0
- package/client/dist/assets/onboarding-mlXSyKzX.js +1 -0
- package/client/dist/assets/origin-03nTuaOb.js +1 -0
- package/client/dist/assets/packet-BjpyRnZr.js +1 -0
- package/client/dist/assets/packet-BwgG5mBt.js +1 -0
- package/client/dist/assets/packet-C3eAUFkV.js +1 -0
- package/client/dist/assets/packet-C8wZuSld.js +1 -0
- package/client/dist/assets/packet-CNXEy_85.js +1 -0
- package/client/dist/assets/packet-DsV5Aa_8.js +1 -0
- package/client/dist/assets/packet-aasskOE7.js +1 -0
- package/client/dist/assets/packet-phxCc2gJ.js +1 -0
- package/client/dist/assets/page-header-BStSHkP8.js +1 -0
- package/client/dist/assets/project-repositories-DJPeAVBK.js +1 -0
- package/client/dist/assets/{provider-capabilities-lePfeT_Y.js → provider-capabilities-DtwcTme4.js} +1 -1
- package/client/dist/assets/recovery-BPDOsC92.js +1 -0
- package/client/dist/assets/recovery-BluNHoXM.js +1 -0
- package/client/dist/assets/recovery-CRvEmB0C.js +1 -0
- package/client/dist/assets/recovery-CeIoRnkR.js +1 -0
- package/client/dist/assets/recovery-DHCo8KGi.js +1 -0
- package/client/dist/assets/recovery-OxAIpbBF.js +1 -0
- package/client/dist/assets/recovery-XXexYGOJ.js +1 -0
- package/client/dist/assets/recovery-pITlc--v.js +1 -0
- package/client/dist/assets/refresh-cw-DfyTkbsf.js +1 -0
- package/client/dist/assets/select-xA3pSmqE.js +1 -0
- package/client/dist/assets/settings--yzDbX9r.js +1 -0
- package/client/dist/assets/settings-5_heTv8s.js +1 -0
- package/client/dist/assets/settings-BSf27MDg.js +1 -0
- package/client/dist/assets/settings-BSj6FakR.js +1 -0
- package/client/dist/assets/settings-BZDo_8Nn.js +1 -0
- package/client/dist/assets/settings-BdWgmNc0.js +1 -0
- package/client/dist/assets/settings-DRouxKqb.js +1 -0
- package/client/dist/assets/settings-DnWFoY-F.js +1 -0
- package/client/dist/assets/setup-BJWy62ri.js +1 -0
- package/client/dist/assets/setup-BgKOIuzc.js +1 -0
- package/client/dist/assets/setup-BvVIyUlz.js +1 -0
- package/client/dist/assets/setup-BxCk2pe1.js +1 -0
- package/client/dist/assets/setup-C-xQTL7R.js +1 -0
- package/client/dist/assets/setup-CbaVoiwV.js +1 -0
- package/client/dist/assets/setup-DxTBkX3P.js +1 -0
- package/client/dist/assets/setup-oGoVAzOD.js +1 -0
- package/client/dist/assets/specs-7tAb4IKr.js +1 -0
- package/client/dist/assets/specs-BUcY4s5v.js +1 -0
- package/client/dist/assets/specs-Bk5LeBAA.js +1 -0
- package/client/dist/assets/specs-CAA4Lrlg.js +1 -0
- package/client/dist/assets/specs-CS091AnA.js +1 -0
- package/client/dist/assets/specs-DJ6gmFcK.js +1 -0
- package/client/dist/assets/specs-GfCcrBSC.js +1 -0
- package/client/dist/assets/specs-xQgyc7WL.js +1 -0
- package/client/dist/assets/spending-CVH8VREb.js +1 -0
- package/client/dist/assets/square-Co6h5vZg.js +1 -0
- package/client/dist/assets/tauri-shell-43ixPGfa.js +2 -0
- package/client/dist/assets/terminal-0v9sBylD.js +1 -0
- package/client/dist/assets/terminal-AbUAmCxE.js +1 -0
- package/client/dist/assets/terminal-BJayIbIP.js +1 -0
- package/client/dist/assets/terminal-C2RUlXyi.js +1 -0
- package/client/dist/assets/terminal-CMmSb_Nj.js +1 -0
- package/client/dist/assets/terminal-DKWjj7HJ.js +1 -0
- package/client/dist/assets/terminal-KlFu7_pV.js +1 -0
- package/client/dist/assets/terminal-i99yqFvm.js +1 -0
- package/client/dist/assets/tickets-846Oq3i3.js +1 -0
- package/client/dist/assets/tickets-B5LJTe_b.js +1 -0
- package/client/dist/assets/tickets-Bfo2GGmH.js +1 -0
- package/client/dist/assets/tickets-BhdZ1yY2.js +1 -0
- package/client/dist/assets/tickets-CgjWJHAW.js +1 -0
- package/client/dist/assets/tickets-Ct9DbDUR.js +1 -0
- package/client/dist/assets/tickets-rptLEJB1.js +1 -0
- package/client/dist/assets/tickets-xQ6DpYdu.js +1 -0
- package/client/dist/assets/trending-up-BGvb4zZt.js +1 -0
- package/client/dist/assets/undo-6zuS4-sL.js +1 -0
- package/client/dist/assets/undo-BeM4gDOP.js +1 -0
- package/client/dist/assets/undo-BeppX8xS.js +1 -0
- package/client/dist/assets/undo-BqvNZ5MG.js +1 -0
- package/client/dist/assets/undo-BzwEPf_k.js +1 -0
- package/client/dist/assets/undo-CJ9Cu1NN.js +1 -0
- package/client/dist/assets/undo-ds8nMFbX.js +1 -0
- package/client/dist/assets/undo-x_gA-knG.js +1 -0
- package/client/dist/assets/useDesktop-BuOp2-MR.js +1 -0
- package/client/dist/assets/useRuntimeRuns-BRS6ncnO.js +1 -0
- package/client/dist/assets/utils-ELimjS2Y.js +1 -0
- package/client/dist/assets/wrench-Br2n1Lxd.js +1 -0
- package/client/dist/index.html +75 -60
- package/docs/ci-cd.md +29 -1
- package/docs/cli.md +10 -31
- package/docs/codex.md +1 -1
- package/docs/creating-specs.md +15 -12
- package/docs/customizing.md +16 -13
- package/docs/getting-started.md +12 -11
- package/docs/guide/de/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/de/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/de/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/de/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
- package/docs/guide/de/getting-started/6-universal-search.md +34 -0
- package/docs/guide/de/insights/1-analytics-and-cost-tracking.md +20 -6
- package/docs/guide/de/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/de/insights/3-code-explorer.md +1 -1
- package/docs/guide/de/integrations/1-ai-providers.md +1 -1
- package/docs/guide/de/integrations/2-plugins.md +1 -1
- package/docs/guide/de/integrations/3-jira-integration.md +3 -3
- package/docs/guide/de/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/de/integrations/5-mcp-server.md +1 -1
- package/docs/guide/de/integrations/6-agent-chat.md +12 -5
- package/docs/guide/de/integrations/8-flow-mode.md +69 -0
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +21 -1
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +12 -0
- package/docs/guide/de/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/de/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/de/settings/1-themes.md +1 -1
- package/docs/guide/de/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
- package/docs/guide/de/settings/5-project-environment.md +1 -1
- package/docs/guide/de/settings/6-updates.md +24 -0
- package/docs/guide/de/settings/7-existing-projects.md +33 -0
- package/docs/guide/de/settings/8-accessibility.md +23 -0
- package/docs/guide/de/specs/1-specs-and-the-backlog.md +41 -3
- package/docs/guide/de/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/de/specs/3-add-spec-explore-mode.md +1 -1
- package/docs/guide/en/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/en/getting-started/1-what-is-specrails.md +1 -1
- package/docs/guide/en/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/en/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/en/getting-started/5-the-dashboard-tour.md +52 -0
- package/docs/guide/en/getting-started/6-universal-search.md +34 -0
- package/docs/guide/en/insights/1-analytics-and-cost-tracking.md +24 -10
- package/docs/guide/en/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/en/insights/3-code-explorer.md +5 -5
- package/docs/guide/en/integrations/1-ai-providers.md +1 -1
- package/docs/guide/en/integrations/2-plugins.md +1 -1
- package/docs/guide/en/integrations/3-jira-integration.md +4 -4
- package/docs/guide/en/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/en/integrations/5-mcp-server.md +4 -4
- package/docs/guide/en/integrations/6-agent-chat.md +12 -5
- package/docs/guide/en/integrations/8-flow-mode.md +69 -0
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +22 -3
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +19 -7
- package/docs/guide/en/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/en/pipeline/5-the-loop-builder.md +2 -2
- package/docs/guide/en/settings/1-themes.md +1 -1
- package/docs/guide/en/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
- package/docs/guide/en/settings/5-project-environment.md +1 -1
- package/docs/guide/en/settings/6-updates.md +24 -0
- package/docs/guide/en/settings/7-existing-projects.md +33 -0
- package/docs/guide/en/settings/8-accessibility.md +23 -0
- package/docs/guide/en/specs/1-specs-and-the-backlog.md +42 -6
- package/docs/guide/en/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/en/specs/3-add-spec-explore-mode.md +2 -2
- package/docs/guide/es/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/es/agents/3-customizing-models-per-agent.md +2 -2
- package/docs/guide/es/agents/4-custom-agents-catalog.md +1 -1
- package/docs/guide/es/getting-started/1-what-is-specrails.md +3 -3
- package/docs/guide/es/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/es/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/es/getting-started/5-the-dashboard-tour.md +52 -0
- package/docs/guide/es/getting-started/6-universal-search.md +34 -0
- package/docs/guide/es/insights/1-analytics-and-cost-tracking.md +26 -12
- package/docs/guide/es/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/es/insights/3-code-explorer.md +5 -5
- package/docs/guide/es/integrations/1-ai-providers.md +1 -1
- package/docs/guide/es/integrations/2-plugins.md +1 -1
- package/docs/guide/es/integrations/3-jira-integration.md +4 -4
- package/docs/guide/es/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/es/integrations/5-mcp-server.md +4 -4
- package/docs/guide/es/integrations/6-agent-chat.md +14 -7
- package/docs/guide/es/integrations/7-local-engines.md +1 -1
- package/docs/guide/es/integrations/8-flow-mode.md +69 -0
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +33 -13
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +38 -26
- package/docs/guide/es/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/es/pipeline/5-the-loop-builder.md +4 -4
- package/docs/guide/es/settings/1-themes.md +1 -1
- package/docs/guide/es/settings/3-pipeline-telemetry-and-diagnostics.md +10 -10
- package/docs/guide/es/settings/5-project-environment.md +1 -1
- package/docs/guide/es/settings/6-updates.md +24 -0
- package/docs/guide/es/settings/7-existing-projects.md +33 -0
- package/docs/guide/es/settings/8-accessibility.md +23 -0
- package/docs/guide/es/specs/1-specs-and-the-backlog.md +43 -7
- package/docs/guide/es/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/es/specs/3-add-spec-explore-mode.md +3 -3
- package/docs/guide/fr/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/fr/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/fr/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/fr/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
- package/docs/guide/fr/getting-started/6-universal-search.md +34 -0
- package/docs/guide/fr/insights/1-analytics-and-cost-tracking.md +18 -4
- package/docs/guide/fr/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/fr/insights/3-code-explorer.md +1 -1
- package/docs/guide/fr/integrations/1-ai-providers.md +1 -1
- package/docs/guide/fr/integrations/2-plugins.md +1 -1
- package/docs/guide/fr/integrations/3-jira-integration.md +3 -3
- package/docs/guide/fr/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/fr/integrations/5-mcp-server.md +1 -1
- package/docs/guide/fr/integrations/6-agent-chat.md +11 -4
- package/docs/guide/fr/integrations/8-flow-mode.md +69 -0
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +21 -1
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +12 -0
- package/docs/guide/fr/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/fr/settings/1-themes.md +1 -1
- package/docs/guide/fr/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
- package/docs/guide/fr/settings/5-project-environment.md +1 -1
- package/docs/guide/fr/settings/6-updates.md +24 -0
- package/docs/guide/fr/settings/7-existing-projects.md +33 -0
- package/docs/guide/fr/settings/8-accessibility.md +23 -0
- package/docs/guide/fr/specs/1-specs-and-the-backlog.md +41 -3
- package/docs/guide/fr/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/fr/specs/3-add-spec-explore-mode.md +1 -1
- package/docs/guide/it/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/it/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/it/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/it/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
- package/docs/guide/it/getting-started/6-universal-search.md +34 -0
- package/docs/guide/it/insights/1-analytics-and-cost-tracking.md +18 -4
- package/docs/guide/it/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/it/insights/3-code-explorer.md +1 -1
- package/docs/guide/it/integrations/1-ai-providers.md +1 -1
- package/docs/guide/it/integrations/2-plugins.md +1 -1
- package/docs/guide/it/integrations/3-jira-integration.md +3 -3
- package/docs/guide/it/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/it/integrations/5-mcp-server.md +1 -1
- package/docs/guide/it/integrations/6-agent-chat.md +11 -4
- package/docs/guide/it/integrations/8-flow-mode.md +69 -0
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +21 -1
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +12 -0
- package/docs/guide/it/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/it/settings/1-themes.md +1 -1
- package/docs/guide/it/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
- package/docs/guide/it/settings/5-project-environment.md +1 -1
- package/docs/guide/it/settings/6-updates.md +24 -0
- package/docs/guide/it/settings/7-existing-projects.md +33 -0
- package/docs/guide/it/settings/8-accessibility.md +23 -0
- package/docs/guide/it/specs/1-specs-and-the-backlog.md +41 -3
- package/docs/guide/it/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/it/specs/3-add-spec-explore-mode.md +1 -1
- package/docs/guide/ja/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/ja/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/ja/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/ja/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
- package/docs/guide/ja/getting-started/6-universal-search.md +34 -0
- package/docs/guide/ja/insights/1-analytics-and-cost-tracking.md +18 -4
- package/docs/guide/ja/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/ja/insights/3-code-explorer.md +1 -1
- package/docs/guide/ja/integrations/1-ai-providers.md +1 -1
- package/docs/guide/ja/integrations/2-plugins.md +1 -1
- package/docs/guide/ja/integrations/3-jira-integration.md +3 -3
- package/docs/guide/ja/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/ja/integrations/5-mcp-server.md +1 -1
- package/docs/guide/ja/integrations/6-agent-chat.md +11 -4
- package/docs/guide/ja/integrations/8-flow-mode.md +69 -0
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +21 -1
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +12 -0
- package/docs/guide/ja/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/ja/settings/1-themes.md +1 -1
- package/docs/guide/ja/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
- package/docs/guide/ja/settings/5-project-environment.md +1 -1
- package/docs/guide/ja/settings/6-updates.md +24 -0
- package/docs/guide/ja/settings/7-existing-projects.md +33 -0
- package/docs/guide/ja/settings/8-accessibility.md +23 -0
- package/docs/guide/ja/specs/1-specs-and-the-backlog.md +41 -3
- package/docs/guide/ja/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/ja/specs/3-add-spec-explore-mode.md +1 -1
- package/docs/guide/pt/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/pt/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/pt/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/pt/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
- package/docs/guide/pt/getting-started/6-universal-search.md +34 -0
- package/docs/guide/pt/insights/1-analytics-and-cost-tracking.md +18 -4
- package/docs/guide/pt/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/pt/insights/3-code-explorer.md +1 -1
- package/docs/guide/pt/integrations/1-ai-providers.md +1 -1
- package/docs/guide/pt/integrations/2-plugins.md +1 -1
- package/docs/guide/pt/integrations/3-jira-integration.md +3 -3
- package/docs/guide/pt/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/pt/integrations/5-mcp-server.md +1 -1
- package/docs/guide/pt/integrations/6-agent-chat.md +12 -5
- package/docs/guide/pt/integrations/8-flow-mode.md +69 -0
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +21 -1
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +12 -0
- package/docs/guide/pt/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/pt/settings/1-themes.md +1 -1
- package/docs/guide/pt/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
- package/docs/guide/pt/settings/5-project-environment.md +1 -1
- package/docs/guide/pt/settings/6-updates.md +24 -0
- package/docs/guide/pt/settings/7-existing-projects.md +33 -0
- package/docs/guide/pt/settings/8-accessibility.md +23 -0
- package/docs/guide/pt/specs/1-specs-and-the-backlog.md +41 -3
- package/docs/guide/pt/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/pt/specs/3-add-spec-explore-mode.md +1 -1
- package/docs/guide/zh/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/zh/getting-started/2-installing-and-first-run.md +2 -0
- package/docs/guide/zh/getting-started/3-try-the-sample-project.md +35 -0
- package/docs/guide/zh/getting-started/{4-the-dashboard-tour.md → 5-the-dashboard-tour.md} +7 -3
- package/docs/guide/zh/getting-started/6-universal-search.md +34 -0
- package/docs/guide/zh/insights/1-analytics-and-cost-tracking.md +18 -4
- package/docs/guide/zh/insights/2-the-integrated-terminal.md +1 -1
- package/docs/guide/zh/insights/3-code-explorer.md +1 -1
- package/docs/guide/zh/integrations/1-ai-providers.md +1 -1
- package/docs/guide/zh/integrations/2-plugins.md +1 -1
- package/docs/guide/zh/integrations/3-jira-integration.md +3 -3
- package/docs/guide/zh/integrations/4-mobile-companion.md +1 -1
- package/docs/guide/zh/integrations/5-mcp-server.md +1 -1
- package/docs/guide/zh/integrations/6-agent-chat.md +11 -4
- package/docs/guide/zh/integrations/8-flow-mode.md +69 -0
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +21 -1
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +12 -0
- package/docs/guide/zh/pipeline/3-reviewing-a-delivery.md +43 -0
- package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/zh/settings/1-themes.md +1 -1
- package/docs/guide/zh/settings/3-pipeline-telemetry-and-diagnostics.md +2 -2
- package/docs/guide/zh/settings/5-project-environment.md +1 -1
- package/docs/guide/zh/settings/6-updates.md +24 -0
- package/docs/guide/zh/settings/7-existing-projects.md +33 -0
- package/docs/guide/zh/settings/8-accessibility.md +23 -0
- package/docs/guide/zh/specs/1-specs-and-the-backlog.md +41 -3
- package/docs/guide/zh/specs/2-add-spec-quick-mode.md +1 -1
- package/docs/guide/zh/specs/3-add-spec-explore-mode.md +1 -1
- package/docs/internals/README.md +8 -0
- package/docs/internals/adding-a-provider.md +19 -2
- package/docs/internals/agent-actions-audit.md +101 -0
- package/docs/internals/agent-sessions.md +36 -1
- package/docs/internals/api-reference.md +190 -45
- package/docs/internals/architecture.md +53 -47
- package/docs/internals/companion-inbox-decisions.md +42 -0
- package/docs/internals/companion-rails-as-loops-contract.md +17 -6
- package/docs/internals/configuration.md +140 -9
- package/docs/internals/core-runtime-updates.md +4 -4
- package/docs/internals/existing-project-anchoring.md +168 -0
- package/docs/internals/flow-mode.md +668 -0
- package/docs/internals/legacy-implementation-notes.md +13 -0
- package/docs/internals/local-testing-feedback-2026-10.md +210 -0
- package/docs/internals/mcp-mission-audit.md +4 -0
- package/docs/internals/mission-rail-cards.md +10 -5
- package/docs/internals/mission-read-only-policy.md +152 -0
- package/docs/internals/modal-standard.md +181 -0
- package/docs/internals/openspec-workflow.md +32 -0
- package/docs/internals/operations-runbook.md +30 -0
- package/docs/internals/profiles.md +6 -3
- package/docs/internals/programmatic-agent-runtime.md +8 -0
- package/docs/internals/project-builder.md +1 -1
- package/docs/internals/review-packet.md +161 -9
- package/docs/internals/safe-pr-review-flow.md +135 -6
- package/docs/internals/source-map.md +413 -18
- package/docs/internals/spec-addenda.md +10 -0
- package/docs/internals/spec-triage.md +140 -0
- package/docs/internals/visual-design-audit.md +15 -2
- package/docs/local-providers.md +3 -0
- package/docs/mcp.md +21 -3
- package/docs/platforms/macos.md +1 -1
- package/docs/platforms/windows.md +2 -2
- package/docs/running-pipelines.md +22 -6
- package/docs/tracking-cost.md +54 -10
- package/local-runner/dist/specrails-local-runner.js +3851 -1178
- package/mcp-bridge/dist/specrails-mcp.js +3864 -1143
- package/package.json +10 -9
- package/server/dist/agent-mcp-config.js +37 -1
- package/server/dist/api-version.js +19 -0
- package/server/dist/command-resolver.js +4 -2
- package/server/dist/core-compat.js +1 -1
- package/server/dist/core-execution.js +2 -1
- package/server/dist/core-update-manager.js +71 -13
- package/server/dist/db/job-search.js +248 -0
- package/server/dist/db/jobs.js +6 -0
- package/server/dist/db/migrations.js +239 -0
- package/server/dist/db.js +9 -2
- package/server/dist/desktop-db.js +99 -5
- package/server/dist/desktop-router.js +126 -13
- package/server/dist/docs-router.js +67 -1
- package/server/dist/feature-flags.js +22 -0
- package/server/dist/index.js +30 -15
- package/server/dist/jira/jira-adf.js +13 -1
- package/server/dist/jira/jira-clarifications.js +146 -0
- package/server/dist/jira/jira-client.js +8 -1
- package/server/dist/jira/jira-db.js +41 -0
- package/server/dist/jira/jira-sync-manager.js +328 -25
- package/server/dist/mcp/guide.js +17 -7
- package/server/dist/mcp/tools/agents.js +1 -1
- package/server/dist/mcp/tools/analytics.js +15 -3
- package/server/dist/mcp/tools/app-settings.js +14 -1
- package/server/dist/mcp/tools/chat.js +1 -1
- package/server/dist/mcp/tools/env.js +4 -2
- package/server/dist/mcp/tools/jobs.js +96 -7
- package/server/dist/mcp/tools/loops.js +1 -1
- package/server/dist/mcp/tools/meta.js +10 -13
- package/server/dist/mcp/tools/rails.js +15 -1
- package/server/dist/mcp/tools/setup.js +1 -1
- package/server/dist/mcp/tools/specs.js +8 -5
- package/server/dist/mcp/tools/support.js +6 -3
- package/server/dist/mcp/tools/types.js +38 -1
- package/server/dist/mobile/mobile-admin-router.js +0 -16
- package/server/dist/mobile/mobile-gateway.js +0 -18
- package/server/dist/mobile/mobile-inbox.js +240 -0
- package/server/dist/mobile/mobile-missions.js +6 -8
- package/server/dist/mobile/mobile-router.js +9 -9
- package/server/dist/mobile/mobile-webrtc-peer.js +4 -54
- package/server/dist/mobile/mobile-ws.js +27 -4
- package/server/dist/modules/accounting/runtime/ai-invocations.js +4 -0
- package/server/dist/modules/accounting/runtime/decision-times.js +102 -0
- package/server/dist/modules/accounting/runtime/loop-economics.js +284 -0
- package/server/dist/modules/accounting/runtime/spending.js +7 -2
- package/server/dist/modules/accounting/runtime/what-if.js +87 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +86 -5
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-controls.js +28 -2
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +15 -2
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +21 -2
- package/server/dist/modules/agent-runtime/runtime/core-capabilities.js +55 -0
- package/server/dist/modules/agent-sessions/adapters/host-process.js +1 -1
- package/server/dist/modules/agent-sessions/domain/availability.js +16 -0
- package/server/dist/modules/agent-sessions/domain/protocol.js +8 -1
- package/server/dist/modules/agent-sessions/index.js +3 -1
- package/server/dist/modules/agent-sessions/runtime/core-sessions-availability.js +16 -0
- package/server/dist/modules/agents/runtime/agent-refine-manager.js +3 -1
- package/server/dist/modules/agents/runtime/agent-store.js +60 -73
- package/server/dist/modules/audit/adapters/http.js +66 -0
- package/server/dist/modules/audit/adapters/runtime.js +60 -0
- package/server/dist/modules/audit/adapters/sqlite.js +73 -0
- package/server/dist/modules/audit/application.js +190 -0
- package/server/dist/modules/audit/domain.js +434 -0
- package/server/dist/modules/audit/index.js +27 -0
- package/server/dist/modules/audit/ports.js +2 -0
- package/server/dist/modules/browser/runtime/browser-capture-manager.js +18 -141
- package/server/dist/modules/browser/runtime/browser-capture-types.js +1 -10
- package/server/dist/modules/browser/runtime/browser-playwright.js +0 -19
- package/server/dist/modules/code/runtime/file-provenance.js +23 -0
- package/server/dist/modules/conversations/runtime/chat-manager.js +5 -2
- package/server/dist/modules/delivery/adapters/decisions/chains.js +1 -0
- package/server/dist/modules/delivery/adapters/decisions/create.js +19 -1
- package/server/dist/modules/delivery/adapters/decisions/discard.js +2 -0
- package/server/dist/modules/delivery/adapters/decisions/local-changes.js +427 -0
- package/server/dist/modules/delivery/adapters/decisions/merge-local.js +80 -6
- package/server/dist/modules/delivery/adapters/decisions/observations.js +5 -0
- package/server/dist/modules/delivery/adapters/decisions/ownership.js +2 -1
- package/server/dist/modules/delivery/adapters/decisions/transitions.js +9 -0
- package/server/dist/modules/delivery/adapters/review-wip-store.js +37 -0
- package/server/dist/modules/delivery/domain/review-wip.js +71 -0
- package/server/dist/modules/delivery/index.js +9 -1
- package/server/dist/modules/delivery/runtime/delivery-changes.js +355 -0
- package/server/dist/modules/delivery/runtime/delivery-evidence.js +249 -8
- package/server/dist/modules/delivery/runtime/flow-review-legacy.js +99 -0
- package/server/dist/modules/delivery/runtime/flow-review-outcome.js +107 -0
- package/server/dist/modules/delivery/runtime/flow-worktree-handoff.js +32 -0
- package/server/dist/modules/delivery/runtime/flow-worktree-return.js +87 -0
- package/server/dist/modules/delivery/runtime/isolated-worktree.js +380 -0
- package/server/dist/modules/delivery/runtime/local-restore-branch.js +325 -0
- package/server/dist/modules/delivery/runtime/local-restore-resolver.js +48 -0
- package/server/dist/modules/delivery/runtime/local-stash.js +423 -0
- package/server/dist/modules/delivery/runtime/multi-repo-execution.js +27 -1
- package/server/dist/modules/delivery/runtime/phase3-harvest.js +40 -0
- package/server/dist/modules/delivery/runtime/pr-body.js +50 -0
- package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +169 -166
- package/server/dist/modules/delivery/runtime/rail-launch-parser.js +5 -2
- package/server/dist/modules/delivery/runtime/rail-pr-decision.js +7 -1
- package/server/dist/modules/delivery/runtime/rail-pr-store.js +193 -12
- package/server/dist/modules/delivery/runtime/rails-router.js +267 -5
- package/server/dist/modules/delivery/runtime/review-brief.js +208 -0
- package/server/dist/modules/delivery/runtime/review-packet.js +41 -2
- package/server/dist/modules/delivery/runtime/review-wip-gate.js +67 -0
- package/server/dist/modules/delivery/runtime/run-records.js +267 -0
- package/server/dist/modules/delivery/runtime/run-review-diagnosis.js +102 -0
- package/server/dist/modules/execution/adapters/budget-storage.js +76 -0
- package/server/dist/modules/execution/application/enforce-budget.js +17 -2
- package/server/dist/modules/execution/domain/agent-env.js +98 -0
- package/server/dist/modules/execution/domain/daily-budget.js +36 -0
- package/server/dist/modules/execution/domain/spend-caps.js +166 -0
- package/server/dist/modules/execution/index.js +34 -1
- package/server/dist/modules/execution/runtime/budget-overview.js +76 -0
- package/server/dist/modules/execution/runtime/daily-budget-gate.js +86 -0
- package/server/dist/modules/execution/runtime/interactive-job-session.js +8 -0
- package/server/dist/modules/execution/runtime/launch-forecast.js +33 -0
- package/server/dist/modules/execution/runtime/queue-manager.js +54 -15
- package/server/dist/modules/execution/runtime/run-duration-stats.js +31 -13
- package/server/dist/modules/flow/adapters/bindings.js +1089 -0
- package/server/dist/modules/flow/adapters/http.js +147 -0
- package/server/dist/modules/flow/adapters/sqlite.js +121 -0
- package/server/dist/modules/flow/application.js +805 -0
- package/server/dist/modules/flow/domain.js +790 -0
- package/server/dist/modules/flow/index.js +34 -0
- package/server/dist/modules/flow/ports.js +2 -0
- package/server/dist/modules/inbox/adapters/http.js +21 -0
- package/server/dist/modules/inbox/adapters/project-source.js +233 -0
- package/server/dist/modules/inbox/application.js +28 -0
- package/server/dist/modules/inbox/domain.js +43 -0
- package/server/dist/modules/inbox/index.js +10 -0
- package/server/dist/modules/inbox/ports.js +2 -0
- package/server/dist/modules/loops/runtime/loop-definition-run.js +9 -0
- package/server/dist/modules/loops/runtime/loop-definition.js +5 -2
- package/server/dist/modules/loops/runtime/loop-executors.js +90 -9
- package/server/dist/modules/loops/runtime/loop-factory.js +30 -2
- package/server/dist/modules/loops/runtime/loop-flow-spec-recipe.js +166 -0
- package/server/dist/modules/loops/runtime/loop-graph.js +1 -1
- package/server/dist/modules/loops/runtime/loop-role-engines.js +4 -1
- package/server/dist/modules/loops/runtime/loop-run-manager.js +267 -10
- package/server/dist/modules/loops/runtime/loop-runs-store.js +21 -5
- package/server/dist/modules/loops/runtime/loop-templates.js +55 -12
- package/server/dist/modules/missions/runtime/agent-chat-manager.js +283 -20
- package/server/dist/modules/missions/runtime/agent-chat-router.js +96 -21
- package/server/dist/modules/missions/runtime/agent-failure-briefing.js +11 -3
- package/server/dist/modules/missions/runtime/agent-fence-promotion.js +9 -1
- package/server/dist/modules/missions/runtime/agent-flow-prompt.js +64 -0
- package/server/dist/modules/missions/runtime/agent-input-store.js +9 -4
- package/server/dist/modules/missions/runtime/agent-operator-prompt.js +100 -14
- package/server/dist/modules/missions/runtime/agent-session-store.js +88 -27
- package/server/dist/modules/missions/runtime/core-session-runner.js +89 -9
- package/server/dist/modules/missions/runtime/flow-turn-context.js +17 -0
- package/server/dist/modules/missions/runtime/mission-core-sessions.js +295 -55
- package/server/dist/modules/missions/runtime/mission-run-notify.js +2 -0
- package/server/dist/modules/missions/runtime/mission-session-projector.js +56 -19
- package/server/dist/modules/missions/runtime/mission-tool-policy.js +47 -0
- package/server/dist/modules/onboarding/adapters/http.js +78 -0
- package/server/dist/modules/onboarding/adapters/providers.js +41 -0
- package/server/dist/modules/onboarding/adapters/runtime.js +130 -0
- package/server/dist/modules/onboarding/application.js +133 -0
- package/server/dist/modules/onboarding/catalog.js +217 -0
- package/server/dist/modules/onboarding/domain.js +102 -0
- package/server/dist/modules/onboarding/index.js +20 -0
- package/server/dist/modules/onboarding/ports.js +2 -0
- package/server/dist/modules/project-rules/adapters/http.js +91 -0
- package/server/dist/modules/project-rules/domain.js +122 -0
- package/server/dist/modules/project-rules/runtime/rules-inventory-runs.js +97 -0
- package/server/dist/modules/project-rules/runtime/rules-store.js +109 -0
- package/server/dist/modules/project-settings/adapters/http.js +13 -0
- package/server/dist/modules/project-settings/adapters/sqlite.js +78 -8
- package/server/dist/modules/project-settings/domain.js +47 -1
- package/server/dist/modules/project-settings/index.js +7 -1
- package/server/dist/modules/recovery/adapters/sqlite.js +28 -0
- package/server/dist/modules/recovery/domain.js +162 -0
- package/server/dist/modules/recovery/index.js +16 -0
- package/server/dist/modules/specs/adapters/timeline-http.js +101 -0
- package/server/dist/modules/specs/domain/handoff-labels.js +371 -0
- package/server/dist/modules/specs/domain/handoff.js +260 -0
- package/server/dist/modules/specs/domain/non-goals.js +101 -0
- package/server/dist/modules/specs/domain/timeline.js +164 -0
- package/server/dist/modules/specs/domain/triage.js +320 -0
- package/server/dist/modules/specs/runtime/contract-refine-runner.js +3 -2
- package/server/dist/modules/specs/runtime/generated-spec-parser.js +75 -0
- package/server/dist/modules/specs/runtime/proposal-manager.js +4 -3
- package/server/dist/modules/specs/runtime/smash-runner.js +2 -1
- package/server/dist/modules/specs/runtime/spec-addenda.js +31 -0
- package/server/dist/modules/specs/runtime/spec-draft-parser.js +6 -1
- package/server/dist/modules/specs/runtime/spec-generation.js +431 -0
- package/server/dist/modules/specs/runtime/spec-handoff.js +103 -0
- package/server/dist/modules/specs/runtime/spec-history.js +376 -0
- package/server/dist/modules/specs/runtime/spec-launcher-manager.js +4 -3
- package/server/dist/modules/specs/runtime/spec-search.js +117 -0
- package/server/dist/modules/specs/runtime/ticket-store.js +47 -2
- package/server/dist/modules/specs/runtime/ticket-trash-service.js +62 -0
- package/server/dist/modules/specs/runtime/ticket-trash.js +193 -0
- package/server/dist/modules/specs/runtime/triage-runner.js +171 -0
- package/server/dist/modules/specs/runtime/triage.js +365 -0
- package/server/dist/modules/terminals/domain/app-urls.js +96 -0
- package/server/dist/modules/terminals/runtime/app-urls.js +77 -0
- package/server/dist/modules/terminals/runtime/background-process-service.js +25 -28
- package/server/dist/project-env.js +60 -0
- package/server/dist/project-git.js +65 -0
- package/server/dist/project-registry.js +264 -27
- package/server/dist/project-router-background-processes.js +27 -3
- package/server/dist/project-router-git.js +30 -0
- package/server/dist/project-router-helpers.js +5 -30
- package/server/dist/project-router-jobs.js +49 -1
- package/server/dist/project-router-loop-runs.js +72 -2
- package/server/dist/project-router-rules.js +54 -0
- package/server/dist/project-router-search.js +52 -0
- package/server/dist/project-router-settings.js +6 -0
- package/server/dist/project-router-setup.js +1 -1
- package/server/dist/project-router-spending.js +138 -0
- package/server/dist/project-router-tickets.js +246 -427
- package/server/dist/project-router.js +7 -0
- package/server/dist/providers/claude-adapter.js +25 -3
- package/server/dist/providers/codex-adapter.js +9 -1
- package/server/dist/providers/gemini-adapter.js +6 -1
- package/server/dist/providers/kimi-adapter.js +2 -0
- package/server/dist/providers/local-adapter.js +2 -0
- package/server/dist/providers/runtime.js +8 -0
- package/server/dist/schemas/agent-runtime.schema.json +3 -1
- package/server/dist/schemas/workflow-definition.schema.json +1 -0
- package/server/dist/setup-manager.js +19 -1
- package/server/dist/transient-children.js +25 -8
- package/server/dist/update-channel.js +21 -0
- package/server/dist/util/search-snippet.js +74 -0
- package/server/dist/worktree-manager.js +19 -8
- package/client/dist/assets/ActivityFeedPage-Dtp7EyHc.js +0 -1
- package/client/dist/assets/AgentBrowserCapture-CLqlEFw8.js +0 -1
- package/client/dist/assets/AgentModeAnalyticsPane-B8_hM3Tw.js +0 -2
- package/client/dist/assets/AgentModeCodePane-CNF8ZNjE.js +0 -2
- package/client/dist/assets/AgentModeJobsPane-CJpJbO9m.js +0 -1
- package/client/dist/assets/AgentsPage-BC8XSR79.js +0 -120
- package/client/dist/assets/AnalyticsPage-Cdv4jLtW.js +0 -1
- package/client/dist/assets/BarChart-BDMqVFJy.js +0 -55
- package/client/dist/assets/CodePage-DI1kegAr.js +0 -3
- package/client/dist/assets/DesktopAnalyticsPage-Bdp8E8U6.js +0 -1
- package/client/dist/assets/DocsDialog-Bm4RS7FX.js +0 -11
- package/client/dist/assets/DocsPage-DihYcU8r.js +0 -11
- package/client/dist/assets/ExportDropdown-Bb1lHx3r.js +0 -1
- package/client/dist/assets/IntegrationsPage-EAipiDWm.js +0 -1
- package/client/dist/assets/InteractiveJobComposer-BO6ASN-2.js +0 -19
- package/client/dist/assets/JobDetailModal-CuPYq7tP.js +0 -1
- package/client/dist/assets/JobDetailPage-BusMjJi9.js +0 -1
- package/client/dist/assets/JobsPage-C0QbsF2d.js +0 -1
- package/client/dist/assets/LoopBuilderPage-B7TlU4iS.js +0 -1
- package/client/dist/assets/LoopPreviewModal-BRWtXOD2.js +0 -1
- package/client/dist/assets/LoopsPage-C4q1DmCE.js +0 -2
- package/client/dist/assets/MinimizedChatsContext-DHfigjHS.js +0 -1
- package/client/dist/assets/PluginsPage-Z1JHSMdR.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-BUNj0tvN.js +0 -1
- package/client/dist/assets/RepositoryDeliveries-B4ybHOyB.js +0 -5
- package/client/dist/assets/ReviewPacketPage-hwfPNjyy.js +0 -4
- package/client/dist/assets/TemplatePreviewModal-V7FpMWuw.js +0 -1
- package/client/dist/assets/TicketDetailModalContext-Dkwo2cDs.js +0 -16
- package/client/dist/assets/Trans-BbFxRFtR.js +0 -1
- package/client/dist/assets/activity-B-rp4h_v.js +0 -1
- package/client/dist/assets/activity-C6kJpm9q.js +0 -1
- package/client/dist/assets/activity-CGx4kb_j.js +0 -1
- package/client/dist/assets/activity-CnoX2bH7.js +0 -1
- package/client/dist/assets/activity-DAyekdlt.js +0 -1
- package/client/dist/assets/activity-DCxtpT7j.js +0 -1
- package/client/dist/assets/activity-DiyjsgQV.js +0 -1
- package/client/dist/assets/activity-JzwRaWPD.js +0 -1
- package/client/dist/assets/addspec-BOvgmcgk.js +0 -1
- package/client/dist/assets/addspec-Clmyfn_R.js +0 -1
- package/client/dist/assets/addspec-CsNaBpHp.js +0 -1
- package/client/dist/assets/addspec-D2tvWmmV.js +0 -1
- package/client/dist/assets/addspec-D3nFwvD0.js +0 -1
- package/client/dist/assets/addspec-DVLEhK3w.js +0 -1
- package/client/dist/assets/addspec-DXbK-tb0.js +0 -1
- package/client/dist/assets/addspec-OHG8DFEn.js +0 -1
- package/client/dist/assets/agent-5bSixVzz.js +0 -1
- package/client/dist/assets/agent-BR4EHfhq.js +0 -1
- package/client/dist/assets/agent-C0IKkJP8.js +0 -1
- package/client/dist/assets/agent-C7li9ayC.js +0 -1
- package/client/dist/assets/agent-D0dRmEen.js +0 -1
- package/client/dist/assets/agent-DZVGHm7H.js +0 -1
- package/client/dist/assets/agent-Dip4h2YE.js +0 -1
- package/client/dist/assets/agent-Pp-P-n1p.js +0 -1
- package/client/dist/assets/agentRuntime-BxF81z52.js +0 -1
- package/client/dist/assets/agentRuntime-BxYS5V7u.js +0 -1
- package/client/dist/assets/agentRuntime-Dc9HG3BA.js +0 -1
- package/client/dist/assets/agents-B6ZsnARo.js +0 -1
- package/client/dist/assets/agents-BORdhe0K.js +0 -1
- package/client/dist/assets/agents-C6aq9Oqs.js +0 -1
- package/client/dist/assets/agents-Cbsc4bcX.js +0 -1
- package/client/dist/assets/agents-D0uYR6hq.js +0 -1
- package/client/dist/assets/agents-Doe1sHY5.js +0 -1
- package/client/dist/assets/agents-DyNi_I9m.js +0 -1
- package/client/dist/assets/agents-StKxiTg0.js +0 -1
- package/client/dist/assets/agentstudio-7cYCXn-L.js +0 -1
- package/client/dist/assets/agentstudio-BHWQh8G3.js +0 -1
- package/client/dist/assets/agentstudio-BjnWHyRs.js +0 -1
- package/client/dist/assets/agentstudio-BkV8vcK4.js +0 -1
- package/client/dist/assets/agentstudio-BzugqB_N.js +0 -1
- package/client/dist/assets/agentstudio-CWbp7KvH.js +0 -1
- package/client/dist/assets/agentstudio-DG6plf5o.js +0 -1
- package/client/dist/assets/agentstudio-DkZVF-Cc.js +0 -1
- package/client/dist/assets/analytics-B1DIQd4m.js +0 -1
- package/client/dist/assets/analytics-BAIZ9vE_.js +0 -1
- package/client/dist/assets/analytics-BTqgmgBd.js +0 -1
- package/client/dist/assets/analytics-BWynXPEm.js +0 -1
- package/client/dist/assets/analytics-DGcUsQ44.js +0 -1
- package/client/dist/assets/analytics-GnSnpJ4W.js +0 -1
- package/client/dist/assets/analytics-TWgYaoO0.js +0 -1
- package/client/dist/assets/analytics-kJy6Tuko.js +0 -1
- package/client/dist/assets/atom-one-dark-qiGhVQxg.js +0 -1
- package/client/dist/assets/builder-B9gorTnT.js +0 -1
- package/client/dist/assets/builder-Bvw5s3Mi.js +0 -1
- package/client/dist/assets/builder-CL5l4dU3.js +0 -1
- package/client/dist/assets/builder-CVDTVrQX.js +0 -1
- package/client/dist/assets/builder-CpS9liE9.js +0 -1
- package/client/dist/assets/builder-DNctIL9Q.js +0 -1
- package/client/dist/assets/builder-De2NxX6o.js +0 -1
- package/client/dist/assets/builder-DeYT7Y-m.js +0 -1
- package/client/dist/assets/button-4FS1ZDTp.js +0 -1
- package/client/dist/assets/chat-D_I7nU5K.js +0 -1
- package/client/dist/assets/chevron-up-6EFqEHBj.js +0 -1
- package/client/dist/assets/chunk-OB3PAWPO-B1EMk45A.js +0 -3
- package/client/dist/assets/clsx-CjueKrWZ.js +0 -1
- package/client/dist/assets/code-B37GRg9C.js +0 -1
- package/client/dist/assets/code-BBOEZbf9.js +0 -1
- package/client/dist/assets/code-BRm-jcyx.js +0 -1
- package/client/dist/assets/code-CF7w62CR.js +0 -1
- package/client/dist/assets/code-CLuvJt2r.js +0 -1
- package/client/dist/assets/code-D0RCm59f.js +0 -1
- package/client/dist/assets/code-DaZ-ZwCT.js +0 -1
- package/client/dist/assets/code-iIHkGaCL.js +0 -1
- package/client/dist/assets/commands-0XjAftla.js +0 -1
- package/client/dist/assets/commands-BAWSYHjQ.js +0 -1
- package/client/dist/assets/commands-BBwowgiE.js +0 -1
- package/client/dist/assets/commands-BacjIZLN.js +0 -1
- package/client/dist/assets/commands-Bs62IAZ3.js +0 -1
- package/client/dist/assets/commands-CLPdh-Hh.js +0 -1
- package/client/dist/assets/commands-DlbFzgrp.js +0 -1
- package/client/dist/assets/commands-LjPSsi5F.js +0 -1
- package/client/dist/assets/common-Bdi0qN4S.js +0 -1
- package/client/dist/assets/common-Bhb9zN1P.js +0 -1
- package/client/dist/assets/common-BykKlZg1.js +0 -1
- package/client/dist/assets/common-CvnNNSJA.js +0 -1
- package/client/dist/assets/common-D5zk_mqq.js +0 -1
- package/client/dist/assets/common-DQNO_al5.js +0 -1
- package/client/dist/assets/common-Dax30Vmp.js +0 -1
- package/client/dist/assets/common-DkllpVSb.js +0 -1
- package/client/dist/assets/core-B3mKBIh5.js +0 -1
- package/client/dist/assets/dashboard-B1ndRHuC.js +0 -1
- package/client/dist/assets/dashboard-BX7KXiqA.js +0 -1
- package/client/dist/assets/dashboard-B_BSNxcN.js +0 -1
- package/client/dist/assets/dashboard-CCeFN7-V.js +0 -1
- package/client/dist/assets/dashboard-CRl0WtFJ.js +0 -1
- package/client/dist/assets/dashboard-XGdQ5mjw.js +0 -1
- package/client/dist/assets/dashboard-_oltA6Jd.js +0 -1
- package/client/dist/assets/dashboard-bAuf5KVk.js +0 -1
- package/client/dist/assets/dialog-DtdR05v1.js +0 -45
- package/client/dist/assets/dist-js-CJ_2XX1Y.js +0 -1
- package/client/dist/assets/event-Bt7f3wXe.js +0 -1
- package/client/dist/assets/explore-BG99VGpL.js +0 -1
- package/client/dist/assets/explore-C0TjprJW.js +0 -1
- package/client/dist/assets/explore-C2dgEo7q.js +0 -1
- package/client/dist/assets/explore-C8NDHbob.js +0 -1
- package/client/dist/assets/explore-CWWgzQGR.js +0 -1
- package/client/dist/assets/explore-CcQXpdtS.js +0 -1
- package/client/dist/assets/explore-DgBACn39.js +0 -1
- package/client/dist/assets/explore-DsXAgnmJ.js +0 -1
- package/client/dist/assets/file-text-C0blZHLh.js +0 -1
- package/client/dist/assets/formatDistanceToNow-NjPHBLfB.js +0 -1
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-vJ7qUoqN.js +0 -1
- package/client/dist/assets/git-branch-yf6LE1Bw.js +0 -1
- package/client/dist/assets/index-BgbCbIua.css +0 -2
- package/client/dist/assets/index-Ce4yZtKf.js +0 -83
- package/client/dist/assets/integrations-BkpRUbvp.js +0 -1
- package/client/dist/assets/integrations-Bo8qbJf4.js +0 -1
- package/client/dist/assets/integrations-CmSrKzZb.js +0 -1
- package/client/dist/assets/integrations-DGtq26Rr.js +0 -1
- package/client/dist/assets/integrations-De38GFnQ.js +0 -1
- package/client/dist/assets/integrations-Dw6zdtb-.js +0 -1
- package/client/dist/assets/integrations-Dwl9KQp0.js +0 -1
- package/client/dist/assets/integrations-Refg_d2I.js +0 -1
- package/client/dist/assets/jira-B6OYw4CJ.js +0 -1
- package/client/dist/assets/jira-BTF6RaOe.js +0 -1
- package/client/dist/assets/jira-CEetIB2q.js +0 -1
- package/client/dist/assets/jira-CIzsZLw5.js +0 -1
- package/client/dist/assets/jira-Daw9tmpI.js +0 -1
- package/client/dist/assets/jira-FXr7u2lh.js +0 -1
- package/client/dist/assets/jira-LaNQn7yl.js +0 -1
- package/client/dist/assets/jira-api-Cabj-H0J.js +0 -1
- package/client/dist/assets/job-time-BCL7wee9.js +0 -1
- package/client/dist/assets/jobs-ARwD85B9.js +0 -1
- package/client/dist/assets/jobs-BMF1w4WT.js +0 -1
- package/client/dist/assets/jobs-CBfzGLwm.js +0 -1
- package/client/dist/assets/jobs-CPjiluBY.js +0 -1
- package/client/dist/assets/jobs-CQQd58pY.js +0 -1
- package/client/dist/assets/jobs-De3EqaO0.js +0 -1
- package/client/dist/assets/jobs-Du9-Ei9a.js +0 -1
- package/client/dist/assets/jobs-qMHbnxwC.js +0 -1
- package/client/dist/assets/layers-BCLTgHXO.js +0 -1
- package/client/dist/assets/loader-circle-BqV9xYGf.js +0 -1
- package/client/dist/assets/loop-layout-CyXj9223.js +0 -7
- package/client/dist/assets/loops-B2PhQLKR.js +0 -1
- package/client/dist/assets/loops-BqbF46st.js +0 -1
- package/client/dist/assets/loops-CINnHbfI.js +0 -1
- package/client/dist/assets/loops-D-3XhH04.js +0 -1
- package/client/dist/assets/loops-DKkEEjZ_.js +0 -1
- package/client/dist/assets/loops-DzWR5-v6.js +0 -1
- package/client/dist/assets/loops-WyWDkhok.js +0 -1
- package/client/dist/assets/loops-scD5fIBf.js +0 -1
- package/client/dist/assets/mcp-6rMoZfEO.js +0 -1
- package/client/dist/assets/mcp-BD8sL5mP.js +0 -1
- package/client/dist/assets/mcp-BkcA3I5s.js +0 -1
- package/client/dist/assets/mcp-CCpSelOh.js +0 -1
- package/client/dist/assets/mcp-CUAN6ORK.js +0 -1
- package/client/dist/assets/mcp-CqbRxRTE.js +0 -1
- package/client/dist/assets/mcp-DP2YfVhO.js +0 -1
- package/client/dist/assets/mcp-DUVQamDz.js +0 -1
- package/client/dist/assets/narration-BEKMVxGm.js +0 -1
- package/client/dist/assets/narration-CjLwGKap.js +0 -1
- package/client/dist/assets/narration-DANWuGsW.js +0 -1
- package/client/dist/assets/narration-DGeEDWiT.js +0 -1
- package/client/dist/assets/narration-DJgpGwIP.js +0 -1
- package/client/dist/assets/narration-DbHnz0qV.js +0 -1
- package/client/dist/assets/narration-bZSsTZG8.js +0 -1
- package/client/dist/assets/narration-i6aKJKEc.js +0 -1
- package/client/dist/assets/nav--u7iPYlS.js +0 -1
- package/client/dist/assets/nav-C5Jgfaby.js +0 -1
- package/client/dist/assets/nav-CAna_Wpt.js +0 -1
- package/client/dist/assets/nav-CCLqeyHo.js +0 -1
- package/client/dist/assets/nav-Cf3c90Jk.js +0 -1
- package/client/dist/assets/nav-DMYQaQjR.js +0 -1
- package/client/dist/assets/nav-Df_PkZ9F.js +0 -1
- package/client/dist/assets/nav-VyNGBJwj.js +0 -1
- package/client/dist/assets/packet-8nn9RsU7.js +0 -1
- package/client/dist/assets/packet-B0H15elv.js +0 -1
- package/client/dist/assets/packet-BQvBgrwh.js +0 -1
- package/client/dist/assets/packet-BR7mO0-a.js +0 -1
- package/client/dist/assets/packet-BgcQ6q_K.js +0 -1
- package/client/dist/assets/packet-D2s92Jnn.js +0 -1
- package/client/dist/assets/packet-YbtcD1HS.js +0 -1
- package/client/dist/assets/packet-c0Qj_9eX.js +0 -1
- package/client/dist/assets/project-repositories-Cnnuj9Ia.js +0 -1
- package/client/dist/assets/rotate-ccw-DalJAQQX.js +0 -1
- package/client/dist/assets/settings-B1NV8Ow9.js +0 -1
- package/client/dist/assets/settings-BQ8XFZeE.js +0 -1
- package/client/dist/assets/settings-BRkxfBbO.js +0 -1
- package/client/dist/assets/settings-C_CcU1dP.js +0 -1
- package/client/dist/assets/settings-Cto9n0eL.js +0 -1
- package/client/dist/assets/settings-Pyw8uYtL.js +0 -1
- package/client/dist/assets/settings-b3HVCNNd.js +0 -1
- package/client/dist/assets/settings-hdive4u6.js +0 -1
- package/client/dist/assets/setup-Be485n2u.js +0 -1
- package/client/dist/assets/setup-CKGUxKr-.js +0 -1
- package/client/dist/assets/setup-Ck1Uwd7_.js +0 -1
- package/client/dist/assets/setup-Cm774a6v.js +0 -1
- package/client/dist/assets/setup-DIqMQpxt.js +0 -1
- package/client/dist/assets/setup-DfCsoNFL.js +0 -1
- package/client/dist/assets/setup-DkeE8mP0.js +0 -1
- package/client/dist/assets/setup-xVntVaz1.js +0 -1
- package/client/dist/assets/specs-Bqvtz2kz.js +0 -1
- package/client/dist/assets/specs-CKes-kz6.js +0 -1
- package/client/dist/assets/specs-CfXxPDNB.js +0 -1
- package/client/dist/assets/specs-CyF9HuTI.js +0 -1
- package/client/dist/assets/specs-DMj035Mt.js +0 -1
- package/client/dist/assets/specs-DfIdoU5L.js +0 -1
- package/client/dist/assets/specs-j5pGLQeU.js +0 -1
- package/client/dist/assets/specs-xW5pkkB7.js +0 -1
- package/client/dist/assets/spending-CQnrWiR3.js +0 -1
- package/client/dist/assets/square-D0JTbRSR.js +0 -1
- package/client/dist/assets/tauri-shell-DE6LfGPw.js +0 -2
- package/client/dist/assets/terminal-BAzpHtpY.js +0 -1
- package/client/dist/assets/terminal-C7dHeR3x.js +0 -1
- package/client/dist/assets/terminal-CMla5Qsz.js +0 -1
- package/client/dist/assets/terminal-CdNXH-n9.js +0 -1
- package/client/dist/assets/terminal-Cw5bZsmV.js +0 -1
- package/client/dist/assets/terminal-DFUP4eNv.js +0 -1
- package/client/dist/assets/terminal-DGqljeK_.js +0 -1
- package/client/dist/assets/terminal-cU70NodO.js +0 -1
- package/client/dist/assets/tickets--tiSOCcn.js +0 -1
- package/client/dist/assets/tickets-BUJ3DMWU.js +0 -1
- package/client/dist/assets/tickets-C1WNPODq.js +0 -1
- package/client/dist/assets/tickets-CDjhWmiE.js +0 -1
- package/client/dist/assets/tickets-CLgPC3uO.js +0 -1
- package/client/dist/assets/tickets-D41ZMQpf.js +0 -1
- package/client/dist/assets/tickets-DEaQC06P.js +0 -1
- package/client/dist/assets/tickets-kcMzbLCp.js +0 -1
- package/client/dist/assets/trash-D8zYUmTg.js +0 -1
- package/client/dist/assets/useDesktop-BjLT0_EE.js +0 -1
- package/client/dist/assets/useRuntimeRuns-C97qEqMg.js +0 -1
- package/client/dist/assets/useSharedWebSocket-Bj4LMp7b.js +0 -2
- package/client/dist/assets/utils-BC4DHlz2.js +0 -1
- package/docs/guide/en/getting-started/4-the-dashboard-tour.md +0 -48
- package/docs/guide/es/getting-started/4-the-dashboard-tour.md +0 -48
- package/server/dist/mobile/mobile-preview-channel.js +0 -179
- package/server/dist/mobile/mobile-preview.js +0 -366
- package/server/dist/modules/browser/domain/preview-origins.js +0 -117
- package/server/dist/modules/browser/runtime/preview-targets.js +0 -80
- /package/client/dist/assets/{atom-one-dark-B-oHczHB.css → DocView-B-oHczHB.css} +0 -0
- /package/docs/guide/de/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
- /package/docs/guide/en/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
- /package/docs/guide/es/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
- /package/docs/guide/fr/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
- /package/docs/guide/it/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
- /package/docs/guide/ja/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
- /package/docs/guide/pt/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
- /package/docs/guide/zh/getting-started/{3-adding-your-first-project.md → 4-adding-your-first-project.md} +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLARIFICATION_REPLY_WINDOW_MS = void 0;
|
|
4
|
+
exports.clarificationsDigest = clarificationsDigest;
|
|
5
|
+
exports.clarificationsCommentMarker = clarificationsCommentMarker;
|
|
6
|
+
exports.clarificationThreadKind = clarificationThreadKind;
|
|
7
|
+
exports.buildClarificationsComment = buildClarificationsComment;
|
|
8
|
+
exports.selectClarificationReplies = selectClarificationReplies;
|
|
9
|
+
exports.clarificationAddendumInput = clarificationAddendumInput;
|
|
10
|
+
exports.insertClarificationThread = insertClarificationThread;
|
|
11
|
+
exports.listOpenClarificationThreads = listOpenClarificationThreads;
|
|
12
|
+
exports.importedCommentIds = importedCommentIds;
|
|
13
|
+
exports.recordImportedReplies = recordImportedReplies;
|
|
14
|
+
// Architect clarifications on Jira (feedback-2026-10 task 3.2).
|
|
15
|
+
//
|
|
16
|
+
// When a run pauses with the architect's questions, or proceeds on stated
|
|
17
|
+
// assumptions (Core `architectClarifications: 1`, `clarifications.json`), and
|
|
18
|
+
// the project enabled `jiraPostClarifications`, Desktop posts them as ONE
|
|
19
|
+
// comment on each linked issue through the durable outbox (idempotency key
|
|
20
|
+
// per run, ticket and record). A human reply posted after that comment is
|
|
21
|
+
// imported once as a spec addendum of kind `clarification`, so the next launch
|
|
22
|
+
// of the spec carries the answer. Scope is deliberately narrow: only replies
|
|
23
|
+
// that follow a Specrails clarifications comment are imported; no other Jira
|
|
24
|
+
// thread is read.
|
|
25
|
+
//
|
|
26
|
+
// This file holds the pure text/selection rules and the thread table access.
|
|
27
|
+
const node_crypto_1 = require("node:crypto");
|
|
28
|
+
const jira_adf_1 = require("./jira-adf");
|
|
29
|
+
/** Replies are imported for this long after the comment was posted. */
|
|
30
|
+
exports.CLARIFICATION_REPLY_WINDOW_MS = 14 * 24 * 60 * 60 * 1000;
|
|
31
|
+
const REPLY_BODY_CAP = 8000;
|
|
32
|
+
/** Stable digest of what the comment says (a later different pause posts again). */
|
|
33
|
+
function clarificationsDigest(record) {
|
|
34
|
+
const content = record.status === 'awaiting-answers'
|
|
35
|
+
? record.blocking.map((item) => item.question)
|
|
36
|
+
: [...record.assumptions, ...record.clarifications.map((item) => `${item.question}=${item.default ?? ''}`)];
|
|
37
|
+
return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify([record.status, content])).digest('hex').slice(0, 16);
|
|
38
|
+
}
|
|
39
|
+
function clarificationsCommentMarker(runId, ticketId, digest) {
|
|
40
|
+
return `[specrails:clarifications=${runId}:ticket=${ticketId}:${digest}]`;
|
|
41
|
+
}
|
|
42
|
+
function clarificationThreadKind(record) {
|
|
43
|
+
return record.status === 'awaiting-answers' ? 'questions' : 'assumptions';
|
|
44
|
+
}
|
|
45
|
+
/** The comment body (plain text; the ADF layer renders paragraphs). */
|
|
46
|
+
function buildClarificationsComment(record) {
|
|
47
|
+
const lines = [];
|
|
48
|
+
if (record.status === 'awaiting-answers') {
|
|
49
|
+
const questions = record.blocking.length ? record.blocking : record.clarifications.filter((item) => item.impact === 'high');
|
|
50
|
+
lines.push('Specrails paused this spec before planning: the architect needs an answer to continue.');
|
|
51
|
+
lines.push('');
|
|
52
|
+
questions.forEach((item, index) => lines.push(`${index + 1}. ${item.question}`));
|
|
53
|
+
const others = record.clarifications.filter((item) => !questions.includes(item));
|
|
54
|
+
if (others.length) {
|
|
55
|
+
lines.push('');
|
|
56
|
+
lines.push('It would otherwise assume:');
|
|
57
|
+
for (const item of others)
|
|
58
|
+
lines.push(`- ${item.question} → ${item.default ?? 'no safe default'} (${item.impact} impact)`);
|
|
59
|
+
}
|
|
60
|
+
lines.push('');
|
|
61
|
+
lines.push('Reply to this comment to answer: Specrails records the reply on the spec for its next run. You can also answer in the app.');
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
lines.push('Specrails planned this spec on the following assumptions. Reply to this comment if any of them is wrong; the reply is recorded on the spec for its next run.');
|
|
65
|
+
lines.push('');
|
|
66
|
+
const assumptions = record.assumptions.length
|
|
67
|
+
? record.assumptions
|
|
68
|
+
: record.clarifications.map((item) => `${item.question} → ${item.default ?? 'no safe default'}`);
|
|
69
|
+
for (const line of assumptions)
|
|
70
|
+
lines.push(`- ${line.replace(/^\s*[-*]\s+/, '')}`);
|
|
71
|
+
}
|
|
72
|
+
return lines.join('\n');
|
|
73
|
+
}
|
|
74
|
+
/** True when the comment was written by Specrails (any marker). */
|
|
75
|
+
function isSpecrailsComment(comment) {
|
|
76
|
+
if (comment.properties?.some((property) => property.key === jira_adf_1.SPECRAILS_COMMENT_PROP_KEY))
|
|
77
|
+
return true;
|
|
78
|
+
return /\[specrails:[a-z-]+=/.test((0, jira_adf_1.adfToText)(comment.body));
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Human replies after the thread's marker comment (Jira lists comments oldest
|
|
82
|
+
* first), skipping Specrails' own comments and the already-imported ids.
|
|
83
|
+
* Empty when the marker comment is not (yet) on the issue.
|
|
84
|
+
*/
|
|
85
|
+
function selectClarificationReplies(comments, marker, imported) {
|
|
86
|
+
const anchor = comments.findIndex((comment) => (0, jira_adf_1.commentHasMarker)(comment, marker));
|
|
87
|
+
if (anchor < 0)
|
|
88
|
+
return [];
|
|
89
|
+
const out = [];
|
|
90
|
+
for (const comment of comments.slice(anchor + 1)) {
|
|
91
|
+
if (!comment.id || imported.has(comment.id) || isSpecrailsComment(comment))
|
|
92
|
+
continue;
|
|
93
|
+
const text = (0, jira_adf_1.adfToText)(comment.body).trim();
|
|
94
|
+
if (!text)
|
|
95
|
+
continue;
|
|
96
|
+
out.push({
|
|
97
|
+
commentId: comment.id,
|
|
98
|
+
author: typeof comment.author?.displayName === 'string' && comment.author.displayName.trim() ? comment.author.displayName.trim().slice(0, 120) : null,
|
|
99
|
+
created: typeof comment.created === 'string' ? comment.created : null,
|
|
100
|
+
text: text.slice(0, REPLY_BODY_CAP),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return out;
|
|
104
|
+
}
|
|
105
|
+
/** The addendum a reply becomes (kind `clarification`, validated by the addenda core). */
|
|
106
|
+
function clarificationAddendumInput(reply, jiraKey, kind) {
|
|
107
|
+
const where = jiraKey ? `Jira ${jiraKey}` : 'Jira';
|
|
108
|
+
const title = `${kind === 'questions' ? 'Answer' : 'Correction'} from ${where}${reply.author ? ` (${reply.author})` : ''}`.slice(0, 200);
|
|
109
|
+
const body = [
|
|
110
|
+
kind === 'questions'
|
|
111
|
+
? 'Answer to the architect\'s clarification questions, posted on the linked Jira issue. Treat it as authoritative for the questions it answers.'
|
|
112
|
+
: 'Reply to the assumptions the architect planned on, posted on the linked Jira issue. Where it contradicts an assumption, the reply wins.',
|
|
113
|
+
'',
|
|
114
|
+
reply.text,
|
|
115
|
+
].join('\n');
|
|
116
|
+
return { kind: 'clarification', title, body };
|
|
117
|
+
}
|
|
118
|
+
function insertClarificationThread(db, row) {
|
|
119
|
+
const result = db.prepare(`
|
|
120
|
+
INSERT OR IGNORE INTO jira_clarification_threads (id, run_id, ticket_id, jira_issue_id, kind, marker, state, imported_comment_ids, created_at, updated_at)
|
|
121
|
+
VALUES (?, ?, ?, ?, ?, ?, 'open', '[]', ?, ?)
|
|
122
|
+
`).run(row.id, row.run_id, row.ticket_id, row.jira_issue_id, row.kind, row.marker, row.created_at, row.created_at);
|
|
123
|
+
return result.changes > 0;
|
|
124
|
+
}
|
|
125
|
+
/** Threads still collecting replies; older ones are closed as a side effect. */
|
|
126
|
+
function listOpenClarificationThreads(db, now = Date.now()) {
|
|
127
|
+
const cutoff = new Date(now - exports.CLARIFICATION_REPLY_WINDOW_MS).toISOString();
|
|
128
|
+
db.prepare(`UPDATE jira_clarification_threads SET state = 'closed', updated_at = ? WHERE state != 'closed' AND created_at < ?`).run(new Date(now).toISOString(), cutoff);
|
|
129
|
+
return db.prepare(`SELECT * FROM jira_clarification_threads WHERE state != 'closed' ORDER BY created_at LIMIT 50`).all();
|
|
130
|
+
}
|
|
131
|
+
function importedCommentIds(row) {
|
|
132
|
+
try {
|
|
133
|
+
const parsed = JSON.parse(row.imported_comment_ids);
|
|
134
|
+
return new Set(Array.isArray(parsed) ? parsed.filter((id) => typeof id === 'string') : []);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return new Set();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function recordImportedReplies(db, threadId, ids, now = new Date().toISOString()) {
|
|
141
|
+
const row = db.prepare(`SELECT imported_comment_ids FROM jira_clarification_threads WHERE id = ?`).get(threadId);
|
|
142
|
+
if (!row)
|
|
143
|
+
return;
|
|
144
|
+
const merged = [...new Set([...importedCommentIds(row), ...ids])].slice(-200);
|
|
145
|
+
db.prepare(`UPDATE jira_clarification_threads SET imported_comment_ids = ?, state = 'answered', updated_at = ? WHERE id = ?`).run(JSON.stringify(merged), now, threadId);
|
|
146
|
+
}
|
|
@@ -207,7 +207,14 @@ class JiraClient {
|
|
|
207
207
|
fields.labels = args.labels;
|
|
208
208
|
if (args.priority)
|
|
209
209
|
fields.priority = { name: args.priority };
|
|
210
|
-
|
|
210
|
+
const body = { fields };
|
|
211
|
+
if (args.properties && args.properties.length > 0)
|
|
212
|
+
body.properties = args.properties;
|
|
213
|
+
return this.request('POST', '/issue', body);
|
|
214
|
+
}
|
|
215
|
+
/** GET /issue/{id}/properties/{key} — read one entity property (404 = absent). */
|
|
216
|
+
getIssueProperty(issueIdOrKey, propertyKey) {
|
|
217
|
+
return this.request('GET', `/issue/${encodeURIComponent(issueIdOrKey)}/properties/${encodeURIComponent(propertyKey)}`);
|
|
211
218
|
}
|
|
212
219
|
/**
|
|
213
220
|
* PUT /issue/{id} — update editable fields (summary/description/labels/
|
|
@@ -27,6 +27,7 @@ exports.updateLinkStatusCategory = updateLinkStatusCategory;
|
|
|
27
27
|
exports.setLinkState = setLinkState;
|
|
28
28
|
exports.tombstoneLink = tombstoneLink;
|
|
29
29
|
exports.enqueueOutbox = enqueueOutbox;
|
|
30
|
+
exports.enqueueHeldUpdate = enqueueHeldUpdate;
|
|
30
31
|
exports.enqueueMany = enqueueMany;
|
|
31
32
|
exports.claimDrainable = claimDrainable;
|
|
32
33
|
exports.markOutboxDone = markOutboxDone;
|
|
@@ -266,6 +267,46 @@ function enqueueOutbox(db, input) {
|
|
|
266
267
|
const existing = db.prepare('SELECT id FROM jira_outbox WHERE idempotency_key = ?').get(input.idempotencyKey);
|
|
267
268
|
return existing?.id ?? 0;
|
|
268
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Enqueue a field `update` that waits `holdMs` before it may drain (the undo
|
|
272
|
+
* window of a label change). While an earlier held update for the same issue is
|
|
273
|
+
* still waiting, it is folded into this one and marked `superseded`, so an edit
|
|
274
|
+
* undone inside the window collapses to the value Jira already has — Jira never
|
|
275
|
+
* sees the transient change. Idempotent on `idempotencyKey`.
|
|
276
|
+
*/
|
|
277
|
+
function enqueueHeldUpdate(db, input) {
|
|
278
|
+
const now = input.now ?? new Date();
|
|
279
|
+
const nowIso = now.toISOString();
|
|
280
|
+
const dueIso = new Date(now.getTime() + input.holdMs).toISOString();
|
|
281
|
+
const tx = db.transaction(() => {
|
|
282
|
+
const existing = db.prepare('SELECT id FROM jira_outbox WHERE idempotency_key = ?').get(input.idempotencyKey);
|
|
283
|
+
if (existing)
|
|
284
|
+
return existing.id;
|
|
285
|
+
const held = db
|
|
286
|
+
.prepare(`SELECT id, payload FROM jira_outbox
|
|
287
|
+
WHERE jira_issue_id = ? AND op_type = 'update' AND state = 'pending'
|
|
288
|
+
AND next_attempt_at IS NOT NULL AND next_attempt_at > ?
|
|
289
|
+
ORDER BY id ASC`)
|
|
290
|
+
.all(input.jiraIssueId, nowIso);
|
|
291
|
+
let merged = {};
|
|
292
|
+
for (const row of held) {
|
|
293
|
+
try {
|
|
294
|
+
const payload = JSON.parse(row.payload);
|
|
295
|
+
merged = { ...merged, ...(payload.fields ?? {}) };
|
|
296
|
+
}
|
|
297
|
+
catch { /* an unreadable held payload carries nothing to merge */ }
|
|
298
|
+
db.prepare("UPDATE jira_outbox SET state = 'superseded', next_attempt_at = NULL, updated_at = ? WHERE id = ?").run(nowIso, row.id);
|
|
299
|
+
}
|
|
300
|
+
merged = { ...merged, ...input.fields };
|
|
301
|
+
const info = db
|
|
302
|
+
.prepare(`INSERT INTO jira_outbox
|
|
303
|
+
(jira_issue_id, op_type, idempotency_key, payload, state, attempts, next_attempt_at, created_at, updated_at)
|
|
304
|
+
VALUES (?, 'update', ?, ?, 'pending', 0, ?, ?, ?)`)
|
|
305
|
+
.run(input.jiraIssueId, input.idempotencyKey, JSON.stringify({ jiraIssueId: input.jiraIssueId, fields: merged }), dueIso, nowIso, nowIso);
|
|
306
|
+
return Number(info.lastInsertRowid);
|
|
307
|
+
});
|
|
308
|
+
return tx();
|
|
309
|
+
}
|
|
269
310
|
/** Enqueue several ops atomically (one SQLite transaction). */
|
|
270
311
|
function enqueueMany(db, ops) {
|
|
271
312
|
const tx = db.transaction((items) => {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// and stays completely inert until the project configures a Jira connection.
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.JiraSyncManager = void 0;
|
|
14
|
+
exports.pendingCreateIssueId = pendingCreateIssueId;
|
|
14
15
|
exports.backoffMs = backoffMs;
|
|
15
16
|
exports.formatJqlDate = formatJqlDate;
|
|
16
17
|
exports.buildCompletionComment = buildCompletionComment;
|
|
@@ -28,6 +29,10 @@ const jira_issue_fields_1 = require("./jira-issue-fields");
|
|
|
28
29
|
const jira_status_resolver_1 = require("./jira-status-resolver");
|
|
29
30
|
const jira_db_1 = require("./jira-db");
|
|
30
31
|
const workspace_resolution_1 = require("../workspace-resolution");
|
|
32
|
+
const db_1 = require("../db");
|
|
33
|
+
const spec_addenda_1 = require("../modules/specs/runtime/spec-addenda");
|
|
34
|
+
const run_records_1 = require("../modules/delivery/runtime/run-records");
|
|
35
|
+
const jira_clarifications_1 = require("./jira-clarifications");
|
|
31
36
|
const POLL_INTERVAL_MS = 60_000;
|
|
32
37
|
const DRAIN_INTERVAL_MS = 10_000;
|
|
33
38
|
const POLL_OVERLAP_MS = 2 * 60_000;
|
|
@@ -380,22 +385,94 @@ class JiraSyncManager {
|
|
|
380
385
|
const client = this.buildClient();
|
|
381
386
|
if (!client)
|
|
382
387
|
return { ok: false, error: 'no jira credentials' };
|
|
383
|
-
const
|
|
384
|
-
const ticket = (0, ticket_store_1.readStore)(file).tickets[String(localId)];
|
|
385
|
-
if (!ticket)
|
|
386
|
-
return { ok: false, error: 'ticket not found' };
|
|
387
|
-
const created = await client.createIssue({
|
|
388
|
-
projectKey: conn.jiraProjectKey,
|
|
389
|
-
issueType: 'Task',
|
|
390
|
-
summary: ticket.title,
|
|
391
|
-
description: ticket.description || undefined,
|
|
392
|
-
labels: ticket.labels,
|
|
393
|
-
});
|
|
388
|
+
const created = await this.createLinkedIssue(client, conn, localId);
|
|
394
389
|
if (!created.ok) {
|
|
390
|
+
if (created.reason === 'ticket_not_found')
|
|
391
|
+
return { ok: false, error: 'ticket not found' };
|
|
392
|
+
if (created.reason === 'flow_held')
|
|
393
|
+
return { ok: false, error: 'the spec is still in Flow; it reaches Jira when its Flow -> Spec rail settles' };
|
|
395
394
|
if (created.code === 'auth')
|
|
396
395
|
this.onAuth401();
|
|
397
396
|
return { ok: false, error: created.error || 'jira issue create failed' };
|
|
398
397
|
}
|
|
398
|
+
return { ok: true, jiraKey: created.jiraKey };
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Durable form of `promoteTicketToJira` (feedback-2026-10 Flow settlement):
|
|
402
|
+
* enqueue a `create` outbox op for a LOCAL ticket. The drainer creates the
|
|
403
|
+
* issue, links it to the same local id and flips the ticket to
|
|
404
|
+
* `source:'jira'` exactly as promote does, with the outbox's retry/backoff
|
|
405
|
+
* and restart replay. Idempotent: the same `idempotencyKey` never enqueues
|
|
406
|
+
* twice, and an already-linked ticket completes as a no-op at drain time.
|
|
407
|
+
* Never throws.
|
|
408
|
+
*/
|
|
409
|
+
enqueuePromote(localTicketId, idempotencyKey) {
|
|
410
|
+
try {
|
|
411
|
+
if (!this.isActive())
|
|
412
|
+
return 'inactive';
|
|
413
|
+
const existing = (0, jira_db_1.getLinkByLocalId)(this.db, localTicketId);
|
|
414
|
+
if (existing && !existing.tombstoned)
|
|
415
|
+
return 'already_linked';
|
|
416
|
+
(0, jira_db_1.enqueueOutbox)(this.db, {
|
|
417
|
+
jiraIssueId: pendingCreateIssueId(localTicketId),
|
|
418
|
+
opType: 'create',
|
|
419
|
+
idempotencyKey,
|
|
420
|
+
payload: { localTicketId },
|
|
421
|
+
});
|
|
422
|
+
this.broadcastOutboxState();
|
|
423
|
+
void this.drainOnce().catch(() => undefined);
|
|
424
|
+
return 'enqueued';
|
|
425
|
+
}
|
|
426
|
+
catch (err) {
|
|
427
|
+
console.error('[jira-sync] enqueuePromote failed:', err);
|
|
428
|
+
return 'failed';
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Create the Jira issue for an existing LOCAL ticket, link it to the SAME
|
|
433
|
+
* local id and flip the cached ticket to `source:'jira'` with its key/url.
|
|
434
|
+
* Shared by `promoteTicketToJira` and the outbox `create` op. Callers own
|
|
435
|
+
* the already-linked check and error policy (auth pause, retry/dead).
|
|
436
|
+
*/
|
|
437
|
+
async createLinkedIssue(client, conn, localId, recovery) {
|
|
438
|
+
const file = (0, ticket_store_1.resolveTicketStoragePath)(this._artifactRoot());
|
|
439
|
+
const ticket = (0, ticket_store_1.readStore)(file).tickets[String(localId)];
|
|
440
|
+
if (!ticket)
|
|
441
|
+
return { ok: false, reason: 'ticket_not_found' };
|
|
442
|
+
// Flow placeholder specs never reach Jira while the Flow is active or paused.
|
|
443
|
+
if ((0, ticket_store_1.isFlowHeldTicket)(ticket))
|
|
444
|
+
return { ok: false, reason: 'flow_held' };
|
|
445
|
+
const marker = (0, jira_adf_1.issueCreateMarker)(this.projectId, localId);
|
|
446
|
+
let created;
|
|
447
|
+
let recovered = false;
|
|
448
|
+
// A retried durable create may follow an attempt whose issue WAS created
|
|
449
|
+
// but whose response was lost. Recover that issue by its invisible
|
|
450
|
+
// creation marker before creating; an unconfirmed search retries later
|
|
451
|
+
// rather than risking a duplicate.
|
|
452
|
+
const existing = recovery ? await this.findIssueByCreateMarker(client, conn, marker, recovery.since) : null;
|
|
453
|
+
if (existing && !existing.ok)
|
|
454
|
+
return { ok: false, reason: 'jira', ...existing.error };
|
|
455
|
+
if (existing?.ok && existing.issue) {
|
|
456
|
+
created = { ok: true, data: existing.issue };
|
|
457
|
+
recovered = true;
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
const input = {
|
|
461
|
+
projectKey: conn.jiraProjectKey,
|
|
462
|
+
issueType: 'Task',
|
|
463
|
+
summary: ticket.title,
|
|
464
|
+
description: ticket.description || undefined,
|
|
465
|
+
labels: ticket.labels,
|
|
466
|
+
};
|
|
467
|
+
created = await client.createIssue({ ...input, properties: [{ key: jira_adf_1.SPECRAILS_ISSUE_CREATE_PROP_KEY, value: { marker } }] });
|
|
468
|
+
// Compatibility: an instance that rejects create-time entity properties
|
|
469
|
+
// still gets the issue (without the recovery marker), as before.
|
|
470
|
+
if (!created.ok && created.code === 'validation')
|
|
471
|
+
created = await client.createIssue(input);
|
|
472
|
+
}
|
|
473
|
+
if (!created.ok) {
|
|
474
|
+
return { ok: false, reason: 'jira', code: created.code, status: created.status, retryAfterMs: created.retryAfterMs, error: created.error };
|
|
475
|
+
}
|
|
399
476
|
(0, jira_db_1.insertLinkWithId)(this.db, {
|
|
400
477
|
localId,
|
|
401
478
|
jiraIssueId: created.data.id,
|
|
@@ -418,7 +495,35 @@ class JiraSyncManager {
|
|
|
418
495
|
if (updated) {
|
|
419
496
|
this.broadcast({ type: 'ticket_updated', ticket: updated, projectId: this.projectId, timestamp: updated.updated_at });
|
|
420
497
|
}
|
|
421
|
-
return { ok: true, jiraKey: created.data.key };
|
|
498
|
+
return { ok: true, jiraKey: created.data.key, ...(recovered ? { recovered: true } : {}) };
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Find an issue this manager created for `marker`: recent issues the
|
|
502
|
+
* connected account created in the project, confirmed by the invisible
|
|
503
|
+
* creation property (works on Cloud and DC without property indexing).
|
|
504
|
+
*/
|
|
505
|
+
async findIssueByCreateMarker(client, conn, marker, since) {
|
|
506
|
+
const sinceMs = since ? Date.parse(since.includes('T') ? since : `${since.replace(' ', 'T')}Z`) : NaN;
|
|
507
|
+
const minutes = Number.isFinite(sinceMs) ? Math.max(1, Math.ceil((Date.now() - sinceMs) / 60_000) + CREATE_RECOVERY_MARGIN_MIN) : CREATE_RECOVERY_DEFAULT_MIN;
|
|
508
|
+
const res = await client.searchJql({
|
|
509
|
+
jql: `project = "${conn.jiraProjectKey}" AND creator = currentUser() AND created >= "-${minutes}m" ORDER BY created DESC`,
|
|
510
|
+
fields: ['summary'],
|
|
511
|
+
maxResults: CREATE_RECOVERY_MAX_CANDIDATES,
|
|
512
|
+
});
|
|
513
|
+
if (!res.ok)
|
|
514
|
+
return { ok: false, error: { code: res.code, status: res.status, retryAfterMs: res.retryAfterMs, error: res.error } };
|
|
515
|
+
for (const issue of res.data.issues ?? []) {
|
|
516
|
+
const prop = await client.getIssueProperty(issue.id, jira_adf_1.SPECRAILS_ISSUE_CREATE_PROP_KEY);
|
|
517
|
+
if (prop.ok) {
|
|
518
|
+
const value = prop.data.value;
|
|
519
|
+
if (value?.marker === marker)
|
|
520
|
+
return { ok: true, issue: { id: issue.id, key: issue.key } };
|
|
521
|
+
}
|
|
522
|
+
else if (prop.code !== 'not_found') {
|
|
523
|
+
return { ok: false, error: { code: prop.code, status: prop.status, retryAfterMs: prop.retryAfterMs, error: prop.error } };
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return { ok: true, issue: null };
|
|
422
527
|
}
|
|
423
528
|
// ─── Inbound poll ──────────────────────────────────────────────────────────
|
|
424
529
|
/** The set of local ids with a pending/inflight outbox op (status is frozen). */
|
|
@@ -515,8 +620,103 @@ class JiraSyncManager {
|
|
|
515
620
|
(0, jira_db_1.setHighWater)(this.db, this.projectId, maxUpdated);
|
|
516
621
|
if (totalUpserted > 0)
|
|
517
622
|
this.broadcast({ type: 'jira.synced', projectId: this.projectId, upserted: totalUpserted, at: Date.now() });
|
|
623
|
+
await this.importClarificationReplies(client).catch((err) => console.error('[jira-sync] clarification replies failed:', err));
|
|
518
624
|
return { upserted: totalUpserted };
|
|
519
625
|
}
|
|
626
|
+
// ─── Architect clarifications (feedback-2026-10 task 3.2) ─────────────────
|
|
627
|
+
/**
|
|
628
|
+
* A run's architect clarifications (Core `clarifications.json`): when the
|
|
629
|
+
* project enabled `jiraPostClarifications`, enqueue ONE comment per linked
|
|
630
|
+
* ticket with the questions the run paused on, or the assumptions it
|
|
631
|
+
* proceeded with. Idempotent per run, ticket and record content (a second
|
|
632
|
+
* pause with different questions posts again). Never throws.
|
|
633
|
+
*/
|
|
634
|
+
onRunClarifications(runId, ticketIds, record) {
|
|
635
|
+
try {
|
|
636
|
+
if (!this.isActive() || !(0, run_records_1.hasClarificationContent)(record))
|
|
637
|
+
return 0;
|
|
638
|
+
if (!(0, db_1.getProjectSettings)(this.db).jiraPostClarifications)
|
|
639
|
+
return 0;
|
|
640
|
+
const digest = (0, jira_clarifications_1.clarificationsDigest)(record);
|
|
641
|
+
const kind = (0, jira_clarifications_1.clarificationThreadKind)(record);
|
|
642
|
+
const text = (0, jira_clarifications_1.buildClarificationsComment)(record);
|
|
643
|
+
const now = new Date().toISOString();
|
|
644
|
+
const ops = [];
|
|
645
|
+
for (const localId of new Set(ticketIds)) {
|
|
646
|
+
const link = (0, jira_db_1.getLinkByLocalId)(this.db, localId);
|
|
647
|
+
if (!link || link.tombstoned)
|
|
648
|
+
continue;
|
|
649
|
+
const marker = (0, jira_clarifications_1.clarificationsCommentMarker)(runId, localId, digest);
|
|
650
|
+
const fresh = (0, jira_clarifications_1.insertClarificationThread)(this.db, { id: `${runId}:${localId}:${digest}`, run_id: runId, ticket_id: localId, jira_issue_id: link.jiraIssueId, kind, marker, created_at: now });
|
|
651
|
+
if (!fresh)
|
|
652
|
+
continue;
|
|
653
|
+
ops.push({
|
|
654
|
+
jiraIssueId: link.jiraIssueId,
|
|
655
|
+
opType: 'comment',
|
|
656
|
+
idempotencyKey: `${runId}:${localId}:comment:clarifications:${digest}`,
|
|
657
|
+
payload: { jiraIssueId: link.jiraIssueId, text, marker },
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
if (ops.length === 0)
|
|
661
|
+
return 0;
|
|
662
|
+
(0, jira_db_1.enqueueMany)(this.db, ops);
|
|
663
|
+
this.broadcastOutboxState();
|
|
664
|
+
void this.drainOnce().catch(() => undefined);
|
|
665
|
+
return ops.length;
|
|
666
|
+
}
|
|
667
|
+
catch (err) {
|
|
668
|
+
console.error('[jira-sync] onRunClarifications failed:', err);
|
|
669
|
+
return 0;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
/** Import human replies to posted clarifications as `clarification` addenda. */
|
|
673
|
+
async importClarificationReplies(client) {
|
|
674
|
+
let threads;
|
|
675
|
+
try {
|
|
676
|
+
threads = (0, jira_clarifications_1.listOpenClarificationThreads)(this.db);
|
|
677
|
+
}
|
|
678
|
+
catch {
|
|
679
|
+
return 0;
|
|
680
|
+
}
|
|
681
|
+
let imported = 0;
|
|
682
|
+
for (const thread of threads) {
|
|
683
|
+
const res = await client.getComments(thread.jira_issue_id);
|
|
684
|
+
if (!res.ok)
|
|
685
|
+
continue;
|
|
686
|
+
const replies = (0, jira_clarifications_1.selectClarificationReplies)(res.data.comments, thread.marker, (0, jira_clarifications_1.importedCommentIds)(thread));
|
|
687
|
+
if (replies.length === 0)
|
|
688
|
+
continue;
|
|
689
|
+
const jiraKey = (0, jira_db_1.getLinkByLocalId)(this.db, thread.ticket_id)?.jiraKey ?? null;
|
|
690
|
+
try {
|
|
691
|
+
const file = (0, ticket_store_1.resolveTicketStoragePath)(this._artifactRoot());
|
|
692
|
+
let touched = false;
|
|
693
|
+
const store = (0, ticket_store_1.mutateStore)(file, (s) => {
|
|
694
|
+
const ticket = s.tickets[String(thread.ticket_id)];
|
|
695
|
+
if (!ticket)
|
|
696
|
+
return;
|
|
697
|
+
for (const reply of replies) {
|
|
698
|
+
const input = (0, spec_addenda_1.parseSpecAddendumInput)((0, jira_clarifications_1.clarificationAddendumInput)(reply, jiraKey, thread.kind));
|
|
699
|
+
(0, spec_addenda_1.appendSpecAddendum)(ticket, (0, spec_addenda_1.buildSpecAddendum)(input, { createdBy: 'jira' }));
|
|
700
|
+
touched = true;
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
// Recorded even when the ticket is gone, so a deleted spec is not retried forever.
|
|
704
|
+
(0, jira_clarifications_1.recordImportedReplies)(this.db, thread.id, replies.map((reply) => reply.commentId));
|
|
705
|
+
if (!touched)
|
|
706
|
+
continue;
|
|
707
|
+
imported += replies.length;
|
|
708
|
+
this.notifyLocalWrite(store.revision);
|
|
709
|
+
const ticket = store.tickets[String(thread.ticket_id)];
|
|
710
|
+
if (ticket)
|
|
711
|
+
this.broadcast({ type: 'ticket_updated', ticket: ticket, projectId: this.projectId, timestamp: ticket.updated_at });
|
|
712
|
+
}
|
|
713
|
+
catch (err) {
|
|
714
|
+
// A full addenda list (or a validation error) keeps the thread for a later poll.
|
|
715
|
+
console.error('[jira-sync] clarification reply import failed:', err);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return imported;
|
|
719
|
+
}
|
|
520
720
|
// ─── Outbound write-back hooks ─────────────────────────────────────────────
|
|
521
721
|
/**
|
|
522
722
|
* Called from the rail-launch handler. For each Jira-linked ticket, enqueue an
|
|
@@ -599,7 +799,7 @@ class JiraSyncManager {
|
|
|
599
799
|
* pending the id is frozen, so the inbound poll won't revert the local edit.
|
|
600
800
|
* Status is intentionally NOT written here (Jira status needs a transition).
|
|
601
801
|
*/
|
|
602
|
-
onSpecEdited(localId, changes) {
|
|
802
|
+
onSpecEdited(localId, changes, opts = {}) {
|
|
603
803
|
if (!this.isActive())
|
|
604
804
|
return;
|
|
605
805
|
const link = (0, jira_db_1.getLinkByLocalId)(this.db, localId);
|
|
@@ -608,18 +808,7 @@ class JiraSyncManager {
|
|
|
608
808
|
const conn = (0, jira_db_1.getConnection)(this.db, this.projectId);
|
|
609
809
|
if (!conn)
|
|
610
810
|
return;
|
|
611
|
-
const fields =
|
|
612
|
-
if (typeof changes.title === 'string' && changes.title.trim())
|
|
613
|
-
fields.summary = changes.title.trim().slice(0, 250);
|
|
614
|
-
if (typeof changes.description === 'string')
|
|
615
|
-
fields.description = (0, jira_adf_1.bodyForDeployment)(changes.description, conn.deployment);
|
|
616
|
-
if (changes.labels !== undefined)
|
|
617
|
-
fields.labels = (changes.labels ?? []).filter((l) => typeof l === 'string');
|
|
618
|
-
if (changes.priority) {
|
|
619
|
-
const name = PRIORITY_TO_JIRA[changes.priority];
|
|
620
|
-
if (name)
|
|
621
|
-
fields.priority = { name };
|
|
622
|
-
}
|
|
811
|
+
const fields = this.specUpdateFields(changes, conn.deployment);
|
|
623
812
|
if (Object.keys(fields).length === 0)
|
|
624
813
|
return;
|
|
625
814
|
// A random component makes two saves of the same ticket inside one wall-clock
|
|
@@ -627,6 +816,20 @@ class JiraSyncManager {
|
|
|
627
816
|
// INSERT OR IGNORE silently drops the second edit while the local cache shows
|
|
628
817
|
// it (local↔Jira divergence). randomUUID() guarantees uniqueness per op.
|
|
629
818
|
const nonce = `${Date.now().toString(36)}:${(0, node_crypto_1.randomUUID)()}`;
|
|
819
|
+
if (opts.holdMs && opts.holdMs > 0) {
|
|
820
|
+
// Undo window: the write waits, and an edit undone inside the window
|
|
821
|
+
// collapses with it so Jira never sees the transient value.
|
|
822
|
+
(0, jira_db_1.enqueueHeldUpdate)(this.db, {
|
|
823
|
+
jiraIssueId: link.jiraIssueId,
|
|
824
|
+
idempotencyKey: `update:${localId}:${nonce}`,
|
|
825
|
+
fields,
|
|
826
|
+
holdMs: opts.holdMs,
|
|
827
|
+
});
|
|
828
|
+
this.broadcastOutboxState();
|
|
829
|
+
const timer = setTimeout(() => { void this.drainOnce().catch(() => undefined); }, opts.holdMs + 250);
|
|
830
|
+
timer.unref?.();
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
630
833
|
(0, jira_db_1.enqueueMany)(this.db, [
|
|
631
834
|
{
|
|
632
835
|
jiraIssueId: link.jiraIssueId,
|
|
@@ -638,6 +841,58 @@ class JiraSyncManager {
|
|
|
638
841
|
this.broadcastOutboxState();
|
|
639
842
|
void this.drainOnce().catch(() => undefined);
|
|
640
843
|
}
|
|
844
|
+
/** The editable Jira fields of a spec edit (summary, description, labels, priority). */
|
|
845
|
+
specUpdateFields(changes, deployment) {
|
|
846
|
+
const fields = {};
|
|
847
|
+
if (typeof changes.title === 'string' && changes.title.trim())
|
|
848
|
+
fields.summary = changes.title.trim().slice(0, 250);
|
|
849
|
+
if (typeof changes.description === 'string')
|
|
850
|
+
fields.description = (0, jira_adf_1.bodyForDeployment)(changes.description, deployment);
|
|
851
|
+
if (changes.labels !== undefined)
|
|
852
|
+
fields.labels = (changes.labels ?? []).filter((l) => typeof l === 'string');
|
|
853
|
+
if (changes.priority) {
|
|
854
|
+
const name = PRIORITY_TO_JIRA[changes.priority];
|
|
855
|
+
if (name)
|
|
856
|
+
fields.priority = { name };
|
|
857
|
+
}
|
|
858
|
+
return fields;
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Durable, IDEMPOTENT push of a linked spec's current summary, description,
|
|
862
|
+
* labels and priority to its existing issue (Flow settlement of a spec that
|
|
863
|
+
* already had an issue: the rewritten spec updates THAT issue, never a new
|
|
864
|
+
* one). The same `idempotencyKey` never enqueues twice; the pending op
|
|
865
|
+
* freezes the id so the inbound poll cannot revert the rewrite. Never throws.
|
|
866
|
+
*/
|
|
867
|
+
enqueueSpecUpdate(localTicketId, idempotencyKey) {
|
|
868
|
+
try {
|
|
869
|
+
if (!this.isActive())
|
|
870
|
+
return 'inactive';
|
|
871
|
+
const link = (0, jira_db_1.getLinkByLocalId)(this.db, localTicketId);
|
|
872
|
+
if (!link || link.tombstoned)
|
|
873
|
+
return 'not_linked';
|
|
874
|
+
const conn = (0, jira_db_1.getConnection)(this.db, this.projectId);
|
|
875
|
+
if (!conn)
|
|
876
|
+
return 'inactive';
|
|
877
|
+
const ticket = (0, ticket_store_1.readStore)((0, ticket_store_1.resolveTicketStoragePath)(this._artifactRoot())).tickets[String(localTicketId)];
|
|
878
|
+
if (!ticket)
|
|
879
|
+
return 'failed';
|
|
880
|
+
const fields = this.specUpdateFields({ title: ticket.title, description: ticket.description ?? '', labels: ticket.labels ?? [], priority: ticket.priority }, conn.deployment);
|
|
881
|
+
(0, jira_db_1.enqueueMany)(this.db, [{
|
|
882
|
+
jiraIssueId: link.jiraIssueId,
|
|
883
|
+
opType: 'update',
|
|
884
|
+
idempotencyKey,
|
|
885
|
+
payload: { jiraIssueId: link.jiraIssueId, fields },
|
|
886
|
+
}]);
|
|
887
|
+
this.broadcastOutboxState();
|
|
888
|
+
void this.drainOnce().catch(() => undefined);
|
|
889
|
+
return 'enqueued';
|
|
890
|
+
}
|
|
891
|
+
catch (err) {
|
|
892
|
+
console.error('[jira-sync] enqueueSpecUpdate failed:', err);
|
|
893
|
+
return 'failed';
|
|
894
|
+
}
|
|
895
|
+
}
|
|
641
896
|
/**
|
|
642
897
|
* Called from project-registry's onJobFinished AFTER the local cache mutation.
|
|
643
898
|
* Enqueues the Jira status transition + completion comment per linked ticket.
|
|
@@ -1025,6 +1280,9 @@ class JiraSyncManager {
|
|
|
1025
1280
|
else if (op.opType === 'update') {
|
|
1026
1281
|
await this.executeUpdate(client, op, payload);
|
|
1027
1282
|
}
|
|
1283
|
+
else if (op.opType === 'create') {
|
|
1284
|
+
await this.executeCreate(client, conn, op, payload);
|
|
1285
|
+
}
|
|
1028
1286
|
else {
|
|
1029
1287
|
(0, jira_db_1.markOutboxDead)(this.db, op.id, `unsupported op type ${op.opType}`);
|
|
1030
1288
|
}
|
|
@@ -1033,6 +1291,39 @@ class JiraSyncManager {
|
|
|
1033
1291
|
this.retryOrDead(op, err instanceof Error ? err.message : String(err));
|
|
1034
1292
|
}
|
|
1035
1293
|
}
|
|
1294
|
+
async executeCreate(client, conn, op, payload) {
|
|
1295
|
+
const localId = Number(payload?.localTicketId);
|
|
1296
|
+
if (!Number.isInteger(localId) || localId <= 0) {
|
|
1297
|
+
(0, jira_db_1.markOutboxDead)(this.db, op.id, 'invalid create payload: localTicketId required');
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
// Idempotency-first: a ticket linked since enqueue (promote, a replay that
|
|
1301
|
+
// crashed after linking) completes without creating a second issue.
|
|
1302
|
+
const existing = (0, jira_db_1.getLinkByLocalId)(this.db, localId);
|
|
1303
|
+
if (existing && !existing.tombstoned) {
|
|
1304
|
+
(0, jira_db_1.markOutboxDone)(this.db, op.id);
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
// attempts > 0 ⇒ an earlier attempt may have created the issue.
|
|
1308
|
+
const created = await this.createLinkedIssue(client, conn, localId, op.attempts > 0 ? { since: op.createdAt } : undefined);
|
|
1309
|
+
if (created.ok) {
|
|
1310
|
+
(0, jira_db_1.markOutboxDone)(this.db, op.id);
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
if (created.reason === 'ticket_not_found') {
|
|
1314
|
+
(0, jira_db_1.markOutboxDead)(this.db, op.id, 'local ticket not found');
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
if (created.reason === 'flow_held') {
|
|
1318
|
+
// Settlement marks the Flow delivered before it publishes; retry until then.
|
|
1319
|
+
if (op.attempts + 1 >= MAX_OUTBOX_ATTEMPTS)
|
|
1320
|
+
(0, jira_db_1.markOutboxDead)(this.db, op.id, 'the spec is still in Flow');
|
|
1321
|
+
else
|
|
1322
|
+
(0, jira_db_1.markOutboxRetry)(this.db, op.id, new Date(Date.now() + backoffMs(op.attempts)).toISOString(), 'the spec is still in Flow');
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
this.handleHardError(op, created.code, created.status, created.retryAfterMs, created.error);
|
|
1326
|
+
}
|
|
1036
1327
|
async executeUpdate(client, op, payload) {
|
|
1037
1328
|
let res = await client.updateIssue(payload.jiraIssueId, payload.fields);
|
|
1038
1329
|
// The priority NAME may not match the instance's scheme. Don't let that lose
|
|
@@ -1380,6 +1671,18 @@ class JiraOpError extends Error {
|
|
|
1380
1671
|
}
|
|
1381
1672
|
}
|
|
1382
1673
|
// ─── Pure helpers ──────────────────────────────────────────────────────────────
|
|
1674
|
+
/**
|
|
1675
|
+
* Outbox serialisation key for a `create` op. The issue does not exist yet, so
|
|
1676
|
+
* the op is keyed by its local ticket (`local:<id>`), which also keeps two
|
|
1677
|
+
* creates for the same ticket FIFO-ordered. It never matches a real issue id.
|
|
1678
|
+
*/
|
|
1679
|
+
/** Durable-create recovery search window: since the op was enqueued, plus margin. */
|
|
1680
|
+
const CREATE_RECOVERY_MARGIN_MIN = 10;
|
|
1681
|
+
const CREATE_RECOVERY_DEFAULT_MIN = 7 * 24 * 60;
|
|
1682
|
+
const CREATE_RECOVERY_MAX_CANDIDATES = 50;
|
|
1683
|
+
function pendingCreateIssueId(localTicketId) {
|
|
1684
|
+
return `local:${localTicketId}`;
|
|
1685
|
+
}
|
|
1383
1686
|
function backoffMs(attempts) {
|
|
1384
1687
|
const base = Math.min(30_000, 2000 * 2 ** attempts);
|
|
1385
1688
|
const jitter = (attempts * 137) % 1000; // deterministic jitter (no Math.random)
|