specrails-desktop 2.64.1 → 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/openspec-shim.js +1 -1
- 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
|
@@ -44,14 +44,18 @@ const project_repositories_1 = require("./project-repositories");
|
|
|
44
44
|
const ids_1 = require("./ids");
|
|
45
45
|
const db_1 = require("./db");
|
|
46
46
|
const providers_1 = require("./providers");
|
|
47
|
+
const non_goals_1 = require("./modules/specs/domain/non-goals");
|
|
47
48
|
const contract_refine_runner_1 = require("./modules/specs/runtime/contract-refine-runner");
|
|
48
49
|
const explore_contract_refine_1 = require("./modules/conversations/runtime/explore-contract-refine");
|
|
50
|
+
const ticket_trash_1 = require("./modules/specs/runtime/ticket-trash");
|
|
51
|
+
const ticket_trash_service_1 = require("./modules/specs/runtime/ticket-trash-service");
|
|
49
52
|
const smash_runner_1 = require("./modules/specs/runtime/smash-runner");
|
|
50
53
|
const explore_smash_1 = require("./modules/conversations/runtime/explore-smash");
|
|
51
54
|
const ai_invocations_1 = require("./modules/accounting/runtime/ai-invocations");
|
|
52
|
-
const
|
|
55
|
+
const spec_generation_1 = require("./modules/specs/runtime/spec-generation");
|
|
53
56
|
const result_event_1 = require("./modules/accounting/runtime/result-event");
|
|
54
57
|
const runtime_1 = require("./providers/runtime");
|
|
58
|
+
const project_env_1 = require("./project-env");
|
|
55
59
|
const crypto_1 = require("crypto");
|
|
56
60
|
const spec_models_1 = require("./modules/specs/runtime/spec-models");
|
|
57
61
|
const provider_selection_1 = require("./provider-selection");
|
|
@@ -63,10 +67,12 @@ const transient_children_1 = require("./transient-children");
|
|
|
63
67
|
const process_admission_1 = require("./process-admission");
|
|
64
68
|
const readline_1 = require("readline");
|
|
65
69
|
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
66
|
-
const workspace_resolution_1 = require("./workspace-resolution");
|
|
67
70
|
const multer_1 = __importDefault(require("multer"));
|
|
71
|
+
const timeline_http_1 = require("./modules/specs/adapters/timeline-http");
|
|
68
72
|
const attachment_manager_1 = require("./attachment-manager");
|
|
69
73
|
const project_router_helpers_1 = require("./project-router-helpers");
|
|
74
|
+
/** The client's Undo window (8 s) plus margin: outbound Jira writes of undoable edits wait this long. */
|
|
75
|
+
const UNDO_WINDOW_HOLD_MS = 10_000;
|
|
70
76
|
/**
|
|
71
77
|
* A NULL conversation provider is the intentional single-provider encoding:
|
|
72
78
|
* it means "use this project's primary provider", never "use Claude".
|
|
@@ -174,6 +180,86 @@ function registerTicketsRoutes(deps) {
|
|
|
174
180
|
res.status(500).json({ error: 'Failed to read tickets' });
|
|
175
181
|
}
|
|
176
182
|
});
|
|
183
|
+
// ─── Recently deleted (soft-deleted specs) ───────────────────────────────────
|
|
184
|
+
// Registered before GET /tickets/:id so `trash` is not read as a ticket id.
|
|
185
|
+
const trashDeps = (req) => {
|
|
186
|
+
const c = ctx(req);
|
|
187
|
+
return {
|
|
188
|
+
ticketStorePath: () => ticketPath(req),
|
|
189
|
+
db: c.db,
|
|
190
|
+
deleteAttachments: (key) => attachment_manager_1.attachmentManager.deleteAll(c.project.slug, key),
|
|
191
|
+
forgetExploreConversation: (conversationId) => {
|
|
192
|
+
c.chatManager?.forgetSpecDraft(conversationId);
|
|
193
|
+
c.chatManager?.forgetExploreLifecycle(conversationId);
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
// GET /:projectId/tickets/trash — "Recently deleted" specs (newest first).
|
|
198
|
+
router.get('/:projectId/tickets/trash', async (req, res) => {
|
|
199
|
+
try {
|
|
200
|
+
await (0, ticket_trash_service_1.purgeProjectTrash)(trashDeps(req));
|
|
201
|
+
const items = (0, ticket_trash_1.listTrashedTickets)(ticketPath(req)).map((e) => ({
|
|
202
|
+
ticket: e.ticket,
|
|
203
|
+
deletedAt: e.deleted_at,
|
|
204
|
+
purgeAt: new Date(Date.parse(e.deleted_at) + ticket_trash_1.TRASH_RETENTION_MS).toISOString(),
|
|
205
|
+
}));
|
|
206
|
+
res.json({ items, retentionDays: ticket_trash_1.TRASH_RETENTION_DAYS });
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
console.error('[project-router] ticket trash list error:', err);
|
|
210
|
+
res.status(500).json({ error: 'Failed to read recently deleted specs' });
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
// POST /:projectId/tickets/:id/restore — Undo a delete. Idempotent.
|
|
214
|
+
router.post('/:projectId/tickets/:id/restore', (req, res) => {
|
|
215
|
+
const ticketId = req.params.id;
|
|
216
|
+
if (!/^\d+$/.test(ticketId)) {
|
|
217
|
+
res.status(400).json({ error: 'Invalid ticket ID' });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
const result = (0, ticket_trash_1.restoreTicket)(ticketPath(req), Number(ticketId));
|
|
222
|
+
if (!result) {
|
|
223
|
+
res.status(404).json({ error: 'Ticket not found in recently deleted' });
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const { broadcast, ticketWatcher, project } = ctx(req);
|
|
227
|
+
if (!result.alreadyLive) {
|
|
228
|
+
ticketWatcher.notifyDesktopWrite(result.revision);
|
|
229
|
+
const now = new Date().toISOString();
|
|
230
|
+
broadcast({ type: 'ticket_created', ticket: result.ticket, projectId: project.id, timestamp: now });
|
|
231
|
+
for (const child of result.readoptedChildren) {
|
|
232
|
+
broadcast({ type: 'ticket_updated', ticket: child, projectId: project.id, timestamp: now });
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
res.json({ ok: true, ticket: result.ticket, revision: result.revision, alreadyLive: result.alreadyLive });
|
|
236
|
+
}
|
|
237
|
+
catch (err) {
|
|
238
|
+
console.error('[project-router] ticket restore error:', err);
|
|
239
|
+
res.status(500).json({ error: 'Failed to restore ticket' });
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
// DELETE /:projectId/tickets/trash/:id — "Delete permanently" (the one confirmed step).
|
|
243
|
+
router.delete('/:projectId/tickets/trash/:id', async (req, res) => {
|
|
244
|
+
const ticketId = req.params.id;
|
|
245
|
+
if (!/^\d+$/.test(ticketId)) {
|
|
246
|
+
res.status(400).json({ error: 'Invalid ticket ID' });
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
const entry = (0, ticket_trash_1.purgeTrashedTicket)(ticketPath(req), Number(ticketId));
|
|
251
|
+
if (!entry) {
|
|
252
|
+
res.status(404).json({ error: 'Ticket not found in recently deleted' });
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
await (0, ticket_trash_service_1.finalizeTrashedTicket)(trashDeps(req), entry);
|
|
256
|
+
res.json({ ok: true });
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
console.error('[project-router] ticket permanent delete error:', err);
|
|
260
|
+
res.status(500).json({ error: 'Failed to delete ticket permanently' });
|
|
261
|
+
}
|
|
262
|
+
});
|
|
177
263
|
// GET /:projectId/tickets/:id — Get single ticket
|
|
178
264
|
router.get('/:projectId/tickets/:id', (req, res) => {
|
|
179
265
|
const ticketId = req.params.id;
|
|
@@ -244,19 +330,11 @@ function registerTicketsRoutes(deps) {
|
|
|
244
330
|
const projectId = project.id;
|
|
245
331
|
const admission = (0, process_admission_1.captureProcessAdmission)(projectId);
|
|
246
332
|
const filePath = ticketPath(req);
|
|
247
|
-
let
|
|
248
|
-
let baseUserPrompt = `Generate a spec for the following idea:\n\n${idea.trim()}`;
|
|
249
|
-
let imageFlags = [];
|
|
250
|
-
let imagePaths = [];
|
|
333
|
+
let attachments;
|
|
251
334
|
if (attachmentIds.length > 0 && pendingSpecId) {
|
|
252
335
|
try {
|
|
253
336
|
const extracted = await attachment_manager_1.attachmentManager.getClaudeArgs(project.slug, pendingSpecId, attachmentIds);
|
|
254
|
-
|
|
255
|
-
imagePaths = extracted.imagePaths;
|
|
256
|
-
if (extracted.textBlocks.length > 0) {
|
|
257
|
-
hasAttachments = true;
|
|
258
|
-
baseUserPrompt = `${baseUserPrompt}\n\n## Attached Resources\n\n${extracted.textBlocks.join('\n\n')}`;
|
|
259
|
-
}
|
|
337
|
+
attachments = { textBlocks: extracted.textBlocks, imageFlags: extracted.imageFlags, imagePaths: extracted.imagePaths };
|
|
260
338
|
}
|
|
261
339
|
catch (err) {
|
|
262
340
|
console.error('[project-router] generate-spec attachment extraction error:', err);
|
|
@@ -286,16 +364,12 @@ function registerTicketsRoutes(deps) {
|
|
|
286
364
|
// Quick spawns from project.path, so project `.mcp.json` (the `mcp`
|
|
287
365
|
// toggle) is discovered natively. `userMcp` additionally loads the
|
|
288
366
|
// developer's user-scope/plugin/connector MCP servers via the claude
|
|
289
|
-
// adapter's `loadUserEnv
|
|
367
|
+
// adapter's `loadUserEnv`.
|
|
290
368
|
mcp: typeof rawScope?.mcp === 'boolean' ? rawScope.mcp : false,
|
|
291
369
|
contractRefine: quickContractRefine,
|
|
292
370
|
userMcp: typeof rawScope?.userMcp === 'boolean' ? rawScope.userMcp : false,
|
|
293
371
|
};
|
|
294
|
-
|
|
295
|
-
const quickToolPolicy = quickScope.full
|
|
296
|
-
? ((0, runtime_1.supportsToolPolicy)(adapter, 'read-only') ? 'read-only' : null)
|
|
297
|
-
: (0, runtime_1.pureOutputToolPolicy)(adapter);
|
|
298
|
-
if (!quickToolPolicy) {
|
|
372
|
+
if (!(0, spec_generation_1.resolveSpecGenerationToolPolicy)(provider, quickScope)) {
|
|
299
373
|
res.status(409).json({
|
|
300
374
|
error: 'provider_tool_policy_unsupported',
|
|
301
375
|
provider,
|
|
@@ -305,269 +379,45 @@ function registerTicketsRoutes(deps) {
|
|
|
305
379
|
}
|
|
306
380
|
// Persist Quick mode Contract Refine choice (per-project last value).
|
|
307
381
|
(0, db_1.setQuickContractRefineLast)(ctx(req).db, quickContractRefine);
|
|
308
|
-
//
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
:
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
// an explicit dedup instruction the model treats it as background and
|
|
322
|
-
// still proposes a near-duplicate of something already in the backlog.
|
|
323
|
-
// Adding the rule here, gated on `quickScope.specrails`, keeps the
|
|
324
|
-
// "toggle is the only gate" contract the user asked for.
|
|
325
|
-
const dedupRule = quickScope.specrails
|
|
326
|
-
? `- The "Specrails Tickets" section above lists every ticket already in the backlog. Do NOT propose a duplicate or a near-duplicate of any of them. If the user's idea is already covered by an existing ticket, say so in "Problem Statement" and pick a *different* angle / sub-feature / next step that builds on the existing one — do not repeat it.\n`
|
|
327
|
-
: '';
|
|
328
|
-
const backlogRecommendationRule = quickScope.specrails
|
|
329
|
-
? `- If the user's idea asks for the "next best spec" or a backlog recommendation, use the existing tickets and OpenSpec context to choose one concrete next spec. Do not respond with generic product directions.\n`
|
|
330
|
-
: '';
|
|
331
|
-
let baseSystemPrompt = `You are a senior product engineer generating a structured spec proposal.\n\n` +
|
|
332
|
-
(specsPrefix ? `${specsPrefix}\n\n` : '') +
|
|
333
|
-
`RULES:\n` +
|
|
334
|
-
`${codebaseRule}\n` +
|
|
335
|
-
dedupRule +
|
|
336
|
-
backlogRecommendationRule +
|
|
337
|
-
`- Do NOT create files, tickets, or issues.\n` +
|
|
338
|
-
`- Output ONLY the structured markdown below. No preamble, no explanation.\n\n` +
|
|
339
|
-
`REQUIRED FORMAT:\n` +
|
|
340
|
-
`## Spec Title\n[Concise, action-oriented title]\n\n` +
|
|
341
|
-
`## Labels\n[2-4 short kebab-case tags categorising the spec — comma-separated on one line, e.g. "ui, settings, dark-mode". Lowercase, no spaces inside a tag.]\n\n` +
|
|
342
|
-
`## Problem Statement\n[2-3 sentences]\n\n` +
|
|
343
|
-
`## Proposed Solution\n[3-5 sentences]\n\n` +
|
|
344
|
-
`## Out of Scope\n[Bullet list]\n\n` +
|
|
345
|
-
`## Acceptance Criteria\n[Numbered list of testable outcomes]\n\n` +
|
|
346
|
-
`## Technical Considerations\n[Bullet list]\n\n` +
|
|
347
|
-
`## Estimated Complexity\n[Low/Medium/High/Very High + one sentence justification]\n\n` +
|
|
348
|
-
`## Short Summary\n[One or two plain-language sentences, max 120 characters total, that capture the essence of this spec for a dashboard postit. No markdown, no bullets, no headings.]`;
|
|
349
|
-
if (hasAttachments)
|
|
350
|
-
baseSystemPrompt = `${baseSystemPrompt}\n\n${attachment_manager_1.USER_ATTACHMENT_SYSTEM_NOTE}`;
|
|
351
|
-
const selectedIds = res.locals.repositoryIds;
|
|
352
|
-
if ((0, project_repositories_1.getProjectRepositories)(project).length > 1) {
|
|
353
|
-
baseSystemPrompt += `\n\nThis logical project has one shared backlog across these repositories: ${JSON.stringify((0, project_repositories_1.getProjectRepositories)(project).map(({ id, name, path, isPrimary, kind }) => ({ id, name, path, isPrimary, kind })))}.\nThis spec targets repository IDs: ${JSON.stringify(selectedIds ?? [(0, project_repositories_1.getProjectRepositories)(project).find((repo) => repo.isPrimary).id])}. Describe cross-repository contracts when selected; do not create separate tickets per repository.`;
|
|
354
|
-
}
|
|
355
|
-
const systemPrompt = baseSystemPrompt;
|
|
356
|
-
const userPrompt = baseUserPrompt;
|
|
357
|
-
// Generate-spec spawn args are adapter-driven. For Claude the `--tools`
|
|
358
|
-
// flag set comes from `toolFlagsForScope(quickScope)` which the adapter
|
|
359
|
-
// doesn't model — pass them through `extraArgs` so they slot in after
|
|
360
|
-
// the standard COMMON_FLAGS. `imageFlags` (also Claude-only) goes the
|
|
361
|
-
// same way. For codex the system prompt folds into the user prompt
|
|
362
|
-
// (no --system-prompt flag) and the extra Claude-only flags are ignored
|
|
363
|
-
// by the codex adapter (it doesn't read extraArgs that don't apply).
|
|
364
|
-
const toolFlags = provider === 'claude' ? (0, context_scope_1.toolFlagsForScope)(quickScope) : { args: [] };
|
|
365
|
-
// Full scope grants Read/Grep/Glob. The model spends turns exploring the
|
|
366
|
-
// repo before it writes the spec; 6 was too tight (a few tool calls on a
|
|
367
|
-
// sparse/empty repo hit error_max_turns → exit 1 → opaque failure). 15
|
|
368
|
-
// leaves comfortable headroom while --max-turns still bounds runaway loops.
|
|
369
|
-
const claudeMaxTurns = quickScope.full ? 15 : (hasAttachments ? 3 : 1);
|
|
370
|
-
const specGenOptions = {
|
|
371
|
-
prompt: userPrompt,
|
|
372
|
-
systemPrompt,
|
|
382
|
+
// The spec-generation use case owns the provider spawn, parsing, ticket
|
|
383
|
+
// persistence, Contract Layer scheduling and accounting; this route maps
|
|
384
|
+
// its lifecycle onto the spec_gen_* / ticket_created WebSocket contract.
|
|
385
|
+
(0, spec_generation_1.startSpecGeneration)({
|
|
386
|
+
db: ctx(req).db,
|
|
387
|
+
project,
|
|
388
|
+
ticketStorePath: filePath,
|
|
389
|
+
ticketWatcher,
|
|
390
|
+
broadcast: broadcast,
|
|
391
|
+
admission,
|
|
392
|
+
}, {
|
|
393
|
+
text: idea,
|
|
394
|
+
provider,
|
|
373
395
|
model: resolvedModel,
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
console.log(`[project-router] spec-gen spawn: ${binary} (cwd=${specGenExec.cwd}, requestId=${requestId})`);
|
|
397
|
-
const child = (0, cli_prompt_1.spawnAiCli)(binary, args, {
|
|
398
|
-
env: (0, runtime_1.buildProviderEnv)(adapter, specGenOptions, specGenEnv),
|
|
399
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
400
|
-
cwd: specGenExec.cwd,
|
|
401
|
-
});
|
|
402
|
-
// Register so removeProject()/shutdown() can tree-kill this otherwise-untracked
|
|
403
|
-
// fire-and-forget child (auto-unregisters on close/error).
|
|
404
|
-
(0, transient_children_1.trackTransientChild)(projectId, child);
|
|
405
|
-
// Watchdog: unlike ai-edit, generate-spec keeps no cancellable handle, so a
|
|
406
|
-
// hung CLI (network stall, model never emitting a terminating event) would
|
|
407
|
-
// otherwise leak this child + its readline for the app's lifetime. Cap is
|
|
408
|
-
// generous — the 'full' scope can legitimately run minutes and --max-turns
|
|
409
|
-
// bounds turns, not wall-clock. Cleared on close/error.
|
|
410
|
-
const GENERATE_SPEC_TIMEOUT_MS = 8 * 60 * 1000;
|
|
411
|
-
let specGenWatchdog = setTimeout(() => {
|
|
412
|
-
specGenWatchdog = null;
|
|
413
|
-
if (child.pid) {
|
|
414
|
-
try {
|
|
415
|
-
(0, tree_kill_1.default)(child.pid, 'SIGTERM');
|
|
416
|
-
}
|
|
417
|
-
catch { /* best-effort */ }
|
|
418
|
-
}
|
|
419
|
-
if (!admission.isCurrent())
|
|
420
|
-
return;
|
|
421
|
-
broadcast({
|
|
422
|
-
type: 'spec_gen_error', projectId, requestId,
|
|
423
|
-
error: `Spec generation timed out after ${Math.round(GENERATE_SPEC_TIMEOUT_MS / 1000)}s`,
|
|
424
|
-
timestamp: new Date().toISOString(),
|
|
425
|
-
});
|
|
426
|
-
}, GENERATE_SPEC_TIMEOUT_MS);
|
|
427
|
-
if (typeof specGenWatchdog.unref === 'function')
|
|
428
|
-
specGenWatchdog.unref();
|
|
429
|
-
const clearSpecGenWatchdog = () => {
|
|
430
|
-
if (specGenWatchdog) {
|
|
431
|
-
clearTimeout(specGenWatchdog);
|
|
432
|
-
specGenWatchdog = null;
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
// Capture stderr so failures (auth missing, model errors, etc.) surface
|
|
436
|
-
// in the server log instead of being swallowed.
|
|
437
|
-
let stderrBuf = '';
|
|
438
|
-
/* c8 ignore start -- diagnostic-only; fires only when claude writes stderr */
|
|
439
|
-
child.stderr?.on('data', (chunk) => {
|
|
440
|
-
const s = chunk.toString();
|
|
441
|
-
stderrBuf += s;
|
|
442
|
-
console.error(`[project-router] spec-gen stderr (${requestId}): ${s.trimEnd()}`);
|
|
443
|
-
});
|
|
444
|
-
/* c8 ignore stop */
|
|
445
|
-
// Without this listener, ENOENT (binary missing on PATH) propagates as
|
|
446
|
-
// an unhandled 'error' event and crashes the entire app process.
|
|
447
|
-
/* c8 ignore start -- spawn-failure path; exercised manually, not in CI */
|
|
448
|
-
child.on('error', (err) => {
|
|
449
|
-
clearSpecGenWatchdog();
|
|
450
|
-
console.error(`[project-router] spec-gen spawn failed (${binary}): ${err.message}`);
|
|
451
|
-
if (!admission.isCurrent())
|
|
452
|
-
return;
|
|
453
|
-
const errMsg = {
|
|
454
|
-
type: 'spec_gen_error', projectId, requestId,
|
|
455
|
-
error: `Failed to launch ${binary}: ${err.message}`,
|
|
456
|
-
timestamp: new Date().toISOString(),
|
|
457
|
-
};
|
|
458
|
-
broadcast(errMsg);
|
|
459
|
-
});
|
|
460
|
-
/* c8 ignore stop */
|
|
461
|
-
res.status(202).json({ requestId });
|
|
462
|
-
let buffer = '';
|
|
463
|
-
let lastResultEvent = null;
|
|
464
|
-
// Canonical adapter events feed finaliseInvocationResult on close, giving
|
|
465
|
-
// codex a real pricing-table cost estimate (+ estimated flag) and tokens,
|
|
466
|
-
// instead of the legacy hardcoded $0. Accumulated ALONGSIDE the existing
|
|
467
|
-
// buffer/delta plumbing below — never in place of it.
|
|
468
|
-
const adapterEvents = [];
|
|
469
|
-
const turnStartedAt = new Date().toISOString();
|
|
470
|
-
const stdoutReader = (0, readline_1.createInterface)({ input: child.stdout, crlfDelay: Infinity });
|
|
471
|
-
stdoutReader.on('line', (line) => {
|
|
472
|
-
if (!admission.isCurrent())
|
|
473
|
-
return;
|
|
474
|
-
const eventsForLine = (0, runtime_1.parseStreamEvents)(adapter, line);
|
|
475
|
-
adapterEvents.push(...eventsForLine);
|
|
476
|
-
let parsed = null;
|
|
477
|
-
try {
|
|
478
|
-
parsed = JSON.parse(line);
|
|
479
|
-
}
|
|
480
|
-
catch { /* skip */ }
|
|
481
|
-
if (parsed && eventsForLine.some((event) => event.kind === 'result')) {
|
|
482
|
-
lastResultEvent = parsed;
|
|
483
|
-
}
|
|
484
|
-
for (const event of eventsForLine) {
|
|
485
|
-
if (event.kind !== 'text-delta' || !event.text)
|
|
486
|
-
continue;
|
|
487
|
-
buffer += event.text;
|
|
488
|
-
const wsMsg = {
|
|
489
|
-
type: 'spec_gen_stream', projectId, requestId,
|
|
490
|
-
delta: event.text, timestamp: new Date().toISOString(),
|
|
491
|
-
};
|
|
492
|
-
broadcast(wsMsg);
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
child.on('close', async (code) => {
|
|
496
|
-
clearSpecGenWatchdog();
|
|
497
|
-
if (!admission.isCurrent())
|
|
498
|
-
return;
|
|
499
|
-
let createdTicketId = null;
|
|
500
|
-
// When claude burns its whole --max-turns budget it exits non-zero with
|
|
501
|
-
// a result event of subtype:error_max_turns — but it may already have
|
|
502
|
-
// emitted a complete spec. Salvage that usable output instead of failing
|
|
503
|
-
// the whole request on an exit code.
|
|
504
|
-
const resultSubtype = lastResultEvent?.subtype ?? null;
|
|
505
|
-
const hasUsableSpec = buffer.trim().length > 0 && /##\s*Spec Title/i.test(buffer);
|
|
506
|
-
const salvageMaxTurns = code !== 0 && resultSubtype === 'error_max_turns' && hasUsableSpec;
|
|
507
|
-
if ((code === 0 && buffer.trim()) || salvageMaxTurns) {
|
|
508
|
-
if (salvageMaxTurns) {
|
|
509
|
-
console.warn(`[project-router] spec-gen salvaged partial output after error_max_turns (${requestId}); ` +
|
|
510
|
-
`consider raising --max-turns if this recurs`);
|
|
511
|
-
}
|
|
512
|
-
// Extract title from generated spec
|
|
513
|
-
const titleMatch = buffer.match(/##\s*Spec Title\s*\n+(.+)/);
|
|
514
|
-
const specTitle = titleMatch ? titleMatch[1].trim() : idea.trim().slice(0, 80);
|
|
515
|
-
// Extract complexity for priority mapping
|
|
516
|
-
const complexityMatch = buffer.match(/##\s*Estimated Complexity\s*\n+(\w+)/);
|
|
517
|
-
const complexity = complexityMatch ? complexityMatch[1].toLowerCase() : 'medium';
|
|
518
|
-
const priority = complexity === 'low' ? 'low' : complexity === 'high' || complexity === 'very' ? 'high' : 'medium';
|
|
519
|
-
// Extract labels from the `## Labels` section. Comma- or
|
|
520
|
-
// newline-separated tags, normalised to lowercase kebab-case.
|
|
521
|
-
// `spec-proposal` is always retained as the marker label.
|
|
522
|
-
const labelsMatch = buffer.match(/##\s*Labels\s*\n+([^\n]+(?:\n(?!##)[^\n]+)*)/);
|
|
523
|
-
const claudeLabels = labelsMatch
|
|
524
|
-
? labelsMatch[1]
|
|
525
|
-
.replace(/[\[\]]/g, '')
|
|
526
|
-
.split(/[,\n]/)
|
|
527
|
-
.map((s) => s.trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''))
|
|
528
|
-
.filter((s) => s.length > 0 && s.length <= 32)
|
|
529
|
-
.slice(0, 6)
|
|
530
|
-
: [];
|
|
531
|
-
const finalLabels = Array.from(new Set(['spec-proposal', ...claudeLabels]));
|
|
532
|
-
const shortSummary = (0, ticket_store_1.clampShortSummary)((0, project_router_helpers_1.extractShortSummary)(buffer));
|
|
533
|
-
const description = (0, project_router_helpers_1.stripSpecMetadataSections)(buffer);
|
|
534
|
-
// Create ticket directly
|
|
535
|
-
try {
|
|
536
|
-
const now = new Date().toISOString();
|
|
537
|
-
let created;
|
|
538
|
-
const store = (0, ticket_store_1.mutateStore)(filePath, (s) => {
|
|
539
|
-
const id = s.next_id++;
|
|
540
|
-
const ticket = {
|
|
541
|
-
...repositoryScope(req, res),
|
|
542
|
-
id,
|
|
543
|
-
title: specTitle,
|
|
544
|
-
description,
|
|
545
|
-
status: 'todo',
|
|
546
|
-
priority: priority,
|
|
547
|
-
labels: finalLabels,
|
|
548
|
-
assignee: null,
|
|
549
|
-
prerequisites: [],
|
|
550
|
-
metadata: {},
|
|
551
|
-
comments: [],
|
|
552
|
-
origin_conversation_id: null,
|
|
553
|
-
is_epic: false,
|
|
554
|
-
parent_epic_id: null,
|
|
555
|
-
execution_order: null,
|
|
556
|
-
short_summary: shortSummary,
|
|
557
|
-
created_at: now,
|
|
558
|
-
updated_at: now,
|
|
559
|
-
created_by: 'sr-product-engineer',
|
|
560
|
-
source: 'propose-spec',
|
|
561
|
-
};
|
|
562
|
-
s.tickets[String(id)] = ticket;
|
|
563
|
-
created = ticket;
|
|
564
|
-
});
|
|
565
|
-
ticketWatcher.notifyDesktopWrite(store.revision);
|
|
566
|
-
if (created)
|
|
567
|
-
createdTicketId = created.id;
|
|
396
|
+
scope: quickScope,
|
|
397
|
+
repositoryIds: res.locals.repositoryIds,
|
|
398
|
+
resolveRepositoryScope: () => repositoryScope(req, res),
|
|
399
|
+
attachments,
|
|
400
|
+
contractRefine: quickContractRefine ? { model: req.body?.model ?? null } : null,
|
|
401
|
+
requestId,
|
|
402
|
+
hooks: {
|
|
403
|
+
onDelta: (delta) => {
|
|
404
|
+
const wsMsg = {
|
|
405
|
+
type: 'spec_gen_stream', projectId, requestId,
|
|
406
|
+
delta, timestamp: new Date().toISOString(),
|
|
407
|
+
};
|
|
408
|
+
broadcast(wsMsg);
|
|
409
|
+
},
|
|
410
|
+
onError: (error) => {
|
|
411
|
+
const msg = {
|
|
412
|
+
type: 'spec_gen_error', projectId, requestId,
|
|
413
|
+
error, timestamp: new Date().toISOString(),
|
|
414
|
+
};
|
|
415
|
+
broadcast(msg);
|
|
416
|
+
},
|
|
417
|
+
onPersisted: async (created) => {
|
|
568
418
|
// Migrate attachments from pendingSpecId → real ticket id (if any were uploaded).
|
|
569
419
|
// Must complete BEFORE broadcasting ticket_created so WS listeners see the populated attachments[].
|
|
570
|
-
if (pendingSpecId
|
|
420
|
+
if (pendingSpecId) {
|
|
571
421
|
try {
|
|
572
422
|
const migrated = await attachment_manager_1.attachmentManager.renameTicketDir({
|
|
573
423
|
slug: project.slug,
|
|
@@ -583,7 +433,7 @@ function registerTicketsRoutes(deps) {
|
|
|
583
433
|
console.error('[project-router] generate-spec attachment migration error:', err);
|
|
584
434
|
}
|
|
585
435
|
if (!admission.isCurrent())
|
|
586
|
-
return;
|
|
436
|
+
return 'abort';
|
|
587
437
|
}
|
|
588
438
|
const ticketMsg = {
|
|
589
439
|
type: 'ticket_created', ticket: created,
|
|
@@ -598,91 +448,10 @@ function registerTicketsRoutes(deps) {
|
|
|
598
448
|
// Add Spec → Jira: promote the new ticket to a Jira issue when the
|
|
599
449
|
// project is Jira-backed (unless the user opted to keep it local).
|
|
600
450
|
void maybePromoteSpecToJira(ctx(req), created.id, req.body?.createLocal === true, broadcast);
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
const refineTicketId = created.id;
|
|
604
|
-
const refineTitle = created.title;
|
|
605
|
-
const refineDescription = created.description;
|
|
606
|
-
const refineModel = req.body?.model ?? null;
|
|
607
|
-
process.nextTick(() => {
|
|
608
|
-
if (!admission.isCurrent())
|
|
609
|
-
return;
|
|
610
|
-
void (0, contract_refine_runner_1.runContractRefineForQuick)({
|
|
611
|
-
db: ctx(req).db,
|
|
612
|
-
projectId: project.id,
|
|
613
|
-
projectSlug: project.slug,
|
|
614
|
-
projectPath: project.path,
|
|
615
|
-
projectName: project.name,
|
|
616
|
-
providerId: provider,
|
|
617
|
-
broadcast: broadcast,
|
|
618
|
-
}, refineTicketId, refineTitle, refineDescription, refineModel).catch((err) => {
|
|
619
|
-
console.error('[project-router] runContractRefineForQuick error:', err);
|
|
620
|
-
});
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
catch (err) {
|
|
625
|
-
console.error('[project-router] generate-spec ticket creation error:', err);
|
|
626
|
-
const errMsg = {
|
|
627
|
-
type: 'spec_gen_error', projectId, requestId,
|
|
628
|
-
error: 'Failed to create ticket', timestamp: new Date().toISOString(),
|
|
629
|
-
};
|
|
630
|
-
broadcast(errMsg);
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
const reason = code === 0
|
|
635
|
-
? 'Empty response from AI'
|
|
636
|
-
: resultSubtype === 'error_max_turns'
|
|
637
|
-
? 'AI hit its turn limit before finishing the spec. Try again, or narrow the idea / turn off full-codebase context.'
|
|
638
|
-
: `Process exited with code ${code}`;
|
|
639
|
-
console.error(`[project-router] spec-gen failed (${requestId}): ${reason}` +
|
|
640
|
-
(stderrBuf.trim() ? `\n stderr: ${stderrBuf.trim()}` : '') +
|
|
641
|
-
(buffer.trim() ? `\n stdout-buffer: ${buffer.trim().slice(0, 500)}` : ''));
|
|
642
|
-
const msg = {
|
|
643
|
-
type: 'spec_gen_error', projectId, requestId,
|
|
644
|
-
error: reason,
|
|
645
|
-
timestamp: new Date().toISOString(),
|
|
646
|
-
};
|
|
647
|
-
broadcast(msg);
|
|
648
|
-
}
|
|
649
|
-
// ai_invocations capture (surface='quick-spec'). Always emit a row, success or fail.
|
|
650
|
-
try {
|
|
651
|
-
// Adapter-driven finalisation: claude passes its native total_cost_usd
|
|
652
|
-
// through untouched; codex (nativeCostUsd:false) gets a pricing-table
|
|
653
|
-
// estimate from its captured token usage + estimated=true. This
|
|
654
|
-
// replaces the legacy normaliseResultEvent path that hardcoded codex
|
|
655
|
-
// cost to $0 and never set the estimated flag.
|
|
656
|
-
const { result: normalised, estimated } = (0, result_event_1.finaliseInvocationResult)(adapter, adapterEvents, { fallbackModel: resolvedModel });
|
|
657
|
-
// extractCodexResult does not surface duration (codex stream carries
|
|
658
|
-
// none); stamp wall-clock so the row's duration isn't lost. Claude's
|
|
659
|
-
// result event already provides duration_ms, so prefer it.
|
|
660
|
-
const wallMs = Date.now() - new Date(turnStartedAt).getTime();
|
|
661
|
-
(0, ai_invocations_1.recordInvocation)(ctx(req).db, {
|
|
662
|
-
id: (0, crypto_1.randomUUID)(),
|
|
663
|
-
project_id: projectId,
|
|
664
|
-
provider: adapter.id,
|
|
665
|
-
surface: 'quick-spec',
|
|
666
|
-
surface_ref_id: requestId,
|
|
667
|
-
ticket_id: createdTicketId,
|
|
668
|
-
// A ticket was delivered — whether via the clean code===0 path OR the
|
|
669
|
-
// error_max_turns salvage path — iff createdTicketId is set. Record
|
|
670
|
-
// 'success' for any delivered ticket so success-scoped averages and
|
|
671
|
-
// failureRate are not skewed by salvaged runs (LOW-13). Genuine
|
|
672
|
-
// failures (no ticket) stay 'failed'.
|
|
673
|
-
status: createdTicketId !== null ? 'success' : 'failed',
|
|
674
|
-
started_at: turnStartedAt,
|
|
675
|
-
finished_at: new Date().toISOString(),
|
|
676
|
-
total_cost_usd_estimated: estimated,
|
|
677
|
-
...normalised,
|
|
678
|
-
duration_ms: normalised.duration_ms ?? wallMs,
|
|
679
|
-
});
|
|
680
|
-
broadcast({ type: 'spending.invalidated', projectId });
|
|
681
|
-
}
|
|
682
|
-
catch (err) {
|
|
683
|
-
console.error('[project-router] generate-spec recordInvocation failed:', err);
|
|
684
|
-
}
|
|
451
|
+
},
|
|
452
|
+
},
|
|
685
453
|
});
|
|
454
|
+
res.status(202).json({ requestId });
|
|
686
455
|
});
|
|
687
456
|
// POST /:projectId/tickets/save-as-draft — Persist an in-progress Explore session as a draft ticket
|
|
688
457
|
router.post('/:projectId/tickets/save-as-draft', (req, res) => {
|
|
@@ -848,6 +617,11 @@ function registerTicketsRoutes(deps) {
|
|
|
848
617
|
.filter((c) => c.length > 0)
|
|
849
618
|
: [];
|
|
850
619
|
const priority = (0, ticket_store_1.isValidPriority)(body.priority) ? body.priority : 'medium';
|
|
620
|
+
const draftNonGoals = body.nonGoals === undefined ? null : (0, non_goals_1.validateNonGoals)(body.nonGoals);
|
|
621
|
+
if (draftNonGoals && !draftNonGoals.ok) {
|
|
622
|
+
res.status(400).json({ error: draftNonGoals.error });
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
851
625
|
// Optional assignee/prerequisites/metadata (same normalization as the
|
|
852
626
|
// PATCH /tickets/:id route) so an MCP commit_draft is a true one-shot
|
|
853
627
|
// insert — no follow-up update call needed for these fields.
|
|
@@ -858,7 +632,12 @@ function registerTicketsRoutes(deps) {
|
|
|
858
632
|
? body.prerequisites.filter((p) => typeof p === 'number')
|
|
859
633
|
: [];
|
|
860
634
|
const hasMetadata = typeof body.metadata === 'object' && body.metadata !== null;
|
|
861
|
-
const
|
|
635
|
+
const regressionCheck = (0, ticket_store_1.normalizeRegressionOfMetadata)(hasMetadata ? body.metadata : {});
|
|
636
|
+
if (!regressionCheck.ok) {
|
|
637
|
+
res.status(400).json({ error: regressionCheck.error });
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
const metadata = hasMetadata ? regressionCheck.metadata : {};
|
|
862
641
|
// A supplied conversationId must reference a REAL chat conversation in this
|
|
863
642
|
// project (an Explore row in chat_conversations). Agent/desktop conversation
|
|
864
643
|
// ids are NOT valid origins — stamping one would corrupt the ticket's origin
|
|
@@ -895,6 +674,13 @@ function registerTicketsRoutes(deps) {
|
|
|
895
674
|
if (bodyShortSummary === null) {
|
|
896
675
|
bodyShortSummary = (0, project_router_helpers_1.deriveFallbackShortSummary)(rawTitle, descriptionForStore);
|
|
897
676
|
}
|
|
677
|
+
// Non-goals (3.2): an explicit `nonGoals` list wins; otherwise a draft's
|
|
678
|
+
// `## Out of Scope` section moves into the field. Either way the section
|
|
679
|
+
// leaves the description so the ticket shows it once, under it.
|
|
680
|
+
const outOfScope = (0, non_goals_1.extractOutOfScopeSection)(descriptionForStore);
|
|
681
|
+
const nonGoalsForStore = draftNonGoals?.ok ? draftNonGoals.nonGoals : outOfScope.nonGoals;
|
|
682
|
+
if (draftNonGoals?.ok || outOfScope.nonGoals.length > 0)
|
|
683
|
+
descriptionForStore = outOfScope.description;
|
|
898
684
|
try {
|
|
899
685
|
const filePath = ticketPath(req);
|
|
900
686
|
const now = new Date().toISOString();
|
|
@@ -930,6 +716,8 @@ function registerTicketsRoutes(deps) {
|
|
|
930
716
|
flipTarget.priority = priority;
|
|
931
717
|
flipTarget.title = rawTitle;
|
|
932
718
|
flipTarget.description = descriptionForStore;
|
|
719
|
+
if (nonGoalsForStore.length > 0 || draftNonGoals?.ok)
|
|
720
|
+
flipTarget.nonGoals = nonGoalsForStore;
|
|
933
721
|
if (labels.length > 0)
|
|
934
722
|
flipTarget.labels = labels;
|
|
935
723
|
// PATCH-route semantics: apply only when the field was supplied;
|
|
@@ -939,8 +727,11 @@ function registerTicketsRoutes(deps) {
|
|
|
939
727
|
flipTarget.assignee = assignee;
|
|
940
728
|
if (hasPrerequisites)
|
|
941
729
|
flipTarget.prerequisites = prerequisites;
|
|
942
|
-
if (hasMetadata)
|
|
730
|
+
if (hasMetadata) {
|
|
943
731
|
flipTarget.metadata = { ...flipTarget.metadata, ...metadata };
|
|
732
|
+
if (regressionCheck.clear)
|
|
733
|
+
delete flipTarget.metadata.regressionOf;
|
|
734
|
+
}
|
|
944
735
|
flipTarget.updated_at = now;
|
|
945
736
|
// Preserve prior short_summary on flip when the model/body omits one;
|
|
946
737
|
// overwrite only when a non-null value is provided.
|
|
@@ -984,6 +775,7 @@ function registerTicketsRoutes(deps) {
|
|
|
984
775
|
parent_epic_id: null,
|
|
985
776
|
execution_order: null,
|
|
986
777
|
short_summary: bodyShortSummary,
|
|
778
|
+
...(nonGoalsForStore.length ? { nonGoals: nonGoalsForStore } : {}),
|
|
987
779
|
created_at: now,
|
|
988
780
|
updated_at: now,
|
|
989
781
|
created_by: 'sr-explore-spec',
|
|
@@ -1236,6 +1028,41 @@ function registerTicketsRoutes(deps) {
|
|
|
1236
1028
|
res.status(500).json({ error: 'Failed to create ticket' });
|
|
1237
1029
|
}
|
|
1238
1030
|
});
|
|
1031
|
+
// POST /:projectId/tickets/:id/triage — Recalculate the spec triage
|
|
1032
|
+
// (launch-triage). Forced: runs even when the inputs hash is unchanged. The
|
|
1033
|
+
// record is stored in metadata.triage and announced as ticket_updated.
|
|
1034
|
+
router.post('/:projectId/tickets/:id/triage', async (req, res) => {
|
|
1035
|
+
const ticketId = String(req.params.id ?? '');
|
|
1036
|
+
if (!/^\d+$/.test(ticketId)) {
|
|
1037
|
+
res.status(400).json({ error: 'Invalid ticket ID' });
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
const service = ctx(req).specTriage;
|
|
1041
|
+
if (!service) {
|
|
1042
|
+
res.status(503).json({ error: 'triage_unavailable' });
|
|
1043
|
+
return;
|
|
1044
|
+
}
|
|
1045
|
+
try {
|
|
1046
|
+
const outcome = await service.triageNow(Number(ticketId), { force: true });
|
|
1047
|
+
if (outcome.kind === 'not_found') {
|
|
1048
|
+
res.status(404).json({ error: 'Ticket not found' });
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
if (outcome.kind === 'not_applicable') {
|
|
1052
|
+
res.status(409).json({ error: 'triage_not_applicable', reason: outcome.reason });
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
if (outcome.kind === 'stored' || outcome.kind === 'unchanged') {
|
|
1056
|
+
res.json({ triage: outcome.triage });
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
res.status(503).json({ error: 'triage_unavailable' });
|
|
1060
|
+
}
|
|
1061
|
+
catch (err) {
|
|
1062
|
+
console.error('[project-router] ticket triage error:', err);
|
|
1063
|
+
res.status(500).json({ error: 'Failed to triage ticket' });
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1239
1066
|
// POST /:projectId/tickets/:id/contract-refine — Manually re-fire refine
|
|
1240
1067
|
router.post('/:projectId/tickets/:id/contract-refine', async (req, res) => {
|
|
1241
1068
|
const ticketId = Number.parseInt(String(req.params.id ?? ''), 10);
|
|
@@ -1478,11 +1305,22 @@ function registerTicketsRoutes(deps) {
|
|
|
1478
1305
|
});
|
|
1479
1306
|
// POST /:projectId/tickets — Create new ticket
|
|
1480
1307
|
router.post('/:projectId/tickets', (req, res) => {
|
|
1481
|
-
const { title, description, status, priority, labels, assignee, prerequisites, metadata, source } = req.body ?? {};
|
|
1308
|
+
const { title, description, status, priority, labels, assignee, prerequisites, metadata: rawMetadata, source, nonGoals: rawNonGoals } = req.body ?? {};
|
|
1482
1309
|
if (!title || typeof title !== 'string' || !title.trim()) {
|
|
1483
1310
|
res.status(400).json({ error: 'title is required' });
|
|
1484
1311
|
return;
|
|
1485
1312
|
}
|
|
1313
|
+
const createNonGoals = rawNonGoals === undefined ? null : (0, non_goals_1.validateNonGoals)(rawNonGoals);
|
|
1314
|
+
if (createNonGoals && !createNonGoals.ok) {
|
|
1315
|
+
res.status(400).json({ error: createNonGoals.error });
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
const createRegression = (0, ticket_store_1.normalizeRegressionOfMetadata)(typeof rawMetadata === 'object' && rawMetadata !== null ? rawMetadata : {});
|
|
1319
|
+
if (!createRegression.ok) {
|
|
1320
|
+
res.status(400).json({ error: createRegression.error });
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
const metadata = typeof rawMetadata === 'object' && rawMetadata !== null ? createRegression.metadata : undefined;
|
|
1486
1324
|
if (status !== undefined && !(0, ticket_store_1.isValidStatus)(status)) {
|
|
1487
1325
|
res.status(400).json({ error: 'status must be one of: draft, todo, in_progress, on_review, done, cancelled' });
|
|
1488
1326
|
return;
|
|
@@ -1517,6 +1355,7 @@ function registerTicketsRoutes(deps) {
|
|
|
1517
1355
|
parent_epic_id: null,
|
|
1518
1356
|
execution_order: null,
|
|
1519
1357
|
short_summary: null,
|
|
1358
|
+
...(createNonGoals?.ok && createNonGoals.nonGoals.length ? { nonGoals: createNonGoals.nonGoals } : {}),
|
|
1520
1359
|
created_at: now,
|
|
1521
1360
|
updated_at: now,
|
|
1522
1361
|
created_by: source === 'mcp' ? 'mcp' : 'hub', // 'hub' = legacy on-disk wire value (tickets.json, shared with specrails-core) — do not rename
|
|
@@ -1575,6 +1414,8 @@ function registerTicketsRoutes(deps) {
|
|
|
1575
1414
|
}
|
|
1576
1415
|
res.status(409).json({ error: 'addendum_applied', detail: 'an applied addendum is history; reopen it or add a new one' });
|
|
1577
1416
|
};
|
|
1417
|
+
// GET /:projectId/tickets/:ticketId/timeline and /handoff — the spec lifecycle projection and its export.
|
|
1418
|
+
(0, timeline_http_1.registerSpecTimelineRoutes)(router, { ctx, ticketPath });
|
|
1578
1419
|
// GET /:projectId/tickets/:id/addenda — list a spec's addenda
|
|
1579
1420
|
router.get('/:projectId/tickets/:id/addenda', (req, res) => {
|
|
1580
1421
|
const ticketId = addendaTicketId(req, res);
|
|
@@ -1765,11 +1606,22 @@ function registerTicketsRoutes(deps) {
|
|
|
1765
1606
|
res.status(400).json({ error: 'Invalid ticket ID' });
|
|
1766
1607
|
return;
|
|
1767
1608
|
}
|
|
1768
|
-
const { title, description, status, priority, labels, assignee, prerequisites, metadata, acceptanceCriteria, short_summary } = req.body ?? {};
|
|
1609
|
+
const { title, description, status, priority, labels, assignee, prerequisites, metadata: rawMetadata, acceptanceCriteria, short_summary, nonGoals: rawNonGoals } = req.body ?? {};
|
|
1610
|
+
const patchNonGoals = rawNonGoals === undefined ? null : (0, non_goals_1.validateNonGoals)(rawNonGoals);
|
|
1611
|
+
if (patchNonGoals && !patchNonGoals.ok) {
|
|
1612
|
+
res.status(400).json({ error: patchNonGoals.error });
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1769
1615
|
if (status !== undefined && !(0, ticket_store_1.isValidStatus)(status)) {
|
|
1770
1616
|
res.status(400).json({ error: 'status must be one of: draft, todo, in_progress, on_review, done, cancelled' });
|
|
1771
1617
|
return;
|
|
1772
1618
|
}
|
|
1619
|
+
const patchRegression = (0, ticket_store_1.normalizeRegressionOfMetadata)(typeof rawMetadata === 'object' && rawMetadata !== null ? rawMetadata : {});
|
|
1620
|
+
if (!patchRegression.ok) {
|
|
1621
|
+
res.status(400).json({ error: patchRegression.error });
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
const metadata = typeof rawMetadata === 'object' && rawMetadata !== null ? patchRegression.metadata : rawMetadata;
|
|
1773
1625
|
if (priority !== undefined && priority !== null && !(0, ticket_store_1.isValidPriority)(priority)) {
|
|
1774
1626
|
res.status(400).json({ error: 'priority must be one of: critical, high, medium, low' });
|
|
1775
1627
|
return;
|
|
@@ -1812,6 +1664,13 @@ function registerTicketsRoutes(deps) {
|
|
|
1812
1664
|
}
|
|
1813
1665
|
if (status !== undefined)
|
|
1814
1666
|
ticket.status = status;
|
|
1667
|
+
// Non-goals (3.2): local-only (never a Jira write-back); [] / null clear.
|
|
1668
|
+
if (patchNonGoals?.ok) {
|
|
1669
|
+
if (patchNonGoals.nonGoals.length)
|
|
1670
|
+
ticket.nonGoals = patchNonGoals.nonGoals;
|
|
1671
|
+
else
|
|
1672
|
+
delete ticket.nonGoals;
|
|
1673
|
+
}
|
|
1815
1674
|
if (priority !== undefined)
|
|
1816
1675
|
ticket.priority = nextPriority;
|
|
1817
1676
|
if (labels !== undefined && Array.isArray(labels))
|
|
@@ -1822,6 +1681,8 @@ function registerTicketsRoutes(deps) {
|
|
|
1822
1681
|
ticket.prerequisites = prerequisites.filter((p) => typeof p === 'number');
|
|
1823
1682
|
if (metadata !== undefined && typeof metadata === 'object' && metadata !== null) {
|
|
1824
1683
|
ticket.metadata = { ...ticket.metadata, ...metadata };
|
|
1684
|
+
if (patchRegression.clear)
|
|
1685
|
+
delete ticket.metadata.regressionOf;
|
|
1825
1686
|
}
|
|
1826
1687
|
// Short summary: explicit non-empty overwrites; explicit null clears;
|
|
1827
1688
|
// omitted leaves the existing value untouched (preserves prior summary
|
|
@@ -1862,8 +1723,11 @@ function registerTicketsRoutes(deps) {
|
|
|
1862
1723
|
changes.priority = u.priority ?? null;
|
|
1863
1724
|
if (labels !== undefined)
|
|
1864
1725
|
changes.labels = u.labels;
|
|
1726
|
+
// A label-only edit is undoable for a few seconds in the UI: hold its Jira
|
|
1727
|
+
// write past that window so an undone change never reaches Jira.
|
|
1728
|
+
const labelsOnly = Object.keys(changes).length === 1 && changes.labels !== undefined;
|
|
1865
1729
|
if (Object.keys(changes).length > 0)
|
|
1866
|
-
jiraSyncManager?.onSpecEdited(Number(ticketId), changes);
|
|
1730
|
+
jiraSyncManager?.onSpecEdited(Number(ticketId), changes, labelsOnly ? { holdMs: UNDO_WINDOW_HOLD_MS } : {});
|
|
1867
1731
|
}
|
|
1868
1732
|
catch (e) {
|
|
1869
1733
|
console.error('[project-router] jira write-back enqueue failed:', e);
|
|
@@ -2000,7 +1864,7 @@ function registerTicketsRoutes(deps) {
|
|
|
2000
1864
|
// spawnAiCli reroutes multi-line argv values through stdin on Windows.
|
|
2001
1865
|
console.log(`[project-router] ai-edit spawn: ${binary} (cwd=${project.path}, requestId=${requestId})`);
|
|
2002
1866
|
const child = (0, cli_prompt_1.spawnAiCli)(binary, args, {
|
|
2003
|
-
env: (0, runtime_1.buildProviderEnv)(adapter, aiEditOptions),
|
|
1867
|
+
env: (0, runtime_1.buildProviderEnv)(adapter, aiEditOptions, (0, project_env_1.projectAgentSourceEnv)(ctx(req).db, (0, runtime_1.providerEnvAllowlist)(adapter))),
|
|
2004
1868
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
2005
1869
|
cwd: project.path,
|
|
2006
1870
|
});
|
|
@@ -2123,6 +1987,11 @@ function registerTicketsRoutes(deps) {
|
|
|
2123
1987
|
res.json({ ok: true });
|
|
2124
1988
|
});
|
|
2125
1989
|
// DELETE /:projectId/tickets/:id — Delete ticket
|
|
1990
|
+
// DELETE /:projectId/tickets/:id — soft delete: the spec moves to "Recently
|
|
1991
|
+
// deleted" (restorable for 30 days). Attachments, its Explore draft
|
|
1992
|
+
// conversation and the Jira link stay untouched until the entry is purged or
|
|
1993
|
+
// deleted permanently, so Undo is lossless and Jira never sees a transient
|
|
1994
|
+
// delete (a spec delete has never written to Jira).
|
|
2126
1995
|
router.delete('/:projectId/tickets/:id', (req, res) => {
|
|
2127
1996
|
const ticketId = req.params.id;
|
|
2128
1997
|
if (!/^\d+$/.test(ticketId)) {
|
|
@@ -2130,76 +1999,26 @@ function registerTicketsRoutes(deps) {
|
|
|
2130
1999
|
return;
|
|
2131
2000
|
}
|
|
2132
2001
|
try {
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2135
|
-
let orphanedConversationId = null;
|
|
2136
|
-
const orphanedChildren = [];
|
|
2137
|
-
const numericId = Number(ticketId);
|
|
2138
|
-
const store = (0, ticket_store_1.mutateStore)(filePath, (s) => {
|
|
2139
|
-
const t = s.tickets[ticketId];
|
|
2140
|
-
if (!t)
|
|
2141
|
-
return;
|
|
2142
|
-
// If this is a draft and no other ticket references the same
|
|
2143
|
-
// origin_conversation_id, mark it for cascade delete.
|
|
2144
|
-
if (t.status === 'draft' && t.origin_conversation_id) {
|
|
2145
|
-
const otherRefs = Object.values(s.tickets).some((other) => other.id !== t.id && other.origin_conversation_id === t.origin_conversation_id);
|
|
2146
|
-
if (!otherRefs)
|
|
2147
|
-
orphanedConversationId = t.origin_conversation_id;
|
|
2148
|
-
}
|
|
2149
|
-
// SMASH: when deleting an épica, orphan its children (set
|
|
2150
|
-
// parent_epic_id/execution_order to null) rather than cascade-delete.
|
|
2151
|
-
if (t.is_epic) {
|
|
2152
|
-
const now = new Date().toISOString();
|
|
2153
|
-
for (const childId of Object.keys(s.tickets)) {
|
|
2154
|
-
const child = s.tickets[childId];
|
|
2155
|
-
if (child.parent_epic_id === numericId) {
|
|
2156
|
-
child.parent_epic_id = null;
|
|
2157
|
-
child.execution_order = null;
|
|
2158
|
-
child.updated_at = now;
|
|
2159
|
-
orphanedChildren.push(child);
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
|
-
}
|
|
2163
|
-
delete s.tickets[ticketId];
|
|
2164
|
-
found = true;
|
|
2165
|
-
});
|
|
2166
|
-
if (!found) {
|
|
2002
|
+
const result = (0, ticket_trash_1.softDeleteTicket)(ticketPath(req), Number(ticketId));
|
|
2003
|
+
if (!result) {
|
|
2167
2004
|
res.status(404).json({ error: 'Ticket not found' });
|
|
2168
2005
|
return;
|
|
2169
2006
|
}
|
|
2170
|
-
const { broadcast, ticketWatcher,
|
|
2171
|
-
ticketWatcher.notifyDesktopWrite(
|
|
2172
|
-
// Cascade-delete attachments for this ticket
|
|
2173
|
-
attachment_manager_1.attachmentManager.deleteAll(ctx(req).project.slug, ticketId).catch((e) => {
|
|
2174
|
-
console.error('[project-router] attachment cascade delete failed:', e);
|
|
2175
|
-
});
|
|
2176
|
-
// Cascade-delete the orphaned Explore conversation, if any.
|
|
2177
|
-
if (orphanedConversationId) {
|
|
2178
|
-
try {
|
|
2179
|
-
const conv = (0, db_1.getConversation)(db, orphanedConversationId);
|
|
2180
|
-
if (conv && conv.kind === 'explore') {
|
|
2181
|
-
(0, db_1.deleteConversation)(db, orphanedConversationId);
|
|
2182
|
-
chatManager?.forgetSpecDraft(orphanedConversationId);
|
|
2183
|
-
chatManager?.forgetExploreLifecycle(orphanedConversationId);
|
|
2184
|
-
}
|
|
2185
|
-
}
|
|
2186
|
-
catch (err) {
|
|
2187
|
-
console.error('[project-router] orphan conversation cleanup failed:', err);
|
|
2188
|
-
}
|
|
2189
|
-
}
|
|
2007
|
+
const { broadcast, ticketWatcher, project } = ctx(req);
|
|
2008
|
+
ticketWatcher.notifyDesktopWrite(result.revision);
|
|
2190
2009
|
// Broadcast ticket_updated for each orphaned child so observers see them
|
|
2191
2010
|
// as regular tickets (no longer attached to the deleted épica).
|
|
2192
|
-
for (const child of orphanedChildren) {
|
|
2011
|
+
for (const child of result.orphanedChildren) {
|
|
2193
2012
|
broadcast({
|
|
2194
2013
|
type: 'ticket_updated',
|
|
2195
2014
|
ticket: child,
|
|
2196
|
-
projectId:
|
|
2015
|
+
projectId: project.id,
|
|
2197
2016
|
timestamp: new Date().toISOString(),
|
|
2198
2017
|
});
|
|
2199
2018
|
}
|
|
2200
|
-
const msg = { type: 'ticket_deleted', ticketId: Number(ticketId), projectId:
|
|
2019
|
+
const msg = { type: 'ticket_deleted', ticketId: Number(ticketId), projectId: project.id, timestamp: new Date().toISOString() };
|
|
2201
2020
|
broadcast(msg);
|
|
2202
|
-
res.json({ ok: true, revision:
|
|
2021
|
+
res.json({ ok: true, revision: result.revision, restorable: true });
|
|
2203
2022
|
}
|
|
2204
2023
|
catch (err) {
|
|
2205
2024
|
console.error('[project-router] ticket delete error:', err);
|