specrails-desktop 2.58.1 → 2.59.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -5
- package/client/dist/assets/{ActivityFeedPage-BQGppIR0.js → ActivityFeedPage-vAY9C71W.js} +1 -1
- package/client/dist/assets/AgentBrowserCapture-CpwjGXQm.js +1 -0
- package/client/dist/assets/AgentModeAnalyticsPane-BHeoJVxQ.js +2 -0
- package/client/dist/assets/AgentModeCodePane-B0Nf3YkN.js +2 -0
- package/client/dist/assets/{AgentModeJobsPane-DR_06oqH.js → AgentModeJobsPane-CpbIItY_.js} +1 -1
- package/client/dist/assets/{AgentsPage-BKIKjm_1.js → AgentsPage-BVJAFXn3.js} +3 -3
- package/client/dist/assets/{AnalyticsPage-069npRVo.js → AnalyticsPage-DDWees-K.js} +1 -1
- package/client/dist/assets/CodePage-CzV5tkvS.js +3 -0
- package/client/dist/assets/{DesktopAnalyticsPage-qtWAPM47.js → DesktopAnalyticsPage-DfRHNK7i.js} +1 -1
- package/client/dist/assets/DocsDialog-BxduBYbh.js +11 -0
- package/client/dist/assets/DocsPage-DOVeRJn_.js +11 -0
- package/client/dist/assets/{ExportDropdown-BcMpvV89.js → ExportDropdown-BnKVV8UK.js} +1 -1
- package/client/dist/assets/InteractiveJobComposer-Da9dvM-0.js +19 -0
- package/client/dist/assets/JobDetailModal-DhwKbZGe.js +1 -0
- package/client/dist/assets/JobDetailPage-MtPE-E_1.js +1 -0
- package/client/dist/assets/JobsPage-0vdlbNik.js +1 -0
- package/client/dist/assets/LoopBuilderPage-DCUHozXh.js +1 -0
- package/client/dist/assets/{LoopPreviewModal-je5pSCf-.js → LoopPreviewModal-Df-S8NGf.js} +1 -1
- package/client/dist/assets/LoopWindowSurface-sdb7QbSo.js +1 -0
- package/client/dist/assets/LoopsPage-CDfCC9Px.js +2 -0
- package/client/dist/assets/MinimizedChatsContext-DKlPf54Y.js +1 -0
- package/client/dist/assets/PluginsPage-iL0G3rQQ.js +2 -0
- package/client/dist/assets/ProjectSettingsDialog-DOkjT7xv.js +1 -0
- package/client/dist/assets/{RepositoryDeliveries-BiwJuS8r.js → RepositoryDeliveries-CJVpOUpZ.js} +1 -1
- package/client/dist/assets/RepositoryScopeSelector-BeM-2gIZ.js +2 -0
- package/client/dist/assets/ReviewPacketPage-EBCim2w_.js +4 -0
- package/client/dist/assets/TemplatePreviewModal-1-92UGwN.js +1 -0
- package/client/dist/assets/TicketDetailModalContext-CkVXuHxU.js +16 -0
- package/client/dist/assets/{Trans-D3AfDylf.js → Trans-CzhPjnjB.js} +1 -1
- package/client/dist/assets/agent--8QAfoXL.js +1 -0
- package/client/dist/assets/agent-3HxXkIWX.js +1 -0
- package/client/dist/assets/agent-BjttZLIl.js +1 -0
- package/client/dist/assets/agent-CpFCz32T.js +1 -0
- package/client/dist/assets/agent-DVnw6ybO.js +1 -0
- package/client/dist/assets/agent-Z5s_GTP0.js +1 -0
- package/client/dist/assets/agent-hv57-zyG.js +1 -0
- package/client/dist/assets/agent-xGrZ_aN1.js +1 -0
- package/client/dist/assets/{agentRuntime-DGz_IqKW.js → agentRuntime-15Pkk6we.js} +1 -1
- package/client/dist/assets/agentRuntime-Bpx3yWHK.js +1 -0
- package/client/dist/assets/{agentRuntime-Bg9tbmqm.js → agentRuntime-C78n13To.js} +1 -1
- package/client/dist/assets/{agentRuntime-D-GJVGkj.js → agentRuntime-CCI7XF4c.js} +1 -1
- package/client/dist/assets/{agentRuntime-D2__CVI_.js → agentRuntime-CKDHe2-a.js} +1 -1
- package/client/dist/assets/{agentRuntime-D35dGVOP.js → agentRuntime-Ddqvp2bP.js} +1 -1
- package/client/dist/assets/{agentRuntime-hInH9Fzj.js → agentRuntime-TXPQowKJ.js} +1 -1
- package/client/dist/assets/{agentRuntime-O1liDt6G.js → agentRuntime-hqZRy08E.js} +1 -1
- package/client/dist/assets/{builder-DGETbtZj.js → builder-B9gorTnT.js} +1 -1
- package/client/dist/assets/{builder-DyQperXU.js → builder-Bvw5s3Mi.js} +1 -1
- package/client/dist/assets/{builder-C1neIYGR.js → builder-CL5l4dU3.js} +1 -1
- package/client/dist/assets/{builder-DXEJUlC0.js → builder-CVDTVrQX.js} +1 -1
- package/client/dist/assets/{builder-CzW5ovyI.js → builder-CpS9liE9.js} +1 -1
- package/client/dist/assets/{builder-CvnFm0im.js → builder-DNctIL9Q.js} +1 -1
- package/client/dist/assets/{builder-D06L7iPy.js → builder-De2NxX6o.js} +1 -1
- package/client/dist/assets/{builder-C0FyvM83.js → builder-DeYT7Y-m.js} +1 -1
- package/client/dist/assets/{button-Ccc9Dc-D.js → button-D1xExSTF.js} +1 -1
- package/client/dist/assets/{common-DmsclwjP.js → common-Bdi0qN4S.js} +1 -1
- package/client/dist/assets/{common-C4Yvvhp6.js → common-Bhb9zN1P.js} +1 -1
- package/client/dist/assets/{common-od8WThlf.js → common-BykKlZg1.js} +1 -1
- package/client/dist/assets/{common-C0BOdeNi.js → common-CvnNNSJA.js} +1 -1
- package/client/dist/assets/{common-BCK7c9Pv.js → common-D5zk_mqq.js} +1 -1
- package/client/dist/assets/{common-DpLWwgI1.js → common-DQNO_al5.js} +1 -1
- package/client/dist/assets/{common-OCvl3c8t.js → common-Dax30Vmp.js} +1 -1
- package/client/dist/assets/{common-c0aujEZC.js → common-DkllpVSb.js} +1 -1
- package/client/dist/assets/{dialog-xXB2q5HJ.js → dialog-CMgps2MY.js} +1 -1
- package/client/dist/assets/external-link-D6XxC_Cu.js +1 -0
- package/client/dist/assets/file-text-BcLCfcWZ.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-aBss1Nai.js → formatDistanceToNow-DlQaXc7c.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DOGj1Mfz.js → getTimezoneOffsetInMilliseconds-DxUFGcVq.js} +1 -1
- package/client/dist/assets/index-Bfunvi6w.css +2 -0
- package/client/dist/assets/index-Czov72g7.js +83 -0
- package/client/dist/assets/integrations-BkpRUbvp.js +1 -0
- package/client/dist/assets/integrations-Bo8qbJf4.js +1 -0
- package/client/dist/assets/integrations-CmSrKzZb.js +1 -0
- package/client/dist/assets/integrations-DGtq26Rr.js +1 -0
- package/client/dist/assets/integrations-De38GFnQ.js +1 -0
- package/client/dist/assets/integrations-Dw6zdtb-.js +1 -0
- package/client/dist/assets/integrations-Dwl9KQp0.js +1 -0
- package/client/dist/assets/integrations-Refg_d2I.js +1 -0
- package/client/dist/assets/jira-api-CbJvbRYx.js +1 -0
- package/client/dist/assets/{jobs-KG4Sn12X.js → jobs-1G3wodhl.js} +1 -1
- package/client/dist/assets/{jobs-6_-r75yC.js → jobs-B4pu8TdF.js} +1 -1
- package/client/dist/assets/{jobs-pPv4KWjb.js → jobs-BD47Ov11.js} +1 -1
- package/client/dist/assets/{jobs-B1yqyId5.js → jobs-BLOoVRRl.js} +1 -1
- package/client/dist/assets/{jobs-BKiK-ZWh.js → jobs-CSrRx5lD.js} +1 -1
- package/client/dist/assets/{jobs-BFuV7ttH.js → jobs-DZAbh1m2.js} +1 -1
- package/client/dist/assets/{jobs-DmKV7b7d.js → jobs-epP7gt8W.js} +1 -1
- package/client/dist/assets/{jobs-BKa8LuwA.js → jobs-tWjcDF_6.js} +1 -1
- package/client/dist/assets/loops--KWr0X-w.js +1 -0
- package/client/dist/assets/{loops-BO3V8244.js → loops-3IutojWt.js} +1 -1
- package/client/dist/assets/{loops-C-hZK8pf.js → loops-BAosWtXE.js} +1 -1
- package/client/dist/assets/{loops-eUnCfLjC.js → loops-BISDssL5.js} +1 -1
- package/client/dist/assets/{loops-Dv849ckF.js → loops-Cm55CXJ4.js} +1 -1
- package/client/dist/assets/{loops-CDOWZ0ci.js → loops-D7tL_Saw.js} +1 -1
- package/client/dist/assets/{loops-BJDY9FTh.js → loops-DHQtnfze.js} +1 -1
- package/client/dist/assets/{loops-Q9LIgGkq.js → loops-kIJJkaxf.js} +1 -1
- package/client/dist/assets/nav--u7iPYlS.js +1 -0
- package/client/dist/assets/nav-C5Jgfaby.js +1 -0
- package/client/dist/assets/nav-CAna_Wpt.js +1 -0
- package/client/dist/assets/nav-CCLqeyHo.js +1 -0
- package/client/dist/assets/nav-Cf3c90Jk.js +1 -0
- package/client/dist/assets/nav-DMYQaQjR.js +1 -0
- package/client/dist/assets/nav-Df_PkZ9F.js +1 -0
- package/client/dist/assets/nav-VyNGBJwj.js +1 -0
- package/client/dist/assets/{project-repositories-CSnfzUpg.js → project-repositories-BkBD3rxx.js} +1 -1
- package/client/dist/assets/provider-capabilities-lePfeT_Y.js +1 -0
- package/client/dist/assets/save-OsUqVn99.js +1 -0
- package/client/dist/assets/settings-B5Hy_Kol.js +1 -0
- package/client/dist/assets/settings-BBj_kZaD.js +1 -0
- package/client/dist/assets/settings-ByVE7jdZ.js +1 -0
- package/client/dist/assets/settings-COlH_P33.js +1 -0
- package/client/dist/assets/settings-D77mC_Lb.js +1 -0
- package/client/dist/assets/settings-DZKy7MqN.js +1 -0
- package/client/dist/assets/settings-Dbyd6gmj.js +1 -0
- package/client/dist/assets/settings-Dn-pXukr.js +1 -0
- package/client/dist/assets/setup-Be485n2u.js +1 -0
- package/client/dist/assets/setup-CKGUxKr-.js +1 -0
- package/client/dist/assets/setup-Ck1Uwd7_.js +1 -0
- package/client/dist/assets/setup-Cm774a6v.js +1 -0
- package/client/dist/assets/setup-DIqMQpxt.js +1 -0
- package/client/dist/assets/setup-DfCsoNFL.js +1 -0
- package/client/dist/assets/setup-DkeE8mP0.js +1 -0
- package/client/dist/assets/setup-xVntVaz1.js +1 -0
- package/client/dist/assets/{spending-HBSk-6jv.js → spending-CYotH-9N.js} +1 -1
- package/client/dist/assets/subscriptionUsage-BH73RO86.js +1 -0
- package/client/dist/assets/subscriptionUsage-BWTeWlHx.js +1 -0
- package/client/dist/assets/subscriptionUsage-CBh82zVa.js +1 -0
- package/client/dist/assets/subscriptionUsage-CHcQ7lLe.js +1 -0
- package/client/dist/assets/subscriptionUsage-CdlE5Mg1.js +1 -0
- package/client/dist/assets/subscriptionUsage-DUPBmSQi.js +1 -0
- package/client/dist/assets/subscriptionUsage-DrlwrJ17.js +1 -0
- package/client/dist/assets/subscriptionUsage-EFu0mIK3.js +1 -0
- package/client/dist/assets/tauri-shell-DE6LfGPw.js +2 -0
- package/client/dist/assets/{useDesktop-0unHDBJJ.js → useDesktop-DpxVGfUC.js} +1 -1
- package/client/dist/assets/{useRuntimeRuns-BN1rhyEm.js → useRuntimeRuns-CfGRbhr9.js} +1 -1
- package/client/dist/assets/useSharedWebSocket-C17TGqT8.js +2 -0
- package/client/dist/index.html +33 -32
- package/docs/README.md +1 -9
- package/docs/agent-live-steering.md +0 -6
- package/docs/agents/README.md +0 -2
- package/docs/agents/mcp.md +1 -14
- package/docs/cli.md +0 -13
- package/docs/codex.md +2 -75
- package/docs/creating-specs.md +0 -39
- package/docs/customizing.md +1 -15
- package/docs/getting-started.md +0 -23
- package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/de/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/de/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/de/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/de/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/de/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/de/integrations/1-ai-providers.md +2 -50
- package/docs/guide/de/integrations/2-plugins.md +0 -8
- package/docs/guide/de/integrations/5-mcp-server.md +1 -14
- package/docs/guide/de/integrations/6-agent-chat.md +0 -11
- package/docs/guide/de/integrations/7-local-engines.md +0 -4
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +0 -20
- package/docs/guide/de/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/de/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +0 -10
- package/docs/guide/en/agents/4-custom-agents-catalog.md +0 -25
- package/docs/guide/en/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/en/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/en/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/en/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/en/insights/3-code-explorer.md +0 -5
- package/docs/guide/en/integrations/1-ai-providers.md +10 -99
- package/docs/guide/en/integrations/2-plugins.md +0 -8
- package/docs/guide/en/integrations/5-mcp-server.md +1 -1
- package/docs/guide/en/integrations/6-agent-chat.md +0 -17
- package/docs/guide/en/integrations/7-local-engines.md +0 -4
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +2 -24
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +10 -65
- package/docs/guide/en/pipeline/5-the-loop-builder.md +0 -7
- package/docs/guide/en/specs/2-add-spec-quick-mode.md +0 -11
- package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/es/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/es/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/es/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/es/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/es/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/es/integrations/1-ai-providers.md +10 -75
- package/docs/guide/es/integrations/2-plugins.md +0 -8
- package/docs/guide/es/integrations/5-mcp-server.md +1 -1
- package/docs/guide/es/integrations/6-agent-chat.md +0 -11
- package/docs/guide/es/integrations/7-local-engines.md +0 -4
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +3 -13
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +10 -53
- package/docs/guide/es/pipeline/5-the-loop-builder.md +1 -6
- package/docs/guide/es/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/fr/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/fr/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/fr/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/fr/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/fr/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/fr/integrations/1-ai-providers.md +2 -50
- package/docs/guide/fr/integrations/2-plugins.md +0 -8
- package/docs/guide/fr/integrations/5-mcp-server.md +1 -14
- package/docs/guide/fr/integrations/6-agent-chat.md +0 -11
- package/docs/guide/fr/integrations/7-local-engines.md +0 -4
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +0 -22
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/fr/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/it/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/it/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/it/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/it/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/it/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/it/integrations/1-ai-providers.md +2 -48
- package/docs/guide/it/integrations/2-plugins.md +0 -8
- package/docs/guide/it/integrations/5-mcp-server.md +1 -14
- package/docs/guide/it/integrations/6-agent-chat.md +0 -11
- package/docs/guide/it/integrations/7-local-engines.md +0 -4
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +2 -13
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +0 -20
- package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -6
- package/docs/guide/it/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +0 -9
- package/docs/guide/ja/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/ja/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/ja/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/ja/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/ja/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/ja/integrations/1-ai-providers.md +1 -69
- package/docs/guide/ja/integrations/2-plugins.md +0 -8
- package/docs/guide/ja/integrations/5-mcp-server.md +1 -14
- package/docs/guide/ja/integrations/6-agent-chat.md +0 -10
- package/docs/guide/ja/integrations/7-local-engines.md +0 -4
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +0 -3
- package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +0 -21
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/ja/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +0 -8
- package/docs/guide/pt/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/pt/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/pt/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/pt/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/pt/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/pt/integrations/1-ai-providers.md +2 -48
- package/docs/guide/pt/integrations/2-plugins.md +0 -8
- package/docs/guide/pt/integrations/5-mcp-server.md +1 -14
- package/docs/guide/pt/integrations/6-agent-chat.md +0 -10
- package/docs/guide/pt/integrations/7-local-engines.md +0 -4
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +0 -2
- package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +0 -21
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/pt/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +0 -7
- package/docs/guide/zh/agents/4-custom-agents-catalog.md +0 -15
- package/docs/guide/zh/getting-started/1-what-is-specrails.md +0 -2
- package/docs/guide/zh/getting-started/2-installing-and-first-run.md +0 -2
- package/docs/guide/zh/getting-started/3-adding-your-first-project.md +0 -4
- package/docs/guide/zh/getting-started/4-the-dashboard-tour.md +0 -5
- package/docs/guide/zh/integrations/1-ai-providers.md +1 -67
- package/docs/guide/zh/integrations/2-plugins.md +0 -8
- package/docs/guide/zh/integrations/5-mcp-server.md +1 -14
- package/docs/guide/zh/integrations/6-agent-chat.md +0 -9
- package/docs/guide/zh/integrations/7-local-engines.md +0 -4
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +0 -13
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +0 -2
- package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +0 -20
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +0 -6
- package/docs/guide/zh/specs/2-add-spec-quick-mode.md +0 -7
- package/docs/internals/adding-a-provider.md +7 -0
- package/docs/internals/api-reference.md +1 -0
- package/docs/internals/core-runtime-updates.md +9 -2
- package/docs/internals/desktop-owned-workflows.md +144 -0
- package/docs/internals/mission-rail-cards.md +15 -0
- package/docs/internals/operations-runbook.md +26 -0
- package/docs/internals/programmatic-agent-runtime.md +34 -28
- package/docs/internals/project-builder.md +34 -11
- package/docs/internals/safe-pr-review-flow.md +25 -7
- package/docs/internals/source-map.md +53 -3
- package/docs/internals/spec-addenda.md +11 -5
- package/docs/internals/visual-design-audit.md +5 -0
- package/docs/local-providers.md +8 -13
- package/docs/mcp.md +1 -17
- package/docs/platforms/macos.md +0 -40
- package/docs/platforms/windows-parity.md +1 -1
- package/docs/platforms/windows.md +0 -8
- package/docs/running-pipelines.md +1 -46
- package/docs/subscription-usage.md +19 -0
- package/docs/terminal.md +0 -2
- package/docs/tracking-cost.md +2 -33
- package/package.json +1 -1
- package/server/dist/core-execution.js +24 -15
- package/server/dist/core-update-manager.js +1 -1
- package/server/dist/db/migrations.js +9 -0
- package/server/dist/desktop-db.js +23 -10
- package/server/dist/desktop-router.js +8 -4
- package/server/dist/index.js +10 -5
- package/server/dist/mcp/guide.js +1 -0
- package/server/dist/mcp/tools/jobs.js +1 -1
- package/server/dist/mcp/tools/loops.js +2 -0
- package/server/dist/mcp/tools/meta.js +6 -7
- package/server/dist/mcp/tools/projects.js +31 -6
- package/server/dist/mcp/tools/rails.js +6 -3
- package/server/dist/mcp/tools/setup.js +10 -0
- package/server/dist/mcp/tools/specs.js +1 -1
- package/server/dist/modules/accounting/runtime/pricing.js +6 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +169 -17
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +1 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +1 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +42 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js +10 -4
- package/server/dist/modules/builder/runtime/milestone-chain.js +76 -10
- package/server/dist/modules/delivery/runtime/delivery-evidence.js +3 -2
- package/server/dist/modules/delivery/runtime/multi-repo-execution.js +10 -5
- package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +66 -30
- package/server/dist/modules/delivery/runtime/rail-launch-parser.js +8 -0
- package/server/dist/modules/delivery/runtime/rail-pr-store.js +3 -3
- package/server/dist/modules/delivery/runtime/rail-relaunch.js +154 -0
- package/server/dist/modules/delivery/runtime/rails-router.js +157 -36
- package/server/dist/modules/delivery/runtime/review-packet.js +1 -1
- package/server/dist/modules/execution/runtime/revision-seed.js +6 -2
- package/server/dist/modules/loops/runtime/loop-agent-defaults.json +6 -0
- package/server/dist/modules/loops/runtime/loop-agents.js +21 -0
- package/server/dist/modules/loops/runtime/loop-command-catalog.js +1 -1
- package/server/dist/modules/loops/runtime/loop-core-factory.js +19 -3
- package/server/dist/modules/loops/runtime/loop-definition-events.js +1 -1
- package/server/dist/modules/loops/runtime/loop-definition.js +79 -12
- package/server/dist/modules/loops/runtime/loop-effect.js +1 -1
- package/server/dist/modules/loops/runtime/loop-executors.js +24 -9
- package/server/dist/modules/loops/runtime/loop-factory.js +1 -1
- package/server/dist/modules/loops/runtime/loop-graph.js +5 -14
- package/server/dist/modules/loops/runtime/loop-implement-recipe.js +53 -0
- package/server/dist/modules/loops/runtime/loop-run-manager.js +30 -20
- package/server/dist/modules/loops/runtime/loop-templates.js +29 -5
- package/server/dist/modules/loops/runtime/loops-router.js +17 -0
- package/server/dist/modules/missions/runtime/agent-context-resolver.js +1 -1
- package/server/dist/modules/missions/runtime/agent-operator-prompt.js +17 -8
- package/server/dist/modules/specs/runtime/spec-models.js +4 -7
- package/server/dist/modules/subscription-usage/adapters/claude.js +123 -0
- package/server/dist/modules/subscription-usage/adapters/codex.js +164 -0
- package/server/dist/modules/subscription-usage/adapters/errors.js +15 -0
- package/server/dist/modules/subscription-usage/adapters/http.js +20 -0
- package/server/dist/modules/subscription-usage/adapters/local-auth.js +61 -0
- package/server/dist/modules/subscription-usage/application.js +12 -0
- package/server/dist/modules/subscription-usage/domain.js +104 -0
- package/server/dist/modules/subscription-usage/index.js +2 -0
- package/server/dist/modules/subscription-usage/ports.js +2 -0
- package/server/dist/modules/subscription-usage/runtime/composition.js +20 -0
- package/server/dist/modules/subscription-usage/runtime/usage-service.js +111 -0
- package/server/dist/project-registry.js +16 -1
- package/server/dist/project-repositories.js +51 -2
- package/server/dist/project-router-helpers.js +1 -1
- package/server/dist/project-router-loop-runs.js +4 -1
- package/server/dist/providers/claude-adapter.js +6 -4
- package/server/dist/providers/codex-adapter.js +4 -5
- package/server/dist/schemas/workflow-definition.schema.json +2 -0
- package/server/dist/worktree-manager.js +114 -6
- package/server/dist/worktree-overlay.js +4 -4
- package/client/dist/assets/AgentBrowserCapture-PI-cxyxi.js +0 -1
- package/client/dist/assets/AgentModeAnalyticsPane-mQsOqdXx.js +0 -2
- package/client/dist/assets/AgentModeCodePane-BL-vpmlY.js +0 -2
- package/client/dist/assets/CodePage-Alitorrv.js +0 -3
- package/client/dist/assets/DocsDialog-DwL6rgcT.js +0 -11
- package/client/dist/assets/DocsPage-BA1hiJZ-.js +0 -11
- package/client/dist/assets/InteractiveJobComposer-B3H1YHr6.js +0 -19
- package/client/dist/assets/JobDetailModal-XZQ9eAAy.js +0 -1
- package/client/dist/assets/JobDetailPage-B-SIaq_q.js +0 -1
- package/client/dist/assets/JobsPage-iQXAv2mx.js +0 -1
- package/client/dist/assets/LoopBuilderPage-B_gbFAHn.js +0 -1
- package/client/dist/assets/LoopsPage-BZwcY5cu.js +0 -2
- package/client/dist/assets/MinimizedChatsContext-CNx_0bZu.js +0 -1
- package/client/dist/assets/PluginsPage-DFocnoHX.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-Bh3S6EBB.js +0 -1
- package/client/dist/assets/RepositoryScopeSelector-C2mvWBQ6.js +0 -1
- package/client/dist/assets/ReviewPacketPage-CrAf-WDy.js +0 -4
- package/client/dist/assets/TemplatePreviewModal-C7DordpN.js +0 -1
- package/client/dist/assets/TicketDetailModalContext-B-DySpKL.js +0 -16
- package/client/dist/assets/agent-BaG10AN6.js +0 -1
- package/client/dist/assets/agent-CH4aJ884.js +0 -1
- package/client/dist/assets/agent-CLc9fA7v.js +0 -1
- package/client/dist/assets/agent-DHh9-AdL.js +0 -1
- package/client/dist/assets/agent-DkKnd6Wv.js +0 -1
- package/client/dist/assets/agent-aiVhqFW1.js +0 -1
- package/client/dist/assets/agent-dbznD3eO.js +0 -1
- package/client/dist/assets/agent-sMVFcPwL.js +0 -1
- package/client/dist/assets/agentRuntime-BeUb3g9g.js +0 -1
- package/client/dist/assets/file-text-CFT-xXKN.js +0 -1
- package/client/dist/assets/index-BS7KCWkV.css +0 -2
- package/client/dist/assets/index-C4Mv6tV6.js +0 -80
- package/client/dist/assets/integrations-CH0zy1Mw.js +0 -1
- package/client/dist/assets/integrations-CIAjhd7L.js +0 -1
- package/client/dist/assets/integrations-CZdwOe8A.js +0 -1
- package/client/dist/assets/integrations-Ct7omMld.js +0 -1
- package/client/dist/assets/integrations-D6MSxy3-.js +0 -1
- package/client/dist/assets/integrations-DbZa-Zyc.js +0 -1
- package/client/dist/assets/integrations-b8pH-vfl.js +0 -1
- package/client/dist/assets/integrations-mB-7zoyT.js +0 -1
- package/client/dist/assets/jira-api-BYbEPlkr.js +0 -1
- package/client/dist/assets/layers-eDMjG41I.js +0 -1
- package/client/dist/assets/loops-B4_D-nbg.js +0 -1
- package/client/dist/assets/nav-B-tpjyc2.js +0 -1
- package/client/dist/assets/nav-BJNXGg29.js +0 -1
- package/client/dist/assets/nav-BdhtRLP7.js +0 -1
- package/client/dist/assets/nav-ByYgyN5T.js +0 -1
- package/client/dist/assets/nav-DA0Mva2c.js +0 -1
- package/client/dist/assets/nav-DcJm_Jg_.js +0 -1
- package/client/dist/assets/nav-DhMPtAXc.js +0 -1
- package/client/dist/assets/nav-DhPb-Isc.js +0 -1
- package/client/dist/assets/provider-capabilities-Vi1ZGvAK.js +0 -1
- package/client/dist/assets/save-B6wGWwBR.js +0 -1
- package/client/dist/assets/settings-3o4Ntzi5.js +0 -1
- package/client/dist/assets/settings-B97jlkwD.js +0 -1
- package/client/dist/assets/settings-BTaT_bsS.js +0 -1
- package/client/dist/assets/settings-CT8w7WiC.js +0 -1
- package/client/dist/assets/settings-Cvr8_tvh.js +0 -1
- package/client/dist/assets/settings-Dn1qgAC8.js +0 -1
- package/client/dist/assets/settings-EShDdg4J.js +0 -1
- package/client/dist/assets/settings-tfLhQZRN.js +0 -1
- package/client/dist/assets/setup-CBMu3tqH.js +0 -1
- package/client/dist/assets/setup-CPh-e6J2.js +0 -1
- package/client/dist/assets/setup-CRKLp_ke.js +0 -1
- package/client/dist/assets/setup-Cy302v4J.js +0 -1
- package/client/dist/assets/setup-D681vTPf.js +0 -1
- package/client/dist/assets/setup-DYK0VBkE.js +0 -1
- package/client/dist/assets/setup-KAuiIiVs.js +0 -1
- package/client/dist/assets/setup-OGX-oCfI.js +0 -1
- package/client/dist/assets/useSharedWebSocket-BZMrX4jr.js +0 -2
- package/client/dist/assets/wrench-BfmNO9Vw.js +0 -1
- package/docs/agy-cli-provider-study.md +0 -257
- package/docs/gemini-cli-provider-study.md +0 -301
- package/docs/gemini-core-support-evaluation.md +0 -160
- package/docs/gemini.md +0 -257
- package/docs/kimi.md +0 -291
|
@@ -163,21 +163,21 @@ function buildRevisionSeedForLaunch(db, revision, ticketIds, includeSpecBody = t
|
|
|
163
163
|
depth += 1;
|
|
164
164
|
cursor = (0, rail_pr_store_1.getPrDelivery)(db, cursor.revision_of) ?? undefined;
|
|
165
165
|
}
|
|
166
|
-
return (0, revision_seed_1.buildRevisionSeed)({
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
166
|
+
return { number: depth, briefing: (0, revision_seed_1.buildRevisionSeed)({
|
|
167
|
+
note: revision.note,
|
|
168
|
+
includeSpecBody,
|
|
169
|
+
specSnapshot: previous ? (0, rail_pr_store_1.readSpecSnapshot)(previous.spec_snapshot) : null,
|
|
170
|
+
ticketIds: [...ticketIds],
|
|
171
|
+
branches,
|
|
172
|
+
baseBranch: previous?.base_branch ?? 'the integration branch',
|
|
173
|
+
branchDiffSummary: null,
|
|
174
|
+
evidence: previous ? (0, delivery_evidence_1.readSettleEvidence)(previous.settle_evidence) : null,
|
|
175
|
+
revisionNumber: depth,
|
|
176
|
+
}) };
|
|
177
177
|
}
|
|
178
178
|
catch {
|
|
179
179
|
// Absolute floor: the user's instruction still reaches the run.
|
|
180
|
-
return revision.note;
|
|
180
|
+
return { briefing: revision.note, number: 1 };
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
/**
|
|
@@ -473,7 +473,7 @@ function createIsolatedRunSettlement(ports) {
|
|
|
473
473
|
}
|
|
474
474
|
let commit;
|
|
475
475
|
try {
|
|
476
|
-
commit = await (0, worktree_manager_1.commitWorktreeAndVerify)(git, a.handle.worktreePath, commitMessage(a, implementationOutcome === 'failed'), a.overlayExcludes);
|
|
476
|
+
commit = await (0, worktree_manager_1.commitWorktreeAndVerify)(git, a.handle.worktreePath, commitMessage(a, implementationOutcome === 'failed'), a.overlayExcludes, a.hygieneBaseSha ?? a.initialSha ?? a.baseRef);
|
|
477
477
|
}
|
|
478
478
|
catch (err) {
|
|
479
479
|
commit = { staged: false, committed: false, clean: false, dirty: [], error: errorDetail(err) };
|
|
@@ -638,10 +638,13 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
638
638
|
// provider session by contract, so durable context is the only thing it has.
|
|
639
639
|
// Per-RUN data, so it is layered over the project's constant map for this
|
|
640
640
|
// launch only and never persisted as a constant.
|
|
641
|
-
const
|
|
641
|
+
const revisionSeed = input.revision ? buildRevisionSeedForLaunch(ctx.db, input.revision, ticketIds, !['factory:sdd-quick-openspec', 'factory:openspec', 'factory:revision'].includes(loopId)) : undefined;
|
|
642
|
+
const constants = input.revision && revisionSeed
|
|
642
643
|
? {
|
|
643
644
|
...(0, loop_constants_1.loadConstantMap)(ctx.desktopDb),
|
|
644
|
-
REVISION_REQUEST:
|
|
645
|
+
REVISION_REQUEST: revisionSeed.briefing,
|
|
646
|
+
REVISION_NUMBER: String(revisionSeed.number),
|
|
647
|
+
REVISION_OF_DELIVERY_ID: input.revision.ofDeliveryId,
|
|
645
648
|
}
|
|
646
649
|
: (0, loop_constants_1.loadConstantMap)(ctx.desktopDb);
|
|
647
650
|
// Spec addenda (spec-addenda): the iteration notes the specs carry are
|
|
@@ -650,6 +653,7 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
650
653
|
// briefing every AI step of the run receives.
|
|
651
654
|
const addendaStorePath = (0, spec_addenda_1.ticketStorePathForProject)(ctx.project);
|
|
652
655
|
const addendaPlan = (0, spec_addenda_1.planSpecAddendaAt)(addendaStorePath, ticketIds);
|
|
656
|
+
const claimedAddendaByRun = new Map();
|
|
653
657
|
// Capture the PR-delivery mode ONCE at launch entry so a mid-flight env flip
|
|
654
658
|
// can never split one launch across the two delivery paths.
|
|
655
659
|
const prMode = Boolean(input.repositoryExecution) || (0, rail_isolation_1.isRailPrDeliveryEnabled)();
|
|
@@ -921,6 +925,7 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
921
925
|
}
|
|
922
926
|
if (prMode) {
|
|
923
927
|
const generation = (0, rail_pr_store_1.createPrDeliveryGeneration)(ctx.db, {
|
|
928
|
+
launchConfig: input.launchConfig,
|
|
924
929
|
parentDeliveryId: input.repositoryExecution?.parentDeliveryId,
|
|
925
930
|
repositoryId: input.repositoryExecution?.repositoryId,
|
|
926
931
|
repositoryPath: input.repositoryExecution ? baseRepo : undefined,
|
|
@@ -947,7 +952,9 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
947
952
|
// predecessor through the shipped rollback path.
|
|
948
953
|
: input.revision
|
|
949
954
|
? { id: input.revision.ofDeliveryId, decision: input.revision.decision }
|
|
950
|
-
:
|
|
955
|
+
: input.retryOfDelivery
|
|
956
|
+
? { id: input.retryOfDelivery.deliveryId, decision: input.retryOfDelivery.decision }
|
|
957
|
+
: null);
|
|
951
958
|
prDeliveryId = generation.delivery.id;
|
|
952
959
|
supersededDelivery = generation.superseded;
|
|
953
960
|
input.onPrDeliveryCreated?.(prDeliveryId);
|
|
@@ -983,15 +990,28 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
983
990
|
}
|
|
984
991
|
// Conventional branch naming (pr-naming): `<type>/<ref>-<kebab-title>`, the
|
|
985
992
|
// Jira key prevailing over the local id when linked. Collisions with foreign
|
|
986
|
-
// branches suffix `-2`… (bounded)
|
|
987
|
-
//
|
|
993
|
+
// branches suffix `-2`… (bounded). Ordinary launches start a new sibling;
|
|
994
|
+
// only exact recorded revision/PR branches can be reused.
|
|
988
995
|
// The integration branch is never used; exhaustion falls back to the legacy
|
|
989
996
|
// `sr/<slug>/ticket-<id>` name. Snapshot under the lock so concurrent
|
|
990
997
|
// launches see each other's just-created branches.
|
|
991
998
|
const takenBranches = await (0, worktree_manager_1.listLocalBranches)(git, baseRepo);
|
|
992
999
|
const preexistingBranches = new Set(takenBranches);
|
|
1000
|
+
const hygieneBase = await git.run(['rev-parse', '--verify', `${worktreeBaseRef.baseRef}^{commit}`], baseRepo);
|
|
1001
|
+
if (hygieneBase.code !== 0)
|
|
1002
|
+
throw new Error('Could not freeze the OpenSpec delivery baseline');
|
|
1003
|
+
const hygieneBaseSha = /^[a-f0-9]{40,64}$/i.test(hygieneBase.stdout.trim()) ? hygieneBase.stdout.trim() : null;
|
|
1004
|
+
const revisionBranches = input.repositoryExecution?.revisionBranches ?? new Map();
|
|
1005
|
+
if (input.revision && !input.repositoryExecution && !launchContinuation) {
|
|
1006
|
+
const previous = (0, rail_pr_store_1.getPrDelivery)(ctx.db, input.revision.ofDeliveryId);
|
|
1007
|
+
for (const unit of previous ? (0, rail_pr_store_1.toPrDeliverySnapshot)(previous).branches : []) {
|
|
1008
|
+
if (unit.succeeded && unit.finalSha && unit.implementationOutcome !== 'failed' && unit.deliveryOutcome !== 'blocked') {
|
|
1009
|
+
revisionBranches.set(unit.ticketId, { branch: unit.branch, sha: unit.finalSha });
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
993
1013
|
const unitBranchName = (ticketId) => {
|
|
994
|
-
const revisionBranch =
|
|
1014
|
+
const revisionBranch = revisionBranches.get(ticketId);
|
|
995
1015
|
if (revisionBranch)
|
|
996
1016
|
return { branch: revisionBranch.branch, ownership: 'preexisting' };
|
|
997
1017
|
const continuation = launchContinuation && continuationTargets.get(ticketId);
|
|
@@ -1001,10 +1021,10 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1001
1021
|
}
|
|
1002
1022
|
const preferred = (0, pr_naming_1.ticketBranchName)(unitNamingInput(ctx, ticketId));
|
|
1003
1023
|
const branch = (0, pr_naming_1.resolveCollisionFreeName)(preferred, {
|
|
1004
|
-
// A
|
|
1024
|
+
// A run can reuse a branch only through the exact revision/PR
|
|
1005
1025
|
// evidence above. An accepted predecessor may now lag the integration
|
|
1006
1026
|
// branch, so ordinary grouped allocations must start a fresh branch.
|
|
1007
|
-
taken: (name) => takenBranches.has(name)
|
|
1027
|
+
taken: (name) => takenBranches.has(name),
|
|
1008
1028
|
reserved: [integration.branch],
|
|
1009
1029
|
}) ?? (0, worktree_manager_1.worktreeBranch)(slug, ticketId);
|
|
1010
1030
|
takenBranches.add(branch);
|
|
@@ -1012,6 +1032,7 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1012
1032
|
};
|
|
1013
1033
|
try {
|
|
1014
1034
|
for (const unit of units) {
|
|
1035
|
+
const runId = input.repositoryExecution?.runIds.get(unit.ticketId) ?? (0, ids_1.newId)();
|
|
1015
1036
|
const continuationTarget = launchContinuation ? continuationTargets.get(unit.ticketId) ?? null : null;
|
|
1016
1037
|
const branchPlan = unitBranchName(unit.ticketId);
|
|
1017
1038
|
let handle = null;
|
|
@@ -1019,7 +1040,9 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1019
1040
|
let worktreeOwnership = 'created';
|
|
1020
1041
|
let initialSha = null;
|
|
1021
1042
|
try {
|
|
1022
|
-
const revisionBranch =
|
|
1043
|
+
const revisionBranch = revisionBranches.get(unit.ticketId);
|
|
1044
|
+
if (input.revision && !input.repositoryExecution && !launchContinuation && !revisionBranch)
|
|
1045
|
+
throw new Error('Revision requires a recorded delivered branch for every ticket');
|
|
1023
1046
|
if (revisionBranch) {
|
|
1024
1047
|
const observed = await git.run(['rev-parse', '--verify', `refs/heads/${revisionBranch.branch}`], baseRepo);
|
|
1025
1048
|
if (observed.code !== 0 || observed.stdout.trim() !== revisionBranch.sha) {
|
|
@@ -1028,12 +1051,14 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1028
1051
|
}
|
|
1029
1052
|
handle = await create(git, {
|
|
1030
1053
|
repoDir: baseRepo,
|
|
1031
|
-
worktreesRoot,
|
|
1054
|
+
worktreesRoot: path.join(worktreesRoot, runId),
|
|
1032
1055
|
slug,
|
|
1033
1056
|
ticketId: unit.ticketId,
|
|
1034
1057
|
baseRef: revisionBranch?.sha ?? continuationTarget?.baseRef ?? worktreeBaseRef.baseRef,
|
|
1035
1058
|
branch: branchPlan.branch,
|
|
1036
1059
|
refreshFromBaseRef: Boolean(continuationTarget?.baseRef),
|
|
1060
|
+
fresh: !revisionBranch && !continuationTarget,
|
|
1061
|
+
reuseBranchWorktree: Boolean(revisionBranch || continuationTarget),
|
|
1037
1062
|
});
|
|
1038
1063
|
worktreeOwnership = handle.worktreeCreated === false ? 'preexisting' : 'created';
|
|
1039
1064
|
if (!continuationTarget && (handle.branch !== branchPlan.branch || handle.branchCreated === false)) {
|
|
@@ -1106,7 +1131,6 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1106
1131
|
console.warn(`[rail-isolated] provenance snapshot failed: ${err.message}`);
|
|
1107
1132
|
}
|
|
1108
1133
|
}
|
|
1109
|
-
const runId = input.repositoryExecution?.runIds.get(unit.ticketId) ?? (0, ids_1.newId)();
|
|
1110
1134
|
const ledgerId = (0, ids_1.newId)();
|
|
1111
1135
|
(0, rail_worktrees_store_1.createRailWorktree)(ctx.db, {
|
|
1112
1136
|
id: ledgerId, railIndex, ticketId: unit.ticketId, runId,
|
|
@@ -1126,6 +1150,7 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1126
1150
|
provenanceSnapshot,
|
|
1127
1151
|
continuationTarget,
|
|
1128
1152
|
baseRef: continuationTarget?.baseRef ?? worktreeBaseRef.baseRef,
|
|
1153
|
+
hygieneBaseSha,
|
|
1129
1154
|
initialSha,
|
|
1130
1155
|
branchOwnership,
|
|
1131
1156
|
worktreeOwnership,
|
|
@@ -1158,9 +1183,23 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1158
1183
|
partialCommitMessage: worktreeCommitMessage(ctx, run.ticketId, run.runId, true), run,
|
|
1159
1184
|
});
|
|
1160
1185
|
})();
|
|
1186
|
+
// Freeze every addendum claim before any sibling can start Core. A missing
|
|
1187
|
+
// store or failed claim must never silently turn a delta into an unbriefed run.
|
|
1188
|
+
for (const run of allocated) {
|
|
1189
|
+
const plan = addendaPlan.filter(entry => run.ticketIds.includes(entry.ticketId)).map(entry => input.retryOfDelivery ? { ...entry, status: null } : launchContinuation || input.revision || input.repositoryContinuation ? { ...entry, status: 'on_review' } : entry);
|
|
1190
|
+
const claimed = (0, spec_addenda_1.claimSpecAddendaForRun)(addendaStorePath, run.ticketIds, run.runId, { plan });
|
|
1191
|
+
claimedAddendaByRun.set(run.runId, claimed);
|
|
1192
|
+
const expected = (0, spec_addenda_1.snapshotSpecAddenda)(plan);
|
|
1193
|
+
if (expected.some(entry => !claimed.snapshot.some(actual => actual.ticketId === entry.ticketId && actual.id === entry.id && actual.hash === entry.hash)) || (expected.length && !claimed.briefing)) {
|
|
1194
|
+
throw new Error('Could not claim the complete frozen spec addenda; no implementation was started. Restore ticket storage and retry.');
|
|
1195
|
+
}
|
|
1196
|
+
(0, spec_addenda_1.broadcastSpecAddendaChange)(msg => ctx.broadcast(msg), ctx.project.id, claimed);
|
|
1197
|
+
}
|
|
1161
1198
|
}
|
|
1162
1199
|
catch (err) {
|
|
1163
1200
|
for (const a of allocated) {
|
|
1201
|
+
if (claimedAddendaByRun.has(a.runId))
|
|
1202
|
+
(0, spec_addenda_1.broadcastSpecAddendaChange)(msg => ctx.broadcast(msg), ctx.project.id, (0, spec_addenda_1.settleSpecAddendaAt)(addendaStorePath, a.ticketIds, a.runId, 'failed'));
|
|
1164
1203
|
if (a.worktreeOwnership === 'created') {
|
|
1165
1204
|
await remove(git, {
|
|
1166
1205
|
repoDir: baseRepo,
|
|
@@ -1265,16 +1304,13 @@ async function launchIsolatedRail(input, io = {}) {
|
|
|
1265
1304
|
requiresTerminalIntent: true,
|
|
1266
1305
|
});
|
|
1267
1306
|
const spec = ctx.getTicketSpec(a.ticketId);
|
|
1268
|
-
const claimedAddenda =
|
|
1269
|
-
plan: addendaPlan.filter((e) => a.ticketIds.includes(e.ticketId)).map((entry) => launchContinuation || input.revision || input.repositoryContinuation
|
|
1270
|
-
? { ...entry, status: 'on_review' } : entry),
|
|
1271
|
-
});
|
|
1272
|
-
(0, spec_addenda_1.broadcastSpecAddendaChange)((msg) => ctx.broadcast(msg), ctx.project.id, claimedAddenda);
|
|
1307
|
+
const claimedAddenda = claimedAddendaByRun.get(a.runId);
|
|
1273
1308
|
const enginePromise = ctx.loopRunManager.run({
|
|
1274
1309
|
runtimeProviderOverride: input.runtimeProviderOverride,
|
|
1275
|
-
runId: a.runId, loopId, loopName, graph: loopGraph, projectId: ctx.project.id,
|
|
1310
|
+
runId: a.runId, loopId, loopName, graph: loopGraph, projectId: ctx.project.id, launchConfig: input.launchConfig,
|
|
1276
1311
|
cwd: a.handle.worktreePath, repoDir: a.handle.worktreePath,
|
|
1277
1312
|
repositoryId: singleRepositoryId,
|
|
1313
|
+
workspacePaths: singleRepositoryId ? input.workspaceSelection?.[singleRepositoryId] : undefined,
|
|
1278
1314
|
isolation: { branch: a.handle.branch, worktreePath: a.handle.worktreePath },
|
|
1279
1315
|
railIndex, ticketId: a.ticketIds.length ? a.ticketId : null,
|
|
1280
1316
|
spec: {
|
|
@@ -75,6 +75,12 @@ function coerceRailLaunchProposal(value) {
|
|
|
75
75
|
const mode = modeRaw === 'batch' || modeRaw === 'batch-implement' ? 'implement' : modeRaw;
|
|
76
76
|
if (!exports.RAIL_LAUNCH_MODES.includes(mode))
|
|
77
77
|
return { ok: false, reason: 'invalid_mode' };
|
|
78
|
+
const repositoryIds = value.repositoryIds;
|
|
79
|
+
const workspaceSelection = value.workspaceSelection;
|
|
80
|
+
if (repositoryIds !== undefined && (!Array.isArray(repositoryIds) || !repositoryIds.length || repositoryIds.length > 50 || repositoryIds.some(id => typeof id !== 'string' || !id.trim()) || new Set(repositoryIds).size !== repositoryIds.length))
|
|
81
|
+
return { ok: false, reason: 'invalid_workspace_selection' };
|
|
82
|
+
if (workspaceSelection !== undefined && (!isRecord(workspaceSelection) || !Object.keys(workspaceSelection).length || Object.keys(workspaceSelection).length > 50 || Object.entries(workspaceSelection).some(([id, paths]) => !id.trim() || !Array.isArray(paths) || !paths.length || paths.length > 50 || paths.some(item => typeof item !== 'string' || !item.trim() || item.length > 4096) || new Set(paths).size !== paths.length)))
|
|
83
|
+
return { ok: false, reason: 'invalid_workspace_selection' };
|
|
78
84
|
const newRailRaw = value.newRail;
|
|
79
85
|
const newRail = newRailRaw === true
|
|
80
86
|
? { name: null }
|
|
@@ -89,6 +95,8 @@ function coerceRailLaunchProposal(value) {
|
|
|
89
95
|
railIndex,
|
|
90
96
|
newRail,
|
|
91
97
|
ticketIds,
|
|
98
|
+
...(repositoryIds !== undefined ? { repositoryIds: repositoryIds } : {}),
|
|
99
|
+
...(workspaceSelection !== undefined ? { workspaceSelection: workspaceSelection } : {}),
|
|
92
100
|
mode: mode,
|
|
93
101
|
loopId: optString(value.loopId, 120),
|
|
94
102
|
aiEngine: optString(value.aiEngine ?? value.provider ?? value.engine, 80),
|
|
@@ -101,11 +101,11 @@ function createPrDelivery(db, input) {
|
|
|
101
101
|
loop_name, origin_surface, origin_conversation_id,
|
|
102
102
|
implementation_outcome, delivery_outcome, status_code,
|
|
103
103
|
is_continuation, supersedes_delivery_id, spec_snapshot,
|
|
104
|
-
revision_note, revision_of, parent_delivery_id, repository_id, repository_path, follow_up, spec_addenda
|
|
104
|
+
revision_note, revision_of, parent_delivery_id, repository_id, repository_path, follow_up, spec_addenda, launch_config_json
|
|
105
105
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'running', 'pending',
|
|
106
|
-
'implementation_running', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.railIndex, input.loopId ?? null, input.railKey, JSON.stringify(input.ticketIds), input.baseBranch, input.loopName, input.originSurface, input.originConversationId ?? null, input.isContinuation ? 1 : 0, input.supersedesDeliveryId ?? null, input.specSnapshot && input.specSnapshot.length > 0
|
|
106
|
+
'implementation_running', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, input.railIndex, input.loopId ?? null, input.railKey, JSON.stringify(input.ticketIds), input.baseBranch, input.loopName, input.originSurface, input.originConversationId ?? null, input.isContinuation ? 1 : 0, input.supersedesDeliveryId ?? null, input.specSnapshot && input.specSnapshot.length > 0
|
|
107
107
|
? JSON.stringify(boundSpecSnapshot(input.specSnapshot))
|
|
108
|
-
: null, input.revisionNote ? boundRevisionNote(input.revisionNote) : null, input.revisionOf ?? null, input.parentDeliveryId ?? null, input.repositoryId ?? null, input.repositoryPath ?? null, input.followUp ? JSON.stringify(input.followUp) : null, input.specAddenda && input.specAddenda.length > 0 ? JSON.stringify(input.specAddenda) : null);
|
|
108
|
+
: null, input.revisionNote ? boundRevisionNote(input.revisionNote) : null, input.revisionOf ?? null, input.parentDeliveryId ?? null, input.repositoryId ?? null, input.repositoryPath ?? null, input.followUp ? JSON.stringify(input.followUp) : null, input.specAddenda && input.specAddenda.length > 0 ? JSON.stringify(input.specAddenda) : null, input.launchConfig ? JSON.stringify(input.launchConfig) : null);
|
|
109
109
|
return getPrDelivery(db, id);
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RailRelaunchError = void 0;
|
|
4
|
+
exports.resolveRailRelaunch = resolveRailRelaunch;
|
|
5
|
+
exports.assertRelaunchRail = assertRelaunchRail;
|
|
6
|
+
exports.restoreRelaunchRail = restoreRelaunchRail;
|
|
7
|
+
const loop_runs_store_1 = require("../../loops/runtime/loop-runs-store");
|
|
8
|
+
const rail_pr_store_1 = require("./rail-pr-store");
|
|
9
|
+
const rails_store_1 = require("./rails-store");
|
|
10
|
+
class RailRelaunchError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
action;
|
|
13
|
+
constructor(code, detail, action) {
|
|
14
|
+
super(detail);
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.action = action;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.RailRelaunchError = RailRelaunchError;
|
|
20
|
+
function jsonObject(raw) {
|
|
21
|
+
if (!raw)
|
|
22
|
+
return undefined;
|
|
23
|
+
const value = JSON.parse(raw);
|
|
24
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
25
|
+
throw new Error('Invalid saved launch configuration');
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function historicalConfig(run) {
|
|
29
|
+
if (!run)
|
|
30
|
+
return {};
|
|
31
|
+
const request = jsonObject(run.run_request_json);
|
|
32
|
+
return {
|
|
33
|
+
mode: 'loop',
|
|
34
|
+
...(run.loop_id ? { loopId: run.loop_id } : {}),
|
|
35
|
+
...(run.provider ? { aiEngine: run.provider } : {}),
|
|
36
|
+
...(run.model ? { model: run.model } : {}),
|
|
37
|
+
...(run.reasoning_effort ? { reasoning_effort: run.reasoning_effort } : {}),
|
|
38
|
+
// These are launch options, not the old cwd, worktree, graph or run id.
|
|
39
|
+
...(request?.profileName !== undefined ? { profileName: request.profileName } : {}),
|
|
40
|
+
...(request?.runtimeProviderOverride ? { runtimeProviderOverride: request.runtimeProviderOverride } : {}),
|
|
41
|
+
...(request?.repositoryId ? { repositoryIds: [request.repositoryId] } : {}),
|
|
42
|
+
...(request?.repositoryId && request.workspacePaths ? { workspaceSelection: { [String(request.repositoryId)]: request.workspacePaths } } : {}),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function unavailable(code, detail) {
|
|
46
|
+
throw new RailRelaunchError(code, detail, 'Refresh the mission and configure a fresh launch on a free rail.');
|
|
47
|
+
}
|
|
48
|
+
/** Per-ticket launches share a rail but settle independently. A later sibling
|
|
49
|
+
* is not a replacement; only a run covering one of this source's specs is. */
|
|
50
|
+
function latestOverlappingRun(c, railIndex, ticketIds) {
|
|
51
|
+
const ids = JSON.stringify(ticketIds);
|
|
52
|
+
return c.db.prepare(`SELECT id, status FROM loop_runs
|
|
53
|
+
WHERE rail_index = ? AND (ticket_id IN (SELECT value FROM json_each(?))
|
|
54
|
+
OR EXISTS (SELECT 1 FROM json_each(COALESCE(ticket_ids_json, '[]')) AS ticket
|
|
55
|
+
WHERE ticket.value IN (SELECT value FROM json_each(?))))
|
|
56
|
+
ORDER BY rowid DESC LIMIT 1`).get(railIndex, ids, ids);
|
|
57
|
+
}
|
|
58
|
+
/** Resolve the source in this project's database. A card never authorizes the
|
|
59
|
+
* current contents of its mutable rail slot, or arbitrary launch overrides. */
|
|
60
|
+
function resolveRailRelaunch(c, railIndex, sourceId) {
|
|
61
|
+
if (typeof sourceId !== 'string' || !/^(?:run:)?[A-Za-z0-9-]{1,128}$/.test(sourceId)) {
|
|
62
|
+
unavailable('invalid_relaunch_source', 'Relaunch requires the original delivery or run id.');
|
|
63
|
+
}
|
|
64
|
+
let ticketIds, config, delivery;
|
|
65
|
+
if (sourceId.startsWith('run:')) {
|
|
66
|
+
const run = (0, loop_runs_store_1.getLoopRun)(c.db, sourceId.slice(4));
|
|
67
|
+
if (!run || run.project_id !== c.project.id || run.rail_index !== railIndex)
|
|
68
|
+
unavailable('relaunch_source_missing', 'The original run is unavailable in this project and rail.');
|
|
69
|
+
if (run.status !== 'completed')
|
|
70
|
+
unavailable('relaunch_source_active', 'The original run is still active or paused.');
|
|
71
|
+
ticketIds = JSON.parse(run.ticket_ids_json ?? '[]');
|
|
72
|
+
if (!ticketIds.length && run.ticket_id != null)
|
|
73
|
+
ticketIds = [run.ticket_id];
|
|
74
|
+
config = jsonObject(run.launch_config_json) ?? historicalConfig(run);
|
|
75
|
+
const newer = latestOverlappingRun(c, railIndex, ticketIds);
|
|
76
|
+
if (newer?.id !== run.id || (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex))
|
|
77
|
+
unavailable('relaunch_source_stale', 'Another attempt has already replaced this run on the rail.');
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const row = (0, rail_pr_store_1.getPrDelivery)(c.db, sourceId);
|
|
81
|
+
if (!row || row.rail_index !== railIndex || row.parent_delivery_id)
|
|
82
|
+
unavailable('relaunch_source_missing', 'The original delivery is unavailable in this project and rail.');
|
|
83
|
+
delivery = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
|
|
84
|
+
if (!['implementation_failed', 'pr_failed'].includes(row.decision) && !(row.decision === 'discarded' && ['delivery_failed', 'cancelled'].includes(row.status_code ?? ''))) {
|
|
85
|
+
unavailable('relaunch_source_stale', 'The original delivery is no longer a failed attempt awaiting relaunch.');
|
|
86
|
+
}
|
|
87
|
+
if (row.operation_token)
|
|
88
|
+
unavailable('relaunch_source_busy', 'A delivery operation is still in progress.');
|
|
89
|
+
const active = (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex);
|
|
90
|
+
const latest = c.db.prepare('SELECT id FROM rail_pr_deliveries WHERE rail_index = ? AND parent_delivery_id IS NULL ORDER BY rowid DESC LIMIT 1').get(railIndex);
|
|
91
|
+
if (active ? active.id !== sourceId : latest?.id !== sourceId)
|
|
92
|
+
unavailable('relaunch_source_stale', 'Another delivery has already replaced this attempt on the rail.');
|
|
93
|
+
ticketIds = delivery.ticketIds;
|
|
94
|
+
const run = delivery.runIds.map(id => (0, loop_runs_store_1.getLoopRun)(c.db, id)).find(Boolean);
|
|
95
|
+
const savedConfig = jsonObject(row.launch_config_json);
|
|
96
|
+
config = savedConfig ?? {
|
|
97
|
+
mode: 'loop',
|
|
98
|
+
...historicalConfig(run),
|
|
99
|
+
...(row.loop_id ? { loopId: row.loop_id } : {}),
|
|
100
|
+
...(delivery.followUp ? { targetPrNumber: delivery.prNumber, followUp: delivery.followUp } : {}),
|
|
101
|
+
};
|
|
102
|
+
// Always retain the admitted base; ordinary launch defaults may have changed.
|
|
103
|
+
if (!config.baseBranch && row.base_branch)
|
|
104
|
+
config.baseBranch = row.base_branch;
|
|
105
|
+
if (delivery.executionManifest) {
|
|
106
|
+
config.repositoryIds = delivery.executionManifest.selectedRepositoryIds;
|
|
107
|
+
config.workspaceSelection = savedConfig?.workspaceSelection ?? Object.fromEntries(delivery.executionManifest.repositories
|
|
108
|
+
.filter(repo => repo.selectedWorkspacePaths).map(repo => [repo.repositoryId, repo.selectedWorkspacePaths]));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (!Array.isArray(ticketIds) || !ticketIds.length || ticketIds.some(id => !Number.isSafeInteger(id) || id <= 0))
|
|
112
|
+
unavailable('relaunch_specs_unavailable', 'The original spec set is unavailable.');
|
|
113
|
+
if (typeof config.loopId !== 'string' || !config.loopId)
|
|
114
|
+
unavailable('relaunch_config_unavailable', 'The original workflow was not recorded; Relaunch cannot safely choose a replacement.');
|
|
115
|
+
// Revision identity belongs to the old generation. Retry uses the original
|
|
116
|
+
// complete spec set and the separate atomic retryOfDelivery contract.
|
|
117
|
+
const { revisionOfDeliveryId: _revisionId, revisionNote: _revisionNote, ...retryConfig } = config;
|
|
118
|
+
const source = { sourceId, ticketIds, config: retryConfig, delivery };
|
|
119
|
+
assertRelaunchRail(c, railIndex, source);
|
|
120
|
+
return source;
|
|
121
|
+
}
|
|
122
|
+
function assertRelaunchRail(c, railIndex, source) {
|
|
123
|
+
if (!(0, rails_store_1.railExists)(c.db, railIndex))
|
|
124
|
+
unavailable('relaunch_rail_missing', 'The original rail was removed.');
|
|
125
|
+
const rail = (0, rails_store_1.getRail)(c.db, railIndex);
|
|
126
|
+
if (rail.ticketIds.length && (rail.ticketIds.length !== source.ticketIds.length || rail.ticketIds.some(id => !source.ticketIds.includes(id)))) {
|
|
127
|
+
unavailable('relaunch_rail_changed', 'This rail now contains different specs. Relaunch has not changed or launched them.');
|
|
128
|
+
}
|
|
129
|
+
if (source.delivery) {
|
|
130
|
+
const current = (0, rail_pr_store_1.getPrDelivery)(c.db, source.sourceId);
|
|
131
|
+
const active = (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex);
|
|
132
|
+
const latest = c.db.prepare('SELECT id FROM rail_pr_deliveries WHERE rail_index = ? AND parent_delivery_id IS NULL ORDER BY rowid DESC LIMIT 1').get(railIndex);
|
|
133
|
+
if (!current || current.decision !== source.delivery.decision || current.operation_token || (active ? active.id !== current.id : latest?.id !== current.id)) {
|
|
134
|
+
unavailable('relaunch_source_stale', 'The original delivery changed while Relaunch was being prepared.');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const latest = latestOverlappingRun(c, railIndex, source.ticketIds);
|
|
139
|
+
if (latest?.id !== source.sourceId.slice(4) || latest.status !== 'completed' || (0, rail_pr_store_1.getActivePrDeliveryByRail)(c.db, railIndex)) {
|
|
140
|
+
unavailable('relaunch_source_stale', 'The original run changed while Relaunch was being prepared.');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return rail;
|
|
144
|
+
}
|
|
145
|
+
/** Called after preflight, immediately before admission. Empty assignment is
|
|
146
|
+
* terminal cleanup; a different assignment remains the user's current work. */
|
|
147
|
+
function restoreRelaunchRail(c, railIndex, source) {
|
|
148
|
+
const rail = assertRelaunchRail(c, railIndex, source);
|
|
149
|
+
if (!rail.ticketIds.length) {
|
|
150
|
+
(0, rails_store_1.setRailTickets)(c.db, railIndex, source.ticketIds, String(source.config.mode ?? 'implement'), typeof source.config.profileName === 'string' ? source.config.profileName : null, typeof source.config.aiEngine === 'string' ? source.config.aiEngine : null);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|