specrails-desktop 2.20.1 → 2.22.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 +3 -2
- package/client/dist/assets/{ActivityFeedPage-3WSqRYVx.js → ActivityFeedPage-roDyKGuv.js} +1 -1
- package/client/dist/assets/AgentBrowserCapture-BsXnWa4j.js +1 -0
- package/client/dist/assets/{AgentModeCodePane-Cnsea6eZ.js → AgentModeCodePane-o97EJvbJ.js} +2 -2
- package/client/dist/assets/AgentModeJobsPane-CLtpPxPM.js +1 -0
- package/client/dist/assets/AgentsPage-eNSo_ZcC.js +86 -0
- package/client/dist/assets/AnalyticsPage-cAJ60_Ex.js +1 -0
- package/client/dist/assets/{BarChart-C6If656N.js → BarChart-NLtK7xAY.js} +1 -1
- package/client/dist/assets/CodePage-B5rum8ZB.js +2 -0
- package/client/dist/assets/DesktopAnalyticsPage-DSuvG6Tq.js +1 -0
- package/client/dist/assets/DocsDialog-Bo38G3Yc.js +11 -0
- package/client/dist/assets/DocsPage-BNkiBBrC.js +11 -0
- package/client/dist/assets/{ExportDropdown-CezTK0EX.js → ExportDropdown-DCV8PN4-.js} +1 -1
- package/client/dist/assets/IntegrationsPage-BMJOzpPz.js +3 -0
- package/client/dist/assets/InteractiveJobComposer-aLduNs5R.js +19 -0
- package/client/dist/assets/JobDetailModal-kpkUWJIS.js +1 -0
- package/client/dist/assets/JobDetailPage-CFeqlrPU.js +1 -0
- package/client/dist/assets/JobsPage-fuwhXy2I.js +1 -0
- package/client/dist/assets/LoopBuilderPage-DP66322C.js +7 -0
- package/client/dist/assets/LoopPreviewModal-CpmBhE31.js +1 -0
- package/client/dist/assets/LoopsPage-CvQ18VUx.js +1 -0
- package/client/dist/assets/ProjectSettingsDialog-Deq4pwvq.js +1 -0
- package/client/dist/assets/TemplatePreviewModal-DziOj2Ct.js +1 -0
- package/client/dist/assets/agent-Csh4kP2S.js +1 -0
- package/client/dist/assets/agent-Cz_jgQX32.js +1 -0
- package/client/dist/assets/agent-D3vcIvaz2.js +1 -0
- package/client/dist/assets/agent-Dnbt0V4e.js +1 -0
- package/client/dist/assets/agent-HolR7QrZ.js +1 -0
- package/client/dist/assets/agent-Ka0rRWJy.js +1 -0
- package/client/dist/assets/agent-Te3yysMd.js +1 -0
- package/client/dist/assets/agent-vM4_iLDk2.js +1 -0
- package/client/dist/assets/{upload-CRtTj4Co.js → brain-kFJuEDNH.js} +1 -1
- package/client/dist/assets/{browser-DEEO-OSi.js → browser-BPkhILSJ.js} +1 -1
- package/client/dist/assets/{browser-BTivfZKE2.js → browser-BijVYG0Y2.js} +1 -1
- package/client/dist/assets/{browser-bpO3onlS.js → browser-BqLqJVVT.js} +1 -1
- package/client/dist/assets/{browser-DlSXtfu5.js → browser-Cc0iDqUi.js} +1 -1
- package/client/dist/assets/browser-CdS6O1Qb.js +1 -0
- package/client/dist/assets/{browser-BKP6hqQC2.js → browser-Cvg-QHvd2.js} +1 -1
- package/client/dist/assets/{browser-INCUyduh.js → browser-FRv8P02E.js} +1 -1
- package/client/dist/assets/{browser-DlKLfT612.js → browser-rWKj-RR_2.js} +1 -1
- package/client/dist/assets/code-BRcDlze52.js +1 -0
- package/client/dist/assets/code-BdMy3Ffq.js +1 -0
- package/client/dist/assets/code-CeQ0FZpC.js +1 -0
- package/client/dist/assets/code-CqCcRThR.js +1 -0
- package/client/dist/assets/code-DgeHz9CB.js +1 -0
- package/client/dist/assets/code-DzC1rMk12.js +1 -0
- package/client/dist/assets/code-UPVvmAKM2.js +1 -0
- package/client/dist/assets/code-thSEptMx.js +1 -0
- package/client/dist/assets/{common-QjVnq9XP2.js → common-BM3LFLCE2.js} +1 -1
- package/client/dist/assets/{common-CeQUwuHt2.js → common-Bwafujnc2.js} +1 -1
- package/client/dist/assets/{common-Bb64s3Bm.js → common-C-vU-j-I.js} +1 -1
- package/client/dist/assets/{common-KbQuTSGg.js → common-C5HKSbbz.js} +1 -1
- package/client/dist/assets/{common-BPQQkgJZ.js → common-CYaT2yHp.js} +1 -1
- package/client/dist/assets/{common-DPxotRK9.js → common-DhWTkocg.js} +1 -1
- package/client/dist/assets/{common-k5MTOHpn.js → common-DiPTT7V_2.js} +1 -1
- package/client/dist/assets/{common-C8ZD5upH2.js → common-DmqBPwZG.js} +1 -1
- package/client/dist/assets/{cssMode-DsArsSCT.js → cssMode-DBHbkBvI.js} +1 -1
- package/client/dist/assets/dashboard-BaStj_a_.js +1 -0
- package/client/dist/assets/dashboard-Bi6ugu5Q.js +1 -0
- package/client/dist/assets/dashboard-BmqTn3L02.js +1 -0
- package/client/dist/assets/dashboard-CvT8lOCT.js +1 -0
- package/client/dist/assets/dashboard-D7Pmeavq2.js +1 -0
- package/client/dist/assets/dashboard-DAnWdAac2.js +1 -0
- package/client/dist/assets/dashboard-JnYy2WLg.js +1 -0
- package/client/dist/assets/dashboard-L47YsFS_.js +1 -0
- package/client/dist/assets/{dist-js-BQn4yxaw.js → dist-js-BZSiJDbG.js} +1 -1
- package/client/dist/assets/{dist-js-BAWSqVtr.js → dist-js-DKpmIJlQ.js} +1 -1
- package/client/dist/assets/{editor.main-G3Sl9C67.js → editor.main-C9J2ikJK.js} +2 -2
- package/client/dist/assets/{freemarker2-pBzQNgFi.js → freemarker2-J5iIIIK-.js} +1 -1
- package/client/dist/assets/{handlebars-CtBTCnBI.js → handlebars-DSw1l_tw.js} +1 -1
- package/client/dist/assets/{html-Dx3DYBzY.js → html-h2-wE1Lj.js} +1 -1
- package/client/dist/assets/{htmlMode-In7frFOo.js → htmlMode-Cc_ij7lW.js} +1 -1
- package/client/dist/assets/index-DM6heiGa.js +155 -0
- package/client/dist/assets/index-DPX6_xIC.css +2 -0
- package/client/dist/assets/{javascript-BKcn-YkN.js → javascript-C1q3xv6N.js} +1 -1
- package/client/dist/assets/jira-B3613-gj.js +1 -0
- package/client/dist/assets/jira-BHAKtc4B.js +1 -0
- package/client/dist/assets/jira-Be369RIR2.js +1 -0
- package/client/dist/assets/jira-CPpgA-5z2.js +1 -0
- package/client/dist/assets/jira-D5efgwp_.js +1 -0
- package/client/dist/assets/jira-DS7ownDy.js +1 -0
- package/client/dist/assets/jira-bDs7Im2C.js +1 -0
- package/client/dist/assets/jira-uNH1gETL2.js +1 -0
- package/client/dist/assets/jobs-1GV2-4zd2.js +1 -0
- package/client/dist/assets/jobs-26F9gGcE.js +1 -0
- package/client/dist/assets/jobs-BgQzB0Sx2.js +1 -0
- package/client/dist/assets/jobs-BqWui9_f.js +1 -0
- package/client/dist/assets/jobs-CE8qeIYj.js +1 -0
- package/client/dist/assets/jobs-D5sZzgLs.js +1 -0
- package/client/dist/assets/jobs-DzeuASRf.js +1 -0
- package/client/dist/assets/jobs-Wh7dn28q2.js +1 -0
- package/client/dist/assets/{jsonMode-jNREoQ3C.js → jsonMode-CeaCdEhr.js} +1 -1
- package/client/dist/assets/{lib-C-g8QbZl.js → lib-B2nCKzmA.js} +1 -1
- package/client/dist/assets/{liquid-CtRkGqBu.js → liquid-eFsVK0V-.js} +1 -1
- package/client/dist/assets/loops-BvEenWBy.js +1 -0
- package/client/dist/assets/loops-CBiWd9Hf.js +1 -0
- package/client/dist/assets/loops-DNGiYKll2.js +1 -0
- package/client/dist/assets/{loops-Y3FQsUCh.js → loops-DjOtVXRo.js} +1 -1
- package/client/dist/assets/loops-HTHf-xu32.js +1 -0
- package/client/dist/assets/loops-YYV2bwjd.js +1 -0
- package/client/dist/assets/loops-hXgncEpF2.js +1 -0
- package/client/dist/assets/loops-kYbydDyN.js +1 -0
- package/client/dist/assets/{lspLanguageFeatures-Cl3gvD_W.js → lspLanguageFeatures-DT3-bbhn.js} +1 -1
- package/client/dist/assets/{mdx-B_nJldHz.js → mdx-Fuwnh1cX.js} +1 -1
- package/client/dist/assets/{monaco.contribution-PUeaZk8T.js → monaco.contribution-Desq7oq4.js} +2 -2
- package/client/dist/assets/{python-DS1Ce-A6.js → python-BgoEs6Cj.js} +1 -1
- package/client/dist/assets/{razor-L41Qg9OK.js → razor-CM1sPMMq.js} +1 -1
- package/client/dist/assets/{settings-BPq9nCJm.js → settings-BOHOmHkb.js} +1 -1
- package/client/dist/assets/{settings-r8Qq2Gzp2.js → settings-BlEA_7h02.js} +1 -1
- package/client/dist/assets/{settings-C-m3yEZ2.js → settings-BsJMsWGc.js} +1 -1
- package/client/dist/assets/{settings-zZr7NzuB.js → settings-D6qY9_UI.js} +1 -1
- package/client/dist/assets/{settings-VgCsjaYf.js → settings-DZJeXoRV.js} +1 -1
- package/client/dist/assets/settings-Mr7MnJbf.js +1 -0
- package/client/dist/assets/{settings-BWHGtmU12.js → settings-TNga5gIF2.js} +1 -1
- package/client/dist/assets/{settings-DZj7Uqy32.js → settings-lFoaYT-s2.js} +1 -1
- package/client/dist/assets/setup-B590KsTX.js +1 -0
- package/client/dist/assets/setup-BkyGoby6.js +1 -0
- package/client/dist/assets/setup-CEj6uY3-2.js +1 -0
- package/client/dist/assets/setup-CbIerFGf2.js +1 -0
- package/client/dist/assets/setup-CmU6bTCV2.js +1 -0
- package/client/dist/assets/setup-D674kWQH.js +1 -0
- package/client/dist/assets/setup-VNqXyB6Y.js +1 -0
- package/client/dist/assets/setup-iY8vH8pB.js +1 -0
- package/client/dist/assets/specs-C9Sd7BhH2.js +1 -0
- package/client/dist/assets/specs-CBDvEYKv.js +1 -0
- package/client/dist/assets/specs-CIPr9reA2.js +1 -0
- package/client/dist/assets/specs-CWtKcVDC.js +1 -0
- package/client/dist/assets/specs-CmEZY57v.js +1 -0
- package/client/dist/assets/specs-D2clrt2c2.js +1 -0
- package/client/dist/assets/specs-DTplt2XM.js +1 -0
- package/client/dist/assets/specs-PozUNhqb.js +1 -0
- package/client/dist/assets/{tsMode-BC1g186U.js → tsMode-BmT8WogI.js} +1 -1
- package/client/dist/assets/{typescript-BGlRGvJW.js → typescript-CQrQPsoW.js} +1 -1
- package/client/dist/assets/upload-CLAzW1mS.js +1 -0
- package/client/dist/assets/{value-D9aLbxw-.js → value-DSwzyyWR.js} +1 -1
- package/client/dist/assets/{workers-CXcXtO3b.js → workers-U0UXyLUf.js} +1 -1
- package/client/dist/assets/{xml-JdZZaIhJ.js → xml-WRxJs8_I.js} +1 -1
- package/client/dist/assets/{yaml-Cm82BVBt.js → yaml-CjpSTjJU.js} +1 -1
- package/client/dist/index.html +14 -14
- package/docs/customizing.md +2 -2
- package/docs/gemini.md +15 -4
- package/docs/guide/de/insights/3-code-explorer.md +6 -0
- package/docs/guide/de/integrations/3-jira-integration.md +1 -1
- package/docs/guide/de/integrations/6-agent-chat.md +5 -0
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +9 -5
- package/docs/guide/de/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/de/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/guide/en/insights/3-code-explorer.md +6 -0
- package/docs/guide/en/integrations/3-jira-integration.md +1 -1
- package/docs/guide/en/integrations/6-agent-chat.md +5 -0
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +10 -4
- package/docs/guide/en/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/en/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/guide/es/insights/3-code-explorer.md +6 -0
- package/docs/guide/es/integrations/3-jira-integration.md +1 -1
- package/docs/guide/es/integrations/6-agent-chat.md +5 -0
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +9 -5
- package/docs/guide/es/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/es/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/guide/fr/insights/3-code-explorer.md +6 -0
- package/docs/guide/fr/integrations/3-jira-integration.md +1 -1
- package/docs/guide/fr/integrations/6-agent-chat.md +5 -0
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +9 -5
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/fr/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/guide/it/insights/3-code-explorer.md +6 -0
- package/docs/guide/it/integrations/3-jira-integration.md +1 -1
- package/docs/guide/it/integrations/6-agent-chat.md +5 -0
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +10 -6
- package/docs/guide/it/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/it/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/guide/ja/insights/3-code-explorer.md +6 -0
- package/docs/guide/ja/integrations/3-jira-integration.md +1 -1
- package/docs/guide/ja/integrations/6-agent-chat.md +5 -0
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +9 -5
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/ja/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/guide/pt/insights/3-code-explorer.md +6 -0
- package/docs/guide/pt/integrations/3-jira-integration.md +1 -1
- package/docs/guide/pt/integrations/6-agent-chat.md +5 -0
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +9 -5
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/pt/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/guide/zh/insights/3-code-explorer.md +6 -0
- package/docs/guide/zh/integrations/3-jira-integration.md +1 -1
- package/docs/guide/zh/integrations/6-agent-chat.md +5 -0
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +6 -6
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +27 -2
- package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +10 -6
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +1 -1
- package/docs/guide/zh/specs/1-specs-and-the-backlog.md +3 -2
- package/docs/internals/README.md +5 -0
- package/docs/internals/adding-a-provider.md +15 -3
- package/docs/internals/api-reference.md +6 -5
- package/docs/internals/browser-capture-performance.md +93 -0
- package/docs/internals/code-explorer-story.md +135 -0
- package/docs/internals/gemini-mcp-registration.md +53 -0
- package/docs/internals/interactive-jobs.md +212 -0
- package/docs/internals/loop-step-log-explorer.md +146 -0
- package/docs/internals/safe-pr-review-flow.md +367 -0
- package/docs/mcp.md +1 -1
- package/docs/running-pipelines.md +6 -2
- package/package.json +1 -1
- package/server/dist/agent-chat-manager.js +211 -0
- package/server/dist/agent-chat-registry.js +20 -0
- package/server/dist/agent-chat-router.js +22 -0
- package/server/dist/agent-mcp-config.js +45 -4
- package/server/dist/agent-operator-prompt.js +149 -56
- package/server/dist/agent-store.js +25 -0
- package/server/dist/agent-tier.js +6 -1
- package/server/dist/browser-capture-manager.js +184 -34
- package/server/dist/browser-playwright.js +98 -13
- package/server/dist/code-explorer-router.js +92 -0
- package/server/dist/db.js +102 -0
- package/server/dist/file-provenance.js +54 -1
- package/server/dist/file-story-manager.js +170 -0
- package/server/dist/file-story.js +148 -0
- package/server/dist/file-summary-generator.js +5 -4
- package/server/dist/git-guardrails.js +62 -0
- package/server/dist/index.js +5 -0
- package/server/dist/integration-branch.js +63 -0
- package/server/dist/interactive-job-session.js +226 -18
- package/server/dist/jira/jira-adf.js +9 -0
- package/server/dist/jira/jira-materializer.js +27 -4
- package/server/dist/jira/jira-status-resolver.js +12 -4
- package/server/dist/jira/jira-sync-manager.js +130 -2
- package/server/dist/jira-router.js +1 -1
- package/server/dist/loop-effect.js +12 -0
- package/server/dist/loop-executors.js +92 -22
- package/server/dist/loop-run-manager.js +354 -28
- package/server/dist/mcp/guide.js +18 -7
- package/server/dist/mcp/tools/jira.js +1 -1
- package/server/dist/mcp/tools/jobs.js +14 -5
- package/server/dist/mcp/tools/rails.js +137 -12
- package/server/dist/mcp/tools/specs.js +35 -9
- package/server/dist/mcp/tools/types.js +49 -0
- package/server/dist/mobile/mobile-ws.js +4 -0
- package/server/dist/path-resolver.js +46 -0
- package/server/dist/pr-body.js +240 -0
- package/server/dist/pr-naming.js +210 -0
- package/server/dist/pr-publisher.js +68 -0
- package/server/dist/project-registry.js +77 -17
- package/server/dist/project-router-jobs.js +53 -13
- package/server/dist/project-router-settings.js +33 -0
- package/server/dist/project-router-terminals.js +16 -0
- package/server/dist/project-router-tickets.js +57 -3
- package/server/dist/project-router.js +52 -13
- package/server/dist/queue-manager.js +268 -83
- package/server/dist/rail-isolated-launch.js +324 -34
- package/server/dist/rail-isolation.js +32 -5
- package/server/dist/rail-pr-decision.js +519 -0
- package/server/dist/rail-pr-delivery.js +75 -0
- package/server/dist/rail-pr-store.js +175 -0
- package/server/dist/rail-worktrees-store.js +18 -0
- package/server/dist/rails-router.js +241 -17
- package/server/dist/rails-store.js +78 -1
- package/server/dist/setup-prerequisites.js +105 -0
- package/server/dist/smash-runner.js +3 -1
- package/server/dist/ticket-store.js +7 -3
- package/server/dist/workspace-resolution.js +27 -0
- package/server/dist/worktree-manager.js +42 -7
- package/server/dist/worktree-overlay.js +261 -0
- package/client/dist/assets/AgentBrowserCapture-BlGDZahz.js +0 -1
- package/client/dist/assets/AgentModeJobsPane-CyNR-9BO.js +0 -1
- package/client/dist/assets/AgentsPage-dNsEsY_x.js +0 -86
- package/client/dist/assets/AnalyticsPage-BAxmR0HQ.js +0 -1
- package/client/dist/assets/CodePage-Crc4BBQN.js +0 -2
- package/client/dist/assets/DesktopAnalyticsPage-IXSnbCce.js +0 -1
- package/client/dist/assets/DocsDialog-Bc4hx7oW.js +0 -11
- package/client/dist/assets/DocsPage-bEU4t9c6.js +0 -11
- package/client/dist/assets/IntegrationsPage-wq2CezEL.js +0 -3
- package/client/dist/assets/JobDetailPage-BBcPk3j8.js +0 -1
- package/client/dist/assets/JobsPage-DXrSPlwa.js +0 -1
- package/client/dist/assets/LogViewer-BoYbwvbU.js +0 -16
- package/client/dist/assets/LoopBuilderPage-CiUMAuWz.js +0 -7
- package/client/dist/assets/LoopsPage-Xrp6W5XW.js +0 -1
- package/client/dist/assets/ProjectSettingsDialog-BU98L5JD.js +0 -1
- package/client/dist/assets/agent-B7GdHP3Z.js +0 -1
- package/client/dist/assets/agent-BHmcgoJf.js +0 -1
- package/client/dist/assets/agent-BdY_fii4.js +0 -1
- package/client/dist/assets/agent-C32FOi9v.js +0 -1
- package/client/dist/assets/agent-CiFQxoaZ2.js +0 -1
- package/client/dist/assets/agent-CtAag7V6.js +0 -1
- package/client/dist/assets/agent-DE4Mp1fY2.js +0 -1
- package/client/dist/assets/agent-DK8qovyG2.js +0 -1
- package/client/dist/assets/browser-ZB1afzjZ.js +0 -1
- package/client/dist/assets/code-BFxE1Yt62.js +0 -1
- package/client/dist/assets/code-BefYOm5Q.js +0 -1
- package/client/dist/assets/code-BkXpJt99.js +0 -1
- package/client/dist/assets/code-C6Sq7_t8.js +0 -1
- package/client/dist/assets/code-CGj3w-2N.js +0 -1
- package/client/dist/assets/code-Dfsxc9o82.js +0 -1
- package/client/dist/assets/code-Y5urks5s2.js +0 -1
- package/client/dist/assets/code-wtcs0ivb.js +0 -1
- package/client/dist/assets/dashboard-B8032psZ.js +0 -1
- package/client/dist/assets/dashboard-BHGKtxty2.js +0 -1
- package/client/dist/assets/dashboard-CXnoUgN22.js +0 -1
- package/client/dist/assets/dashboard-Ccyxqy7d.js +0 -1
- package/client/dist/assets/dashboard-CoED_41r.js +0 -1
- package/client/dist/assets/dashboard-Dc5ZAgMN.js +0 -1
- package/client/dist/assets/dashboard-JMY8ueD3.js +0 -1
- package/client/dist/assets/dashboard-tkWr1aHD2.js +0 -1
- package/client/dist/assets/index-BHPbzyg6.css +0 -2
- package/client/dist/assets/index-n2PmJGF6.js +0 -152
- package/client/dist/assets/jira-BcZzX9122.js +0 -1
- package/client/dist/assets/jira-CTYs7LA12.js +0 -1
- package/client/dist/assets/jira-D2nN39e92.js +0 -1
- package/client/dist/assets/jira-DJxmIkyr.js +0 -1
- package/client/dist/assets/jira-DXMoAKWD.js +0 -1
- package/client/dist/assets/jira-IhC1ROIc.js +0 -1
- package/client/dist/assets/jira-Iw575fN8.js +0 -1
- package/client/dist/assets/jira-kbWZY7jH.js +0 -1
- package/client/dist/assets/jobs-BqF79kHz2.js +0 -1
- package/client/dist/assets/jobs-C1XM5urS.js +0 -1
- package/client/dist/assets/jobs-C5UjG0262.js +0 -1
- package/client/dist/assets/jobs-DBfaHTxC.js +0 -1
- package/client/dist/assets/jobs-DM4BDPdg.js +0 -1
- package/client/dist/assets/jobs-Da5OkZmf2.js +0 -1
- package/client/dist/assets/jobs-JJdnuQ03.js +0 -1
- package/client/dist/assets/jobs-SI34ML8I.js +0 -1
- package/client/dist/assets/loops-BR4FmOv12.js +0 -1
- package/client/dist/assets/loops-BgX_uudn.js +0 -1
- package/client/dist/assets/loops-Bpl2j2LP.js +0 -1
- package/client/dist/assets/loops-CQuuMlyZ.js +0 -1
- package/client/dist/assets/loops-DW8hSMdS2.js +0 -1
- package/client/dist/assets/loops-Q2muu8hW2.js +0 -1
- package/client/dist/assets/loops-q7CNDvfK.js +0 -1
- package/client/dist/assets/settings-CY8udi0e.js +0 -1
- package/client/dist/assets/setup-CNMdCHHt2.js +0 -1
- package/client/dist/assets/setup-Cag4XrbL2.js +0 -1
- package/client/dist/assets/setup-D9IHGoWU.js +0 -1
- package/client/dist/assets/setup-Dg6Ba3JT.js +0 -1
- package/client/dist/assets/setup-DyK36RIW.js +0 -1
- package/client/dist/assets/setup-G4ZvDKxX.js +0 -1
- package/client/dist/assets/setup-aTlGxuwi2.js +0 -1
- package/client/dist/assets/setup-kWsoAeHQ.js +0 -1
- package/client/dist/assets/specs-BFSUPa122.js +0 -1
- package/client/dist/assets/specs-BMzip1WY2.js +0 -1
- package/client/dist/assets/specs-BYeAbIEy.js +0 -1
- package/client/dist/assets/specs-C-mtLcXw.js +0 -1
- package/client/dist/assets/specs-CAzpvADd2.js +0 -1
- package/client/dist/assets/specs-CyRIw_IR.js +0 -1
- package/client/dist/assets/specs-DMm7gB_l.js +0 -1
- package/client/dist/assets/specs-DuottM0Z.js +0 -1
- /package/client/dist/assets/{abap-CpHUwCVK.js → abap-D0E4FfVW.js} +0 -0
- /package/client/dist/assets/{activity-DemHQS7l.js → activity--iN4Ad2R2.js} +0 -0
- /package/client/dist/assets/{activity-B_71BWg3.js → activity-6hM_ZSg9.js} +0 -0
- /package/client/dist/assets/{activity-DHv2V5Oi.js → activity-BZNfOdiS.js} +0 -0
- /package/client/dist/assets/{activity-D0rfjQzT2.js → activity-BuVo5sPB.js} +0 -0
- /package/client/dist/assets/{activity-BpTTj_PH.js → activity-CIOLxGvh.js} +0 -0
- /package/client/dist/assets/{activity-D2e62vbV2.js → activity-D2r2h3SE2.js} +0 -0
- /package/client/dist/assets/{activity-Ch-wbr0C2.js → activity-DtxrAUMo2.js} +0 -0
- /package/client/dist/assets/{addon-image-Ba-TY3wr.js → addon-image-CwoZj17F.js} +0 -0
- /package/client/dist/assets/{addon-ligatures-T4ARLiuu.js → addon-ligatures-CWDrED80.js} +0 -0
- /package/client/dist/assets/{addon-webgl-Cd73n8eh.js → addon-webgl-DMbGeI_u.js} +0 -0
- /package/client/dist/assets/{addspec-xwRX_Pnf.js → addspec-BMtLZLW62.js} +0 -0
- /package/client/dist/assets/{addspec-l_zU5gla.js → addspec-CP0HRuxY.js} +0 -0
- /package/client/dist/assets/{addspec-Dio-H5z0.js → addspec-CRuvWn8d.js} +0 -0
- /package/client/dist/assets/{addspec-D6L4ZteP.js → addspec-D-JLDsUV.js} +0 -0
- /package/client/dist/assets/{addspec-CrEm6Fzr2.js → addspec-DfhDbg5c.js} +0 -0
- /package/client/dist/assets/{addspec-B6Ns8KU02.js → addspec-bsNDdqRm2.js} +0 -0
- /package/client/dist/assets/{addspec-qGyH7MHy2.js → addspec-mgPOt5q02.js} +0 -0
- /package/client/dist/assets/{agents-OzxCLVW1.js → agents-78bTZGZh.js} +0 -0
- /package/client/dist/assets/{agents-hv3sqmPm2.js → agents-BLhWCmDS2.js} +0 -0
- /package/client/dist/assets/{agents-CHgCudUV.js → agents-BUdEi3-N.js} +0 -0
- /package/client/dist/assets/{agents-Dumx4JiM2.js → agents-BpoUaoW92.js} +0 -0
- /package/client/dist/assets/{agents-CnaPeSyw.js → agents-CWo-KyAB.js} +0 -0
- /package/client/dist/assets/{agents-Xh-zYHUx2.js → agents-DDtCJ5M02.js} +0 -0
- /package/client/dist/assets/{agents-DuhLEaQ_.js → agents-bvyRLczL.js} +0 -0
- /package/client/dist/assets/{agentstudio-CCthUdzR.js → agentstudio-BMQxc_bz.js} +0 -0
- /package/client/dist/assets/{agentstudio-CcH8Ckql2.js → agentstudio-COZriimI2.js} +0 -0
- /package/client/dist/assets/{agentstudio-Bo91kfUd2.js → agentstudio-CWgXG5W52.js} +0 -0
- /package/client/dist/assets/{agentstudio-VJOa_NVO.js → agentstudio-C_Jq8Tl4.js} +0 -0
- /package/client/dist/assets/{agentstudio-BIxikDf_.js → agentstudio-Dtq3dGYk.js} +0 -0
- /package/client/dist/assets/{agentstudio-Bz8cP8_c.js → agentstudio-jKMTdT70.js} +0 -0
- /package/client/dist/assets/{agentstudio-DARgYg5Z2.js → agentstudio-sI27TpBu2.js} +0 -0
- /package/client/dist/assets/{aiedit-5ZXN4cep2.js → aiedit-6CHdb_iv2.js} +0 -0
- /package/client/dist/assets/{aiedit-B7gAJZVC.js → aiedit-B03pD_Na.js} +0 -0
- /package/client/dist/assets/{aiedit-D92V-kUW.js → aiedit-BtRqRxML.js} +0 -0
- /package/client/dist/assets/{aiedit-D9ualLVJ.js → aiedit-eMN4eQPF.js} +0 -0
- /package/client/dist/assets/{aiedit-h48tJU0V2.js → aiedit-hknZlly82.js} +0 -0
- /package/client/dist/assets/{aiedit-xkA_mR2a2.js → aiedit-igmw-ZoZ2.js} +0 -0
- /package/client/dist/assets/{aiedit-7B2dvCv-.js → aiedit-pc5JDUq1.js} +0 -0
- /package/client/dist/assets/{analytics-slx4X1mu2.js → analytics-BWMUZ2Pq2.js} +0 -0
- /package/client/dist/assets/{analytics-uRNP6yAJ.js → analytics-Bj-SmKHa.js} +0 -0
- /package/client/dist/assets/{analytics-WF1I49ln.js → analytics-C5dpiS0o.js} +0 -0
- /package/client/dist/assets/{analytics-CBvaxOId.js → analytics-CCprAqk3.js} +0 -0
- /package/client/dist/assets/{analytics-BakymH7Z2.js → analytics-CR1TJqUi2.js} +0 -0
- /package/client/dist/assets/{analytics-B7bPj6u_2.js → analytics-DfNdXR0y2.js} +0 -0
- /package/client/dist/assets/{analytics-DZ74aQ54.js → analytics-rmHuJv0V.js} +0 -0
- /package/client/dist/assets/{apex-DlD7oJX6.js → apex-D_X_8J4d.js} +0 -0
- /package/client/dist/assets/{atom-one-dark-BrRN8wBy.js → atom-one-dark-BMDPFwRZ.js} +0 -0
- /package/client/dist/assets/{attachments-C11tOKZ_.js → attachments-BgBNSqQd.js} +0 -0
- /package/client/dist/assets/{attachments-Bnbyj2PN.js → attachments-BjyMmrwE.js} +0 -0
- /package/client/dist/assets/{attachments-CIeLa8l12.js → attachments-C9GTTJsx2.js} +0 -0
- /package/client/dist/assets/{attachments-DslHfa-L.js → attachments-DCZOL1RU.js} +0 -0
- /package/client/dist/assets/{attachments-C-gyrCOb.js → attachments-DL-bPy9E.js} +0 -0
- /package/client/dist/assets/{attachments-Cxrs0pyL2.js → attachments-DPCmkFZu2.js} +0 -0
- /package/client/dist/assets/{attachments-TTPsc0a52.js → attachments-rNn1ekRy2.js} +0 -0
- /package/client/dist/assets/{azcli-CmXFAbc-.js → azcli-PZLnZ3jH.js} +0 -0
- /package/client/dist/assets/{bat-DdNJq4hH.js → bat-KlBOxpO4.js} +0 -0
- /package/client/dist/assets/{bicep-Bppz7WOA.js → bicep-CgG9oF3V.js} +0 -0
- /package/client/dist/assets/{cameligo-0MRMdSmg.js → cameligo-6R45j6Ph.js} +0 -0
- /package/client/dist/assets/{chat-BvHrebKC2.js → chat-BgL3zv6x2.js} +0 -0
- /package/client/dist/assets/{chat-CZyiLJvQ.js → chat-Bh3NdgJs.js} +0 -0
- /package/client/dist/assets/{chat-DKYP7NnC.js → chat-Bom6bqK3.js} +0 -0
- /package/client/dist/assets/{chat-5mdg_YIc2.js → chat-DdwZjT8K2.js} +0 -0
- /package/client/dist/assets/{chat-wkTIy9rX.js → chat-Dnwg-NpQ.js} +0 -0
- /package/client/dist/assets/{chat-BpYxnkr4.js → chat-DsbwJhus.js} +0 -0
- /package/client/dist/assets/{chat-BGax2nV62.js → chat-vylxqR0P2.js} +0 -0
- /package/client/dist/assets/{clojure-B5dKj863.js → clojure-CLAAMO7J.js} +0 -0
- /package/client/dist/assets/{clsx-1dnHRn8W.js → clsx-CNmW0Nip.js} +0 -0
- /package/client/dist/assets/{coffee-DSbWjzk7.js → coffee-AruSygo-.js} +0 -0
- /package/client/dist/assets/{commands-uz_uKT242.js → commands-C4Y3C-PF2.js} +0 -0
- /package/client/dist/assets/{commands-Bb7MnPqn2.js → commands-CSDs9q_2.js} +0 -0
- /package/client/dist/assets/{commands-C_7zZwJf.js → commands-DkU0qliq.js} +0 -0
- /package/client/dist/assets/{commands-D_6B8lfU.js → commands-JWMfGDmr.js} +0 -0
- /package/client/dist/assets/{commands-DBc5llLi2.js → commands-RHOchN4n2.js} +0 -0
- /package/client/dist/assets/{commands-CQkdthjF.js → commands-u-4eEHCN.js} +0 -0
- /package/client/dist/assets/{commands-DhZNhSbl.js → commands-xHDDGfcP2.js} +0 -0
- /package/client/dist/assets/{cpp-SBF8SAh9.js → cpp-DEE5r4Pw.js} +0 -0
- /package/client/dist/assets/{csharp-Lzuq_1t-.js → csharp-BVXJUvbK.js} +0 -0
- /package/client/dist/assets/{csp-BEzxZqi1.js → csp-cXOF0JoV.js} +0 -0
- /package/client/dist/assets/{css-C3D3PKln.js → css-C_zQuAoy.js} +0 -0
- /package/client/dist/assets/{cypher-CQ3dEPmv.js → cypher-t95m_Q-O.js} +0 -0
- /package/client/dist/assets/{dart-DCPmxolI.js → dart-B4r1Tg-e.js} +0 -0
- /package/client/dist/assets/{dockerfile-B_2_aaTO.js → dockerfile-6mt7zHQw.js} +0 -0
- /package/client/dist/assets/{ecl-rADUeXsV.js → ecl-DEY_Fz_Q.js} +0 -0
- /package/client/dist/assets/{editor.api2-T7u8kQWG.js → editor.api2-C3B0tp2x.js} +0 -0
- /package/client/dist/assets/{elixir-DOd-TuJO.js → elixir-R6-q1c5t.js} +0 -0
- /package/client/dist/assets/{explore-BHEhNekP2.js → explore-B7fblXBb2.js} +0 -0
- /package/client/dist/assets/{explore-DAsroA482.js → explore-BHtEpoNN2.js} +0 -0
- /package/client/dist/assets/{explore-UwHHj2ux.js → explore-C0k8HrkN.js} +0 -0
- /package/client/dist/assets/{explore-DaXiW9-6.js → explore-CNBzrEPS.js} +0 -0
- /package/client/dist/assets/{explore-CWlAXx0f2.js → explore-D_mWBYCS2.js} +0 -0
- /package/client/dist/assets/{explore-DG1CtYqT.js → explore-Dahc1lOx.js} +0 -0
- /package/client/dist/assets/{explore-DMSGAnhK.js → explore-UvW1jEMa.js} +0 -0
- /package/client/dist/assets/{flow9-Bf7zg_j0.js → flow9-CNQvHBOt.js} +0 -0
- /package/client/dist/assets/{format-command-BHymDa4r.js → format-command-CuWuRvka.js} +0 -0
- /package/client/dist/assets/{fsharp-BqROZjbA.js → fsharp-vPZkFXwv.js} +0 -0
- /package/client/dist/assets/{go-oQTP5uLe.js → go-KUzBMYJ_.js} +0 -0
- /package/client/dist/assets/{graphql-CSHfTU3q.js → graphql-C3W0rCsD.js} +0 -0
- /package/client/dist/assets/{hcl-CeG-RoFJ.js → hcl-BOOMFSNX.js} +0 -0
- /package/client/dist/assets/{ini-B2Dv4ohc.js → ini-CFat1WJr.js} +0 -0
- /package/client/dist/assets/{integrations-CAF21FbQ.js → integrations-4KZnYECp.js} +0 -0
- /package/client/dist/assets/{integrations-CHCgning2.js → integrations-7W266oqF2.js} +0 -0
- /package/client/dist/assets/{integrations-B-JVE1_D.js → integrations-BNuauK3o.js} +0 -0
- /package/client/dist/assets/{integrations-BAujIDoE.js → integrations-CHy8tnpV.js} +0 -0
- /package/client/dist/assets/{integrations-DS5FFMes.js → integrations-Cl_wD5AI.js} +0 -0
- /package/client/dist/assets/{integrations-axZN4--n2.js → integrations-Cy8nZ_dv2.js} +0 -0
- /package/client/dist/assets/{integrations-CtsOpq2D2.js → integrations-zMqY4VU12.js} +0 -0
- /package/client/dist/assets/{java-aUDDeufb.js → java-Dee-CNAM.js} +0 -0
- /package/client/dist/assets/{julia-C5LbruO5.js → julia-CGNlLYuU.js} +0 -0
- /package/client/dist/assets/{kotlin-C6mOuSKk.js → kotlin-CY7lhknJ.js} +0 -0
- /package/client/dist/assets/{less-D5qC3caW.js → less-D0KN7hfJ.js} +0 -0
- /package/client/dist/assets/{lexon-Dr2La-fj.js → lexon-CuRJufPs.js} +0 -0
- /package/client/dist/assets/{lua-Zy6u5z6Z.js → lua-DHvH62Zf.js} +0 -0
- /package/client/dist/assets/{m3-C7XHeDz_.js → m3-tlthQ8Fo.js} +0 -0
- /package/client/dist/assets/{markdown-PiF7r-2h.js → markdown-Dbx1LgUZ.js} +0 -0
- /package/client/dist/assets/{mcp-B_nWlxZa2.js → mcp-CjVKXAhD2.js} +0 -0
- /package/client/dist/assets/{mcp-B8omp_Cd.js → mcp-Dcl-XxkR.js} +0 -0
- /package/client/dist/assets/{mcp-DTCCrYHz2.js → mcp-DtbxuH3V2.js} +0 -0
- /package/client/dist/assets/{mcp-DytBbASZ.js → mcp-H-gnQUdN.js} +0 -0
- /package/client/dist/assets/{mcp-D_oPS6Zc.js → mcp-N1nzp8oL.js} +0 -0
- /package/client/dist/assets/{mcp-Cb2jtHP72.js → mcp-XJNRfxVp2.js} +0 -0
- /package/client/dist/assets/{mcp-DPqm2C8-.js → mcp-sRmWE8WJ.js} +0 -0
- /package/client/dist/assets/{mips-nn07GiyE.js → mips-D_O3IUz_.js} +0 -0
- /package/client/dist/assets/{msdax-DaKFVMST.js → msdax-C_ZmCnRt.js} +0 -0
- /package/client/dist/assets/{mysql-C6d6xrbU.js → mysql-C-dCEYSX.js} +0 -0
- /package/client/dist/assets/{nav-Cibp2KWF.js → nav-40HzpIFb.js} +0 -0
- /package/client/dist/assets/{nav-DtTnF9xd.js → nav-8yPhBn00.js} +0 -0
- /package/client/dist/assets/{nav-Danf5sRf2.js → nav-B6PkGfTk2.js} +0 -0
- /package/client/dist/assets/{nav-Bqhyfbcj2.js → nav-BHqMLrS72.js} +0 -0
- /package/client/dist/assets/{nav-CQb9y1km.js → nav-CGy4yx3C.js} +0 -0
- /package/client/dist/assets/{nav-BAsYcqdw2.js → nav-CXEDcRdv2.js} +0 -0
- /package/client/dist/assets/{nav-BRrNlZkr.js → nav-EI_OhEAo.js} +0 -0
- /package/client/dist/assets/{objective-c-B6KMtI-k.js → objective-c-DZY9Aqxd.js} +0 -0
- /package/client/dist/assets/{pascal-DYr8MPE7.js → pascal-BVHLXoor.js} +0 -0
- /package/client/dist/assets/{pascaligo-B3pd-jJ_.js → pascaligo-XdG_6u3k.js} +0 -0
- /package/client/dist/assets/{perl-z2xUzoaL.js → perl-b9QV0BcD.js} +0 -0
- /package/client/dist/assets/{pgsql-DUvT-09-.js → pgsql-Du5FDOgT.js} +0 -0
- /package/client/dist/assets/{php-CGyOmJfy.js → php-WJD0z2Z_.js} +0 -0
- /package/client/dist/assets/{pla-CMqgvyD0.js → pla-CbciTf2w.js} +0 -0
- /package/client/dist/assets/{postiats-Dx5LUn4Z.js → postiats-C1QxmvVq.js} +0 -0
- /package/client/dist/assets/{powerquery-DazYxvJ6.js → powerquery-BEYDhPLZ.js} +0 -0
- /package/client/dist/assets/{powershell-B3nwlDka.js → powershell-CfaYw4XL.js} +0 -0
- /package/client/dist/assets/{protobuf-BGuu2u2s.js → protobuf-pwZEDOYa.js} +0 -0
- /package/client/dist/assets/{pug-Dbte1MXA.js → pug-5ftqSPVe.js} +0 -0
- /package/client/dist/assets/{qsharp-DJLwBOvG.js → qsharp-uI6qZMq4.js} +0 -0
- /package/client/dist/assets/{r-DmGBRSHj.js → r-BK54P1EG.js} +0 -0
- /package/client/dist/assets/{redis-VvUYn0a4.js → redis-DI0yd7kN.js} +0 -0
- /package/client/dist/assets/{redshift-6GdDrxg3.js → redshift-Dov26eyI.js} +0 -0
- /package/client/dist/assets/{restructuredtext-CfAB8aRU.js → restructuredtext-QqJ_1dC-.js} +0 -0
- /package/client/dist/assets/{ruby-CIYK6MXY.js → ruby-5WjveeVb.js} +0 -0
- /package/client/dist/assets/{rust-CTHZfjj9.js → rust-BzVSfqFH.js} +0 -0
- /package/client/dist/assets/{sb-CkKTdkz_.js → sb-DMIUfT-3.js} +0 -0
- /package/client/dist/assets/{scala-Bx-Wr9TM.js → scala-CSKA7lqt.js} +0 -0
- /package/client/dist/assets/{scheme-Dcfi6f83.js → scheme-CojOP2Qc.js} +0 -0
- /package/client/dist/assets/{scss-ByL-7PFQ.js → scss-DoBZGJG6.js} +0 -0
- /package/client/dist/assets/{shell-Csnb9Yqd.js → shell-YOaE4udl.js} +0 -0
- /package/client/dist/assets/{solidity-Dbw5-0QP.js → solidity-l3jSyVLu.js} +0 -0
- /package/client/dist/assets/{sophia-ZQ3saZQx.js → sophia-BhSGTaQJ.js} +0 -0
- /package/client/dist/assets/{sparql-BEtOel8u.js → sparql-qhk6QD9w.js} +0 -0
- /package/client/dist/assets/{sql-DGPDbzB7.js → sql-DoO3y21-.js} +0 -0
- /package/client/dist/assets/{st-GeW2MOgh.js → st-ChZAY8oG.js} +0 -0
- /package/client/dist/assets/{swift-BVYTN8jq.js → swift-D290Tr7_.js} +0 -0
- /package/client/dist/assets/{systemverilog-Deg2a8Lr.js → systemverilog-DsxzgJ-o.js} +0 -0
- /package/client/dist/assets/{tcl-6DnLmROF.js → tcl-BKDUHAAR.js} +0 -0
- /package/client/dist/assets/{terminal-CDiOAmBd2.js → terminal-BRm03iFA2.js} +0 -0
- /package/client/dist/assets/{terminal-CJN-mQMc.js → terminal-De2Brd23.js} +0 -0
- /package/client/dist/assets/{terminal-CYB4TiAd.js → terminal-DxQWCqSD2.js} +0 -0
- /package/client/dist/assets/{terminal-DsaDTq5N2.js → terminal-WSAvHXoU.js} +0 -0
- /package/client/dist/assets/{terminal-DTQ_dPqi2.js → terminal-Z7KsDM_n.js} +0 -0
- /package/client/dist/assets/{terminal-58ReNaya.js → terminal-cqfd3EDV.js} +0 -0
- /package/client/dist/assets/{terminal-DawP8xNL.js → terminal-xGbCZJHg.js} +0 -0
- /package/client/dist/assets/{tickets-DoRTUYRT.js → tickets-B7zT4IRf.js} +0 -0
- /package/client/dist/assets/{tickets-DBfFePwk2.js → tickets-BoXom7l8.js} +0 -0
- /package/client/dist/assets/{tickets-DvohTziT2.js → tickets-C3b8cHhd2.js} +0 -0
- /package/client/dist/assets/{tickets-Da15iaRw.js → tickets-CFXnJsYF.js} +0 -0
- /package/client/dist/assets/{tickets-CujsZvkf.js → tickets-CWYFvx1W2.js} +0 -0
- /package/client/dist/assets/{tickets-Df6pee-O2.js → tickets-DTHo9c3C.js} +0 -0
- /package/client/dist/assets/{tickets-CNvIilmP.js → tickets-SuX_HkK4.js} +0 -0
- /package/client/dist/assets/{twig-XbbXW9Yz.js → twig-UpZQaM8G.js} +0 -0
- /package/client/dist/assets/{typespec-CRlV8GhI.js → typespec-DzaKvN8i.js} +0 -0
- /package/client/dist/assets/{vb-BHE2izPH.js → vb-CZpbb7tk.js} +0 -0
- /package/client/dist/assets/{wgsl-Bf5vkfmY.js → wgsl-CNt3OIvl.js} +0 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# Safe PR review flow (ask-first) — as-built record
|
|
2
|
+
|
|
3
|
+
> Successor to the shipped `safe-pr-workflow` (#486–#500). That change made every repo-mutating
|
|
4
|
+
> rail isolate in worktrees off the integration branch and **auto-deliver** a draft PR at settle,
|
|
5
|
+
> surfaced by a one-shot toast. This change replaces the auto-delivery half with an explicit,
|
|
6
|
+
> durable, **ask-first** flow: at settle the work stays on its isolated branches and the user
|
|
7
|
+
> decides — from the dashboard rail row or from the launching agent-chat conversation — whether a
|
|
8
|
+
> PR is created at all. specrails remains a PR producer, never a merge authority.
|
|
9
|
+
|
|
10
|
+
## The single source of truth
|
|
11
|
+
|
|
12
|
+
One durable row per rail **launch** in `rail_pr_deliveries` (per-project `jobs.sqlite`,
|
|
13
|
+
migration 36; CRUD in `server/rail-pr-store.ts`). Grain is the launch, not the ticket: a delivery
|
|
14
|
+
is one PR for the whole launch, keyed internally by `rail_key = ${railIndex}-${loopId}`; the row
|
|
15
|
+
is keyed by uuid because a rail slot can be relaunched.
|
|
16
|
+
|
|
17
|
+
Columns beyond the obvious: `ticket_ids` (JSON `number[]`), `base_branch` (the resolved
|
|
18
|
+
integration branch — the "against `<base>`" in the question), `branches` (JSON
|
|
19
|
+
`DeliverBranchRecord[]` — per-unit `{ticketId, branch, succeeded}` captured at build-settle),
|
|
20
|
+
`worktree_ids` (JSON `string[]` of `rail_worktrees` ledger ids), `loop_name` (PR title/body),
|
|
21
|
+
`pr_url`/`pr_number`, `pr_state` (`none | local-only | pushed | pr-created` — the pr-publisher
|
|
22
|
+
degradation ladder, independent of `decision`), `origin_surface` (`dashboard | agent-chat`),
|
|
23
|
+
`origin_conversation_id` (soft cross-DB reference to `agent_conversations.id` in
|
|
24
|
+
`desktop.sqlite`; no FK is possible across SQLite files).
|
|
25
|
+
|
|
26
|
+
The `branches` + `worktree_ids` columns exist because PR creation is **deferred**: nothing about
|
|
27
|
+
the settle survives in memory by the time the user clicks, so `create-pr` and `discard`
|
|
28
|
+
reconstruct all their inputs from the row.
|
|
29
|
+
|
|
30
|
+
## State machine (`decision`)
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
building ──(settle, ≥1 succeeded unit)──▶ on_review [patch branches/worktree_ids]
|
|
34
|
+
building ──(settle, 0 succeeded)────────▶ discarded (terminal auto-close; per-run settle already reverted tickets)
|
|
35
|
+
on_review | pr_failed ──[Create PR]────▶ pr_draft (delivered) | pr_failed (assembly-failed / throw)
|
|
36
|
+
pr_draft (pr_url != null) ──[Publish]──▶ pr_ready (gh pr ready — opens the draft for team review)
|
|
37
|
+
pr_draft | pr_ready ──[Check merge]────▶ merged (gh pr view reports MERGED; else 200 no-op)
|
|
38
|
+
on_review | pr_draft | pr_ready | pr_failed ──[Discard]─▶ discarded
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`merged` / `discarded` are terminal. A **degraded** draft (`pr_state` `pushed`/`local-only`,
|
|
42
|
+
`pr_url = null`) offers no Publish — only retry (`create-pr` is legal from a `pr_draft` whose
|
|
43
|
+
`pr_url` is null) or Discard. Every transition is the compare-and-set
|
|
44
|
+
`transitionDecision(db, id, expected, next, patch)` — one atomic
|
|
45
|
+
`UPDATE … WHERE id = ? AND decision = ?` — so two surfaces racing on the same delivery cannot
|
|
46
|
+
both win; the loser's `false` return maps to **409 `stale_decision`**.
|
|
47
|
+
|
|
48
|
+
## Launch wiring (`server/rail-isolated-launch.ts`)
|
|
49
|
+
|
|
50
|
+
- `prMode = isRailPrDeliveryEnabled()` is captured **once at launch entry** — a mid-flight env
|
|
51
|
+
flip can never split one launch across the two delivery paths.
|
|
52
|
+
- In PR mode the row is INSERTed **up front** (`decision='building'`) so the origin link is
|
|
53
|
+
persisted before any await can drop it and late-joining clients hydrate mid-build via
|
|
54
|
+
`GET /rails`. Worktree-allocation failure transitions the row to `discarded` (kept for audit,
|
|
55
|
+
never deleted) so a wedged `building` row can never block the slot.
|
|
56
|
+
- Isolation units: `scope='per-ticket'` → one worktree/run per ticket; `scope='all'`
|
|
57
|
+
(implement/batch — one pipeline invocation covers all tickets) → **one** worktree/run covering
|
|
58
|
+
every ticket. `isolationApplies` (`server/rail-isolation.ts`) isolates per-ticket rails always
|
|
59
|
+
and `all`-scoped rails **only when PR delivery is on** (kill-switch off ⇒ byte-identical
|
|
60
|
+
legacy shared-cwd).
|
|
61
|
+
- Per-run settle: `ctx.onLoopRunFinished(runId, outcome, { ticketCompletionStatus })` —
|
|
62
|
+
`'on_review'` in PR mode, `'done'` otherwise (`applyJobOutcomeToTickets` gains the analogous
|
|
63
|
+
`{ completedStatus }` option; explicit `'done'` / kill-switch off is byte-identical legacy).
|
|
64
|
+
When the caller passes NO opts (shared-cwd rail runs, standalone loop runs,
|
|
65
|
+
isolation-unavailable fallbacks) the default now derives from `isRailPrDeliveryEnabled()` —
|
|
66
|
+
read once per settle and reused for the Jira split, so one settle can never split across the
|
|
67
|
+
two paths (universal ask-first; the explicit isolated-rail opts are idempotent with it).
|
|
68
|
+
Failures ignore the field (revert `in_progress → todo` as always). In PR mode the completed
|
|
69
|
+
path calls `jiraSyncManager.onRailReview` instead of the done-flavoured `onJobOutcome`.
|
|
70
|
+
- All-settle in PR mode: patch `branches` + `worktree_ids`, transition `building →`
|
|
71
|
+
`on_review` (≥1 succeeded) or `discarded` (0 succeeded), broadcast, and — when
|
|
72
|
+
`origin_conversation_id` is set — post the inline decision card into the conversation.
|
|
73
|
+
The legacy merge-back **never runs** in PR mode. Kill-switch off: no row, no `on_review`,
|
|
74
|
+
legacy local merge-back exactly as before.
|
|
75
|
+
|
|
76
|
+
## Per-run worktree overlay (`server/worktree-overlay.ts`)
|
|
77
|
+
|
|
78
|
+
`git worktree add` materializes only TRACKED files — so a RELOCATED project's framework
|
|
79
|
+
surface (`.claude/commands/specrails/*.md`, sr-* agents, skills, rules, `.mcp.json`, the
|
|
80
|
+
seeded instruction file), which lives in `~/.specrails/projects/<slug>/workspace/`, was
|
|
81
|
+
absent from the worktree: the claude CLI reported `Unknown command: /specrails:implement`
|
|
82
|
+
and the loop "succeeded" through verify/fix without implementing (live evidence: run
|
|
83
|
+
01f41203). Legacy projects have the sibling gap for their UNTRACKED on-disk `.claude`
|
|
84
|
+
entries. Each allocated worktree therefore gets `applyWorktreeOverlay(...)` at launch:
|
|
85
|
+
|
|
86
|
+
- **Source root** = the project's effective artifact root, resolved once per launch via
|
|
87
|
+
`resolveProjectExecution`: the workspace when relocated, else the repo itself.
|
|
88
|
+
- **Merge-only symlinks** under `<worktree>/<providerDir>/`: dir links where a dir is
|
|
89
|
+
wholly absent, per-file/per-child where the checkout is partially present; checkout
|
|
90
|
+
content is NEVER overwritten. `agent-memory` is linked (all runs share memory — the
|
|
91
|
+
pre-isolation shared-cwd semantics, deliberate). The providerDir root and the source's
|
|
92
|
+
`worktrees/` entry are never linked (nested pipeline worktrees stay local). `.mcp.json`
|
|
93
|
+
and the instruction file (CLAUDE.md/AGENTS.md/GEMINI.md per provider) are COPIED when
|
|
94
|
+
the checkout lacks them. Windows: junction → dereferencing-copy fallback.
|
|
95
|
+
- **Never on the PR**: every overlay-owned path lands in a worktree-local manifest
|
|
96
|
+
(`.sr-rail-overlay.json`, unioned across passes so a RESUMED worktree keeps prior
|
|
97
|
+
entries claimed) and is excluded from `commitWorktree`'s stage via `:(exclude)`
|
|
98
|
+
pathspecs. Excluded paths are untracked by construction, so no real work can be lost;
|
|
99
|
+
a no-op overlay keeps the byte-identical `git add -A`. Worktree removal (`git worktree
|
|
100
|
+
remove --force`) deletes the symlinks as entries without following them.
|
|
101
|
+
- **Degrade, don't abort**: entry-level failures produce `warnings` — surfaced as a
|
|
102
|
+
server log line plus the project-scoped `rail.overlay_degraded` WS event — and the
|
|
103
|
+
spawn proceeds (a partial surface beats an aborted rail). `applyWorktreeOverlay` never
|
|
104
|
+
throws.
|
|
105
|
+
- **Env correctness**: `SPECRAILS_REPO_DIR` = the WORKTREE per run (loop-executors
|
|
106
|
+
`aiStepEnv` — writes/git land in the worktree, never the live repo), while the
|
|
107
|
+
relocated workspace artifact indirection (`SPECRAILS_TICKETS_PATH` /
|
|
108
|
+
`SPECRAILS_BACKLOG_CONFIG_PATH` / `SPECRAILS_PROFILES_DIR` / `SPECRAILS_STATE_DIR` /
|
|
109
|
+
`SPECRAILS_WORKSPACE_DIR`) rides the executors' lazily-resolved base env
|
|
110
|
+
(`workspace-resolution.ts` `resolveLoopBaseEnv`, wired per project in
|
|
111
|
+
`project-registry.ts`) — the worktree's cwd-relative `${ENV:-legacy}` defaults would
|
|
112
|
+
otherwise resolve to nothing. Legacy projects keep `process.env` untouched.
|
|
113
|
+
|
|
114
|
+
## The one decision endpoint
|
|
115
|
+
|
|
116
|
+
`POST /rails/pr-decision` `{ prDeliveryId, action, expectedDecision }` (replaces the stateless
|
|
117
|
+
v1 `POST /rails/pr-review`). The route validates and delegates to
|
|
118
|
+
`server/rail-pr-decision.ts` `executePrDecision` (deps injected — db/git/exec/broadcast/jira/
|
|
119
|
+
agent-chat — so the whole matrix unit-tests without git/gh/network).
|
|
120
|
+
|
|
121
|
+
- **create-pr** — deferred `deliverRailAsPr` (`server/rail-pr-delivery.ts`: 1 unit → its
|
|
122
|
+
branch; N → assembled onto the conventional batch branch off the integration branch, one PR
|
|
123
|
+
covering every ticket). The PR **title and canonical body are composed here** (see "Branch
|
|
124
|
+
naming & PR content" below) from the ticket store + `jira_links` + the branch diffs — all
|
|
125
|
+
failure-tolerant. Retry hazard handled first: a prior degraded delivery leaves the batch
|
|
126
|
+
branch behind and `deliverRailAsPr` assembles with `worktree add -b`, so the stale batch branch
|
|
127
|
+
is defensively `-D`'d (never the integration branch); inside `deliverRailAsPr` the batch name
|
|
128
|
+
additionally collide-suffixes `-2`… against the live branch listing. Delivered → `pr_draft`
|
|
129
|
+
(+`pr_url`/`pr_number` when `pr-created`; null when degraded); assembly-failed or a thrown
|
|
130
|
+
guardrail → `pr_failed` (retryable). Tickets stay `on_review` — a draft PR still awaits the
|
|
131
|
+
merge.
|
|
132
|
+
- **publish** — `gh pr ready <url>` → `pr_ready` (the draft opens for the team's normal review).
|
|
133
|
+
Requires a real `pr_url`.
|
|
134
|
+
- **discard** — best-effort `gh pr close <url> --delete-branch`; remove the launch's worktrees
|
|
135
|
+
(ledger rows closed as `failed`); delete every referenced branch (per-unit sources, assembled
|
|
136
|
+
head, and the possibly-stale batch branch recomputed from the same ticket data create-pr names
|
|
137
|
+
it from — the integration branch is NEVER deleted); → `discarded`; revert
|
|
138
|
+
still-`on_review` tickets → `todo` (a manually re-triaged spec is respected) + Jira
|
|
139
|
+
`onRailDiscard`.
|
|
140
|
+
- **poll-merge** — on-demand `gh pr view <url> --json state,mergedAt`; `MERGED` → `merged` +
|
|
141
|
+
tickets → `done` + Jira `onRailMerged` (with a "PR merged: `<url>`" comment); anything else is
|
|
142
|
+
an observation-only 200. There is no background poller (loopback server, no webhooks) —
|
|
143
|
+
detection is click-driven.
|
|
144
|
+
|
|
145
|
+
`gh` failures return 502 `gh_failed` with **no transition**. Illegal action for the current
|
|
146
|
+
state → 409 (`stale_decision` + `reason: 'illegal_action'`).
|
|
147
|
+
|
|
148
|
+
## Branch naming & PR content (pr-naming.ts / pr-body.ts)
|
|
149
|
+
|
|
150
|
+
Conventional, open-source-style naming for everything the user sees on GitHub. All pure string
|
|
151
|
+
logic in `server/pr-naming.ts` (branches + titles) and `server/pr-body.ts` (canonical body +
|
|
152
|
+
diff collection), fully unit-tested.
|
|
153
|
+
|
|
154
|
+
- **`<ref>`** — the ticket's Jira key when Jira-linked, else the local ticket number. **JIRA
|
|
155
|
+
ALWAYS PREVAILS**, resolved per ticket at naming/body time with no HTTP: the authoritative
|
|
156
|
+
`jira_links` row (`getLinkByLocalId`, tombstoned links ignored) wins over the ticket's
|
|
157
|
+
`jira_key` field; a missing link degrades to the local id.
|
|
158
|
+
- **`<type>` heuristic** (labels checked before the title; first match wins): bug|bugfix|fix|
|
|
159
|
+
hotfix → `fix`; chore|refactor|cleanup → `chore`; docs|documentation → `docs`; else `feat`.
|
|
160
|
+
Batch type = `feat` unless ALL tickets map to the same other type.
|
|
161
|
+
- **Per-unit branch** — `<type>/<ref>-<kebab-title>` (e.g. `feat/SKILLS-101-add-dark-mode`,
|
|
162
|
+
`fix/37-crash-on-save`). The kebab is ascii-folded (NFKD, diacritics stripped, `ß`→`ss`),
|
|
163
|
+
capped ~40 chars at a word boundary, never a leading/trailing dash; emoji-only titles fold to
|
|
164
|
+
nothing (`<type>/<ref>`). Every generated name passes `isValidBranchName`.
|
|
165
|
+
- **Batch branch** (N>1 assembled delivery) — `<type>/<primary-ref>-batch-<n>-tickets`.
|
|
166
|
+
- **Collisions** — bounded suffixing `-2`, `-3`… (20 attempts). At worktree allocation
|
|
167
|
+
(`rail-isolated-launch`) a branch that a PRIOR rail run allocated for the SAME ticket (per the
|
|
168
|
+
`rail_worktrees` ledger) is **resumed**, not suffixed — preserving the stop/relaunch resume
|
|
169
|
+
semantics; exhaustion falls back to the legacy `sr/<slug>/ticket-<id>`. The **integration
|
|
170
|
+
branch is never used** (reserved in the resolver + asserted in tests). `createWorktree` stays
|
|
171
|
+
generic: an optional preferred `branch` input with the legacy fallback when absent.
|
|
172
|
+
- **PR title** — `[<ref>]<type> - <change>` (e.g. `[SKILLS-101]feat - darkmode added`); the
|
|
173
|
+
`<change>` clause is the ticket title, control-stripped, trailing-period-free and
|
|
174
|
+
first-letter-lowercased unless it reads as an acronym/CamelCase. Batch:
|
|
175
|
+
`[<primary-ref> +<n-1>]<type> - <loop summary>` (e.g. `[SKILLS-101 +2]feat - implement batch
|
|
176
|
+
of 3 tickets`). The per-ticket type matches its branch type.
|
|
177
|
+
- **PR body** (`buildCanonicalPrBody`, composed at create-pr time) — one summary paragraph
|
|
178
|
+
(loop, N tickets, base branch), then per ticket `## <ref> — <title>` (Jira key verbatim,
|
|
179
|
+
`#<id>` for local) with **Problem** (the spec's leading narrative / problem-ish heading;
|
|
180
|
+
omitted when missing), **Solution** (a tight digest of the solution-ish sections; overflow in
|
|
181
|
+
a collapsed `<details>` block — never a full spec dump; the Contract Layer appendix is
|
|
182
|
+
stripped first), and **Tests** (HONEST: touched `*.test.*`/`*.spec.*`/`__tests__/` files from
|
|
183
|
+
`git diff --name-status <base>...<branch>`; "No test files changed in this diff." when none;
|
|
184
|
+
an explicit unavailable note when the diff failed — never invented). A final `## Changes`
|
|
185
|
+
section lists the per-branch diffstat (`git diff --shortstat`), omitted entirely when git
|
|
186
|
+
fails — diff problems can only degrade the body, NEVER block PR creation. The v1
|
|
187
|
+
`buildBatchPrBody` and its "_Draft PR produced by specrails — the engineer owns the merge._"
|
|
188
|
+
footer are gone.
|
|
189
|
+
|
|
190
|
+
## The sync contract (two surfaces, zero desync)
|
|
191
|
+
|
|
192
|
+
Neither surface holds authoritative state; both render the last snapshot they received and POST
|
|
193
|
+
the same endpoint with the `expectedDecision` they rendered.
|
|
194
|
+
|
|
195
|
+
- **Durable WS event `rail.pr_state`** (project-scoped, full snapshot — replaces the retired
|
|
196
|
+
one-shot `rail.pr_delivered`): broadcast at row INSERT (`building`), build-settle, and every
|
|
197
|
+
decision mutation. **`GET /rails`** returns `prDeliveries: Record<railIndex, snapshot>`
|
|
198
|
+
(newest non-terminal row per slot) for late-join hydration.
|
|
199
|
+
- **Option A — dashboard.** `client/src/context/RailPrDecisionContext.tsx` (registerHandler on
|
|
200
|
+
the shared socket + `GET /rails` seed) feeds `RailPrDecisionStrip` on `RailRow` (both density
|
|
201
|
+
branches): on_review → Create PR / Discard; pr_draft → Open PR + Publish / Discard (degraded →
|
|
202
|
+
retry); pr_ready → Check merge / Discard; pr_failed → Retry / Discard. Buttons disable in
|
|
203
|
+
flight and reconcile to the next broadcast; Discard confirms first.
|
|
204
|
+
- **Option B — agent chat.** When the row carries `origin_conversation_id`, settle posts a
|
|
205
|
+
**persisted inline card**: a `'system'`-role `agent_messages` row (role is unconstrained TEXT —
|
|
206
|
+
no migration; TS unions widened) whose content is the `PrDecisionCardEnvelope` JSON.
|
|
207
|
+
`AgentChatManager.postPrDecisionCard` / `updatePrDecisionCard` (update-in-place on every
|
|
208
|
+
transition, so cold-load shows terminal states correctly) are reached from rails code via the
|
|
209
|
+
process-wide `server/agent-chat-registry.ts` singleton (null-safe: tests/disabled builds).
|
|
210
|
+
Live updates ride the app-global `agent_pr_decision` WS event; the client renders
|
|
211
|
+
`AgentPrDecisionCard` and POSTs the same project-scoped `/rails/pr-decision`.
|
|
212
|
+
- **Race:** the second answer arrives with a stale `expectedDecision` → 409; the client shows a
|
|
213
|
+
neutral "already resolved" toast and reconciles to the broadcast.
|
|
214
|
+
|
|
215
|
+
## Relaunch guard
|
|
216
|
+
|
|
217
|
+
`POST /rails/:i/launch` returns **409 `{ error: 'pr_decision_pending', prDeliveryId }`** when an
|
|
218
|
+
active (non-terminal) delivery exists for the slot AND the launch would take the isolated PR
|
|
219
|
+
path — a relaunch would append new commits to the undecided branches (worktree creation resumes
|
|
220
|
+
existing branches). Legacy / non-isolated launches are unaffected.
|
|
221
|
+
|
|
222
|
+
## Ticket lifecycle — `on_review`
|
|
223
|
+
|
|
224
|
+
New status in `TicketStatus` / `VALID_STATUSES` (`server/ticket-store.ts`), between
|
|
225
|
+
`in_progress` and `done`. Pipeline-owned:
|
|
226
|
+
|
|
227
|
+
**Universal ask-first (both completion chokepoints).** Under the default-on PR-delivery flag
|
|
228
|
+
EVERY completed job/run promotes its tickets `todo|in_progress → on_review`, never `done`:
|
|
229
|
+
|
|
230
|
+
- **Loop runs** (`project-registry.ts` `onLoopRunFinished`): explicit `ticketCompletionStatus`
|
|
231
|
+
from `launchIsolatedRail` (launch-captured `prMode`); absent opts default to the flag (see
|
|
232
|
+
"Per-run settle" above) — covering shared-cwd rail launches, standalone loop runs, and the
|
|
233
|
+
isolation-unavailable fallback.
|
|
234
|
+
- **QueueManager jobs** (`project-registry.ts` `onJobFinished`): bare-mode launches, MCP
|
|
235
|
+
`/spawn` jobs, ultracode Finalize, interactive auto-settles. `QueueManager._startJob` reads
|
|
236
|
+
`isRailPrDeliveryEnabled()` ONCE per job at spawn — the SAME read that injects
|
|
237
|
+
`SPECRAILS_GIT_AUTO=false` — records it in the in-memory `_jobPrDelivery` map (restart-durable
|
|
238
|
+
by construction, like the interactive gate: a queued job surviving a restart recomputes at its
|
|
239
|
+
own spawn), and both settle paths (`_onJobExit` / `_settleInteractiveJob`) consume it and
|
|
240
|
+
thread `{ ticketCompletionStatus }` into `onJobFinished` on COMPLETED exits (failure statuses
|
|
241
|
+
keep the legacy 3-arg call shape). A mid-flight env flip can never split one job between the
|
|
242
|
+
spawn-env methodology and the settle parking. The Jira write-back splits identically:
|
|
243
|
+
completed + on_review → `onRailReview(changedIds, jobId)`; failed/canceled/zombie → the
|
|
244
|
+
legacy done-flavoured `onJobOutcome`.
|
|
245
|
+
|
|
246
|
+
`done` is reachable ONLY via the PR-decision `poll-merge`, a manual context-menu move, or the
|
|
247
|
+
kill-switch-off legacy path. The `needs_review`-clearing and failure-revert branches of
|
|
248
|
+
`applyJobOutcomeToTickets` are byte-identical to legacy.
|
|
249
|
+
|
|
250
|
+
- Board: lives in the ToDo bucket with an accent-warning "On review" pill
|
|
251
|
+
(`TicketStatusIndicator` et al.); auto-stripped from rails; not draggable onto rails; a rail
|
|
252
|
+
containing one cannot launch.
|
|
253
|
+
- Users can move OUT of it manually (`todo`/`done` via the ticket context menu) but never INTO
|
|
254
|
+
it. Explore "Continue Editing" excludes it (Jira-mirror specs keep their any-column rule).
|
|
255
|
+
`validatePriorityForStatus` unchanged (priority null only for `draft`).
|
|
256
|
+
- Merge → `done`; discard → `todo`; both applied only to tickets still sitting at `on_review`.
|
|
257
|
+
|
|
258
|
+
## Jira mapping
|
|
259
|
+
|
|
260
|
+
- `SpecLogicalState` gains `on_review` (server `server/jira/types.ts` + client `jira-api.ts`);
|
|
261
|
+
`sanitizeStatusMap` accepts the new key (it silently dropped unknown keys before); the connect
|
|
262
|
+
**wizard** and the **connected card** both expose a `statusMap.on_review` editor.
|
|
263
|
+
- Resolver (`jira-status-resolver.ts`): explicit `statusMap.on_review` first, else
|
|
264
|
+
`statusCategory` fallback `indeterminate`. **Same-category-walk fix:** when an explicit target
|
|
265
|
+
is configured and the current status *name* differs, the walk transitions even if both statuses
|
|
266
|
+
share a category (previously a same-category no-op made e.g. In Progress → In Review
|
|
267
|
+
impossible). Unconfigured `statusMap.on_review` still no-ops (issue stays In Progress).
|
|
268
|
+
- Materializer (`jira-materializer.ts`): an inbound issue whose status name equals the mapped
|
|
269
|
+
`on_review` status (case-insensitive) materializes as `on_review` instead of being reverted by
|
|
270
|
+
the `indeterminate` category ~one poll after the outbox drained.
|
|
271
|
+
- Hooks (`jira-sync-manager.ts`, all outbox-only — the local cache write belongs to the caller):
|
|
272
|
+
`onRailReview(ticketIds, refId)` at PR-mode settle; `onRailMerged(ticketIds, refId, prUrl)`
|
|
273
|
+
(Done transition + "PR merged" comment — NOT `onJobOutcome`, whose completion comment assumes
|
|
274
|
+
cost/duration); `onRailDiscard(ticketIds, refId)` (configured `discardStatus`, else logical
|
|
275
|
+
todo).
|
|
276
|
+
|
|
277
|
+
## Origin link (as-built)
|
|
278
|
+
|
|
279
|
+
Persisted end state: `rail_pr_deliveries.origin_surface` + `origin_conversation_id`, written at
|
|
280
|
+
the launch INSERT. As-built:
|
|
281
|
+
|
|
282
|
+
- `POST /rails/:i/launch` accepts `originConversationId` (validated `/^[A-Za-z0-9-]{1,64}$/`) and
|
|
283
|
+
`originSurface` (`'dashboard' | 'agent-chat'`), threaded into `launchIsolatedRail`.
|
|
284
|
+
Dashboard launches default to `origin_surface='dashboard'`, `origin_conversation_id=NULL`.
|
|
285
|
+
- **The MCP auto-attach chain (shipped)** — four hops, so an agent-launched rail tags itself
|
|
286
|
+
end-to-end with no manager change (`AgentChatManager` already passes `conversationId` into
|
|
287
|
+
`prepareAgentMcp`):
|
|
288
|
+
1. `agent-mcp-config.ts` `buildSpecrailsMcpEntry` gained `conversationId` in its opts
|
|
289
|
+
(validated against the same launch regex; malformed ⇒ silently omitted) and sets
|
|
290
|
+
`SPECRAILS_AGENT_CONVERSATION` in `entry.env` — threaded at both internal call sites
|
|
291
|
+
(`prepareAgentMcp` and `buildAgentMcpArgs`), so the claude `--mcp-config` file, the codex
|
|
292
|
+
inline `-c mcp_servers.specrails.env.*` overrides and the gemini cwd `.mcp.json` all carry
|
|
293
|
+
it automatically. `mergeSpecrailsIntoWorkspaceMcp` (Part A workspace wiring) deliberately
|
|
294
|
+
stays conversation-less.
|
|
295
|
+
2. `mcp-bridge` forwards the env as the `x-specrails-agent-conversation` header
|
|
296
|
+
(`agentForwardHeaders` in `bridge.ts`, alongside the tier/project forwards). The staged
|
|
297
|
+
bundle `src-tauri/binaries/specrails-mcp.js` must be regenerated via
|
|
298
|
+
`npm run build:mcp-bridge` whenever the bridge source changes — a stale bundle silently
|
|
299
|
+
drops the header (origin degrades to NULL with no error).
|
|
300
|
+
3. `registerTieredTool` (`server/mcp/tools/types.ts`) reads the header into the per-call
|
|
301
|
+
`ctx.originConversationId` next to the project pin (same per-call ctx-copy discipline;
|
|
302
|
+
malformed ⇒ `null`, never throws — the launch degrades to untagged).
|
|
303
|
+
4. `specrails_rails(launch)` (`server/mcp/tools/rails.ts`) adds
|
|
304
|
+
`originConversationId` + `originSurface:'agent-chat'` to the POST body when the ctx
|
|
305
|
+
carries an id (`apiCall` forwards no custom headers, so the id rides the JSON body).
|
|
306
|
+
External MCP clients (Claude Desktop, Cursor, …) spawn the bridge without any
|
|
307
|
+
`SPECRAILS_AGENT_*` env → no header → untagged launches, by design. Covered end-to-end by
|
|
308
|
+
`server/mcp/tools/rails-origin.test.ts` (header → ctx → body → route → persisted row →
|
|
309
|
+
settle fires `postPrDecisionCard` for that conversation).
|
|
310
|
+
|
|
311
|
+
## Decisions (D1–D11, condensed)
|
|
312
|
+
|
|
313
|
+
- **D1 — three extra columns** (`branches`, `loop_name`, `worktree_ids`) on migration 36:
|
|
314
|
+
deferred create-pr/discard must be reconstructible from the row; nothing survives in memory
|
|
315
|
+
after settle.
|
|
316
|
+
- **D2 — the on_review divert intercepts `onLoopRunFinished`**, not `onJobFinished`: isolated
|
|
317
|
+
rails settle per-run through `rail-isolated-launch`, and an opt-in
|
|
318
|
+
`ticketCompletionStatus`/`completedStatus` option keeps the default path byte-identical.
|
|
319
|
+
**Superseded (universal ask-first):** the divert now lives in BOTH chokepoints — the
|
|
320
|
+
`onLoopRunFinished` default derives from the flag when opts are absent, and `onJobFinished`
|
|
321
|
+
receives the spawn-captured flag from QueueManager — see "Ticket lifecycle" above. The opt-in
|
|
322
|
+
option shape survives unchanged; only its defaults moved from hardcoded `'done'` to
|
|
323
|
+
flag-derived.
|
|
324
|
+
- **D3 — state machine**: 0-succeeded settles auto-close to `discarded`; degraded drafts
|
|
325
|
+
(`pr_url` null) have no Publish, only retry/discard; `pr_state` records delivery degradation
|
|
326
|
+
independent of `decision`.
|
|
327
|
+
- **D4 — create-pr reconstructs deliverRailAsPr inputs from the row** and defensively deletes a
|
|
328
|
+
stale batch branch first (retry after a degraded delivery would die on "branch already
|
|
329
|
+
exists"); never the integration branch.
|
|
330
|
+
- **D5 — relaunch collision** = 409 `pr_decision_pending` only on the isolated PR path.
|
|
331
|
+
- **D6 — `rail.pr_delivered` retired**, replaced by the durable `rail.pr_state` + the
|
|
332
|
+
`GET /rails` `prDeliveries` hydration; `Map<railIndex, …>` on the client keyed to the newest
|
|
333
|
+
active row.
|
|
334
|
+
- **D7 — no SQL migration for the `'system'` role** (`agent_messages.role` is unconstrained
|
|
335
|
+
TEXT); the card is a system-role row updated in place; rails code reaches the manager via the
|
|
336
|
+
new `agent-chat-registry` (no circular import of `index.ts`).
|
|
337
|
+
- **D8 — origin rides the rails launch only**; the `jobs.ts /spawn` hop is dropped (QueueManager
|
|
338
|
+
jobs have no delivery row — the id would go nowhere). The full MCP auto-attach chain is
|
|
339
|
+
shipped — see "Origin link" above.
|
|
340
|
+
- **D9 — Jira**: two real bug fixes (sanitizeStatusMap whitelist, same-category walk) plus
|
|
341
|
+
inbound preservation and the three outbox hooks.
|
|
342
|
+
- **D10 — on_review everywhere**: server union + every client `Record<TicketStatus, …>` map,
|
|
343
|
+
board bucketing (ToDo tab), drag/launch guards, context-menu out-only, pill, i18n ×8.
|
|
344
|
+
- **D11 — premium decision UI**: disable-on-click reconciled to the broadcast, tooltips (base
|
|
345
|
+
branch, PR url), designed degraded/failed states, 409 → neutral "already resolved" toast;
|
|
346
|
+
English source strings, all 8 locales, locale-parity green.
|
|
347
|
+
|
|
348
|
+
## Kill-switch
|
|
349
|
+
|
|
350
|
+
`SPECRAILS_RAIL_DELIVER_PR` (default ON; `0`/`false`/`off` disables) — off means: no
|
|
351
|
+
`rail_pr_deliveries` rows, no `on_review` (completed jobs/runs promote straight to `done` with
|
|
352
|
+
the done-flavoured Jira `onJobOutcome` — byte-identical legacy at BOTH chokepoints), no
|
|
353
|
+
decision surfaces, `all`-scope rails fall back to the shared cwd, and the legacy local
|
|
354
|
+
merge-back runs — byte-identical pre-change behaviour. Capture grain: once per isolated LAUNCH
|
|
355
|
+
(`launchIsolatedRail` entry), once per JOB at spawn (`QueueManager._startJob`), once per
|
|
356
|
+
shared-cwd run SETTLE (`onLoopRunFinished` default) — a mid-flight flip only affects
|
|
357
|
+
lifecycles that start (or, for the settle-grain default, finish) after it.
|
|
358
|
+
PR mode also injects `SPECRAILS_GIT_AUTO=false` into rail spawns (loop-executors +
|
|
359
|
+
queue-manager); bundled specrails-core ≥ 4.11.0 honours it, so implement no longer self-ships.
|
|
360
|
+
|
|
361
|
+
## Deferred by this change
|
|
362
|
+
|
|
363
|
+
- A background merge poller for `pr_draft`/`pr_ready` rows (`poll-merge` is on-demand only).
|
|
364
|
+
- An origin hop for QueueManager `/spawn` jobs (no delivery row exists at job grain).
|
|
365
|
+
|
|
366
|
+
(The relocation per-run workspace overlay — formerly on this list — has SHIPPED; see
|
|
367
|
+
"Per-run worktree overlay" above.)
|
package/docs/mcp.md
CHANGED
|
@@ -38,7 +38,7 @@ reading one description. The tools are:
|
|
|
38
38
|
|---|---|
|
|
39
39
|
| `specrails_projects` | List / resolve projects; unregister (destructive) |
|
|
40
40
|
| `specrails_specs` | The spec/ticket backlog: list, get, create, update, delete, drafts, AI generate, AI-edit, Contract Refine, SMASH, per-ticket spend |
|
|
41
|
-
| `specrails_rails` | Assign tickets to a rail, configure it, and launch the pipeline |
|
|
41
|
+
| `specrails_rails` | Assign tickets to a rail, configure it, and launch the pipeline — rails are dynamic (`create_rail`, up to 12) and `launch_all` starts every ready rail in parallel (worktree-isolated) |
|
|
42
42
|
| `specrails_jobs` | Inspect, stream, and stop pipeline jobs |
|
|
43
43
|
| `specrails_chat` | Explore / sidebar chat conversations and turns |
|
|
44
44
|
| `specrails_agents` | Agent profiles and the agents catalog (Claude-only features) |
|
|
@@ -55,7 +55,7 @@ Beyond the built-ins, the **Loops** section (left sidebar, above the project lis
|
|
|
55
55
|
|
|
56
56
|
Each run is bounded by **max iterations**, a wall-clock **timeout**, and an optional **cost cap** (USD, checked between steps). The builder also has live validation, a dry-run preview (resolve every step's exact text without spawning), import/export to JSON, and copy/paste of steps across loops. **Fork** a built-in to start from a working graph, then **Publish** to make a loop selectable on any rail.
|
|
57
57
|
|
|
58
|
-
> Loop runs stream live in the Jobs view
|
|
58
|
+
> Loop runs stream live in the Jobs view like any rail job — and the Job Detail view groups a loop's log **by step**: a live chip map of the graph on top, one collapsible section per step below, with follow mode tracking the running step. Provider/model/effort are governed by the **rail**, not the loop's steps.
|
|
59
59
|
|
|
60
60
|
### Pipeline phases
|
|
61
61
|
|
|
@@ -76,6 +76,8 @@ Each phase is a specialised agent invoked by the rail's engine (Claude, Codex, o
|
|
|
76
76
|
|
|
77
77
|
In plain terms: the project's **agent profile** decides which AI agent handles each phase. The baseline trio (`sr-architect`, `sr-developer`, `sr-reviewer`) is always present; a profile's routing rules can add extra agents or swap which one runs a phase. The phase progress bar only renders when the command defines phases. For the full format, see [internals/profiles.md](internals/profiles.md).
|
|
78
78
|
|
|
79
|
+
**How the work is delivered (ask-first).** By default (`SPECRAILS_RAIL_DELIVER_PR` on — set `0`/`false`/`off` to disable) a rail runs in isolated git worktree(s) off your project's designated integration branch (*Settings → Integration branch*, defaults to the repo default branch). When the run finishes, **nothing is pushed and no PR is opened yet**: the work stays committed on its isolated branches, the specs move to a new **On Review** status, and the app asks you what to do — a persistent decision bar appears on the rail with **Create PR** and **Discard**. **Create PR** assembles the branches into **one draft pull request** — combined across every spec on the rail, with per-ticket commit history preserved; you can then **Approve** it (promote to ready-for-review) and later **Check merge** — once a human merges it in GitHub, the specs flip to Done. **Discard** cleans up the worktrees and branches and returns the specs to the backlog. specrails never merges and never modifies your working tree; a human owns the merge. Creating the PR needs `gh` authenticated + a remote; otherwise the work is still committed to a branch you can PR from yourself (the bar offers a retry). When the flow is disabled, the rail integrates its branches locally instead (the legacy behaviour) and no decision is asked. This is desktop-owned: specrails-core's `implement` is told to skip its own shipping (`SPECRAILS_GIT_AUTO=false`) so it never opens a second, uncoordinated PR.
|
|
80
|
+
|
|
79
81
|
### Freestyle
|
|
80
82
|
|
|
81
83
|
`Freestyle` (mode value `ultracode` on the API — its original name) is a Claude-only loop that skips the Architect → Developer → Reviewer → Ship pipeline entirely. Instead of orchestrating the agent chain, it hands Claude a configurable pre-prompt plus the full spec text and lets it work autonomously with its native tools.
|
|
@@ -84,7 +86,7 @@ In plain terms: the project's **agent profile** decides which AI agent handles e
|
|
|
84
86
|
- **Variable cost.** Because the run is open-ended, pressing Play opens a confirmation dialog before anything spawns.
|
|
85
87
|
- **Model picker.** A per-rail control lets you pick **Haiku / Sonnet / Opus** (default Sonnet) for the Freestyle run.
|
|
86
88
|
- **Claude only.** The Freestyle loop and its model picker are offered only when the rail's engine is Claude. Codex and Gemini rails can't run Freestyle, and agent profiles don't apply to Freestyle rails.
|
|
87
|
-
- **Interactive
|
|
89
|
+
- **Interactive by default.** Like every Claude job, a Freestyle run is a live session: chat with the running job and send follow-up prompts from the Job Detail composer. What's special about Freestyle is the ending — the session stays open until **you** click **Finalize** (other jobs wrap up on their own once a turn finishes with nothing queued). Can be disabled server-side via `SPECRAILS_INTERACTIVE_JOBS=false`.
|
|
88
90
|
|
|
89
91
|
You can customise the Freestyle pre-prompt per project on the [Settings page](customizing.md#freestyle-pre-prompt).
|
|
90
92
|
|
|
@@ -121,6 +123,8 @@ Two panels sit above the streaming log:
|
|
|
121
123
|
|
|
122
124
|
Below: the full streaming log with auto-scroll, search, and copy.
|
|
123
125
|
|
|
126
|
+
**Talk to the running job.** Every Claude job (and every Claude AI step in a loop run) is an interactive session by default: a chat composer sits at the bottom of the Job Detail page — and of the job modal in mission mode — so you can ask the running agent a question or steer it mid-run. Messages sent while the model is streaming queue up and run next; the job keeps following its plan. The composer shows a live `N turns · $X` line summed from each completed turn's real usage (still no estimates). Most jobs finish on their own the moment a turn completes with nothing queued — a subtle **Wrap up now** ends them early; Freestyle jobs instead wait for your explicit **Finalize**. During a loop run your messages reach the currently running AI step (between steps the composer shows a short waiting state, and **Settle this step** advances the loop). Codex and Gemini jobs run one-shot as before. Server kill switch: `SPECRAILS_INTERACTIVE_JOBS=false`.
|
|
127
|
+
|
|
124
128
|
### Cancelling a job
|
|
125
129
|
|
|
126
130
|
Click **Stop** on the rail header. The app sends `SIGTERM` to the subprocess, waits **5 s**, then `SIGKILL`.
|