specrails-desktop 2.36.0 → 2.42.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -247
- package/client/dist/assets/ActivityFeedPage-DoEMumQS.js +1 -0
- package/client/dist/assets/AgentBrowserCapture-DIh4K0gh.js +1 -0
- package/client/dist/assets/AgentModeAnalyticsPane-mbq4WEoO.js +2 -0
- package/client/dist/assets/AgentModeCodePane-CKh7zuA4.js +2 -0
- package/client/dist/assets/AgentModeJobsPane-BDokPiLJ.js +1 -0
- package/client/dist/assets/AgentsPage-BFVAZbBj.js +87 -0
- package/client/dist/assets/AnalyticsPage-3Y9LuWwz.js +1 -0
- package/client/dist/assets/CodePage-C9KyuV_C.js +3 -0
- package/client/dist/assets/DesktopAnalyticsPage-Bhi54bXQ.js +1 -0
- package/client/dist/assets/{DocsDialog-C76VdBJC.js → DocsDialog-Dj6mt4ga.js} +2 -2
- package/client/dist/assets/{DocsPage-ziMlj6B6.js → DocsPage-24yWglNI.js} +1 -1
- package/client/dist/assets/ExportDropdown-ophapHrT.js +1 -0
- package/client/dist/assets/InteractiveJobComposer-C1ucmxQh.js +19 -0
- package/client/dist/assets/JobDetailModal-DNWmgVHD.js +1 -0
- package/client/dist/assets/JobDetailPage-BcajZyuu.js +1 -0
- package/client/dist/assets/JobsPage-B9nTZw6e.js +1 -0
- package/client/dist/assets/LoopBuilderPage-Oc48iOFW.js +7 -0
- package/client/dist/assets/LoopPreviewModal-ae0Fr6SU.js +1 -0
- package/client/dist/assets/LoopsPage-CUEqzUBI.js +1 -0
- package/client/dist/assets/MinimizedChatsContext-Deg39peL.js +1 -0
- package/client/dist/assets/PluginsPage-C1xtARIx.js +2 -0
- package/client/dist/assets/ProjectSettingsDialog-JZzrXFBN.js +1 -0
- package/client/dist/assets/RepositoryDeliveries-CSDsiVUz.js +5 -0
- package/client/dist/assets/RepositoryScopeSelector-D-RCaknl.js +1 -0
- package/client/dist/assets/ReviewPacketPage-x5EfGTiL.js +1 -0
- package/client/dist/assets/TemplatePreviewModal-BSyuZxGq.js +1 -0
- package/client/dist/assets/TicketDetailModalContext-DqyF0so-.js +14 -0
- package/client/dist/assets/Trans-SnMX4MhW.js +1 -0
- package/client/dist/assets/agent-BdT0SB1D.js +1 -0
- package/client/dist/assets/agent-Bh9K7iEt.js +1 -0
- package/client/dist/assets/agent-C4ibdFk9.js +1 -0
- package/client/dist/assets/agent-CSFY22Zo.js +1 -0
- package/client/dist/assets/agent-DAnqxUn8.js +1 -0
- package/client/dist/assets/agent-DTQiu0Mi.js +1 -0
- package/client/dist/assets/agent-T54WuR_Y.js +1 -0
- package/client/dist/assets/agent-i75WDZOA.js +1 -0
- package/client/dist/assets/browser-05vRDg_y.js +1 -0
- package/client/dist/assets/browser-Bulb-cB1.js +1 -0
- package/client/dist/assets/browser-C7f-Jsg1.js +1 -0
- package/client/dist/assets/browser-CG0PE1j_.js +1 -0
- package/client/dist/assets/browser-CMzaqAjo.js +1 -0
- package/client/dist/assets/browser-DMajYdNX.js +1 -0
- package/client/dist/assets/browser-DxcOHrdP.js +1 -0
- package/client/dist/assets/browser-ObE7xVo3.js +1 -0
- package/client/dist/assets/builder-765NeYTp.js +1 -0
- package/client/dist/assets/builder-8MG3V6ea.js +1 -0
- package/client/dist/assets/builder-B-1UBs5K.js +1 -0
- package/client/dist/assets/builder-BTiGnPT0.js +1 -0
- package/client/dist/assets/builder-Cx9Rz-7u.js +1 -0
- package/client/dist/assets/builder-DKFMELBl.js +1 -0
- package/client/dist/assets/builder-OcmKrC0h.js +1 -0
- package/client/dist/assets/builder-P9qVBXFZ.js +1 -0
- package/client/dist/assets/{button-CJqFnUOL.js → button-DCBqEaZl.js} +1 -1
- package/client/dist/assets/{code-CkUuW4m9.js → code-B37GRg9C.js} +1 -1
- package/client/dist/assets/{code-B0O8-p8k.js → code-BBOEZbf9.js} +1 -1
- package/client/dist/assets/{code-B1VLZDhS.js → code-BRm-jcyx.js} +1 -1
- package/client/dist/assets/{code-Bpj4Ddml.js → code-CF7w62CR.js} +1 -1
- package/client/dist/assets/{code-BykBZ5-e.js → code-CLuvJt2r.js} +1 -1
- package/client/dist/assets/{code-B86IMAfz.js → code-D0RCm59f.js} +1 -1
- package/client/dist/assets/code-DaZ-ZwCT.js +1 -0
- package/client/dist/assets/{code-cAqaqMTx.js → code-iIHkGaCL.js} +1 -1
- package/client/dist/assets/commands-0XjAftla.js +1 -0
- package/client/dist/assets/commands-BAWSYHjQ.js +1 -0
- package/client/dist/assets/commands-BBwowgiE.js +1 -0
- package/client/dist/assets/commands-BacjIZLN.js +1 -0
- package/client/dist/assets/commands-Bs62IAZ3.js +1 -0
- package/client/dist/assets/commands-CLPdh-Hh.js +1 -0
- package/client/dist/assets/commands-DlbFzgrp.js +1 -0
- package/client/dist/assets/commands-LjPSsi5F.js +1 -0
- package/client/dist/assets/common-B5AZNYMH.js +1 -0
- package/client/dist/assets/common-BFZ0c_vN.js +1 -0
- package/client/dist/assets/common-BrlwEnL7.js +1 -0
- package/client/dist/assets/common-BttQx3z4.js +1 -0
- package/client/dist/assets/common-CM65k_-e.js +1 -0
- package/client/dist/assets/common-D4mvFFlu.js +1 -0
- package/client/dist/assets/common-TZ9Ny96S.js +1 -0
- package/client/dist/assets/common-nFpSF4GC.js +1 -0
- package/client/dist/assets/dashboard-B14uYXkG.js +1 -0
- package/client/dist/assets/dashboard-BK_mez-z.js +1 -0
- package/client/dist/assets/dashboard-BfBir_6o.js +1 -0
- package/client/dist/assets/dashboard-Bt0cCzeG.js +1 -0
- package/client/dist/assets/dashboard-BwkjxI6H.js +1 -0
- package/client/dist/assets/{dashboard-C8WOEiPu.js → dashboard-C3bDKf7s.js} +1 -1
- package/client/dist/assets/dashboard-CdvjGfog.js +1 -0
- package/client/dist/assets/dashboard-fRrP0Kv0.js +1 -0
- package/client/dist/assets/dialog-SRw01_QU.js +45 -0
- package/client/dist/assets/dist-js-CJ_2XX1Y.js +1 -0
- package/client/dist/assets/formatDistanceToNow-DSj5DprF.js +1 -0
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-YhD8rIEs.js +1 -0
- package/client/dist/assets/index-DwAmL7m5.css +2 -0
- package/client/dist/assets/index-EzrkUb8B.js +76 -0
- package/client/dist/assets/{jira-api-B1-MUehg.js → jira-api-CSCqGr-Q.js} +1 -1
- package/client/dist/assets/{jobs-CN_zv4Gr.js → jobs-B8rrzfyZ.js} +1 -1
- package/client/dist/assets/{jobs-DUlWSYq2.js → jobs-BS6RTurf.js} +1 -1
- package/client/dist/assets/{jobs-Bpks6doU.js → jobs-BTT0Bsks.js} +1 -1
- package/client/dist/assets/{jobs-Bgq-PZkC.js → jobs-CezU69AE.js} +1 -1
- package/client/dist/assets/{jobs-SwYS2M-B.js → jobs-ClFJae0s.js} +1 -1
- package/client/dist/assets/{jobs-BAls3bWq.js → jobs-DJSFIFVy.js} +1 -1
- package/client/dist/assets/{jobs-DhxKgWFq.js → jobs-DhgGr8vm.js} +1 -1
- package/client/dist/assets/{jobs-B_TeSQxb.js → jobs-DzMjUcaN.js} +1 -1
- package/client/dist/assets/mcp-6rMoZfEO.js +1 -0
- package/client/dist/assets/mcp-BD8sL5mP.js +1 -0
- package/client/dist/assets/mcp-BkcA3I5s.js +1 -0
- package/client/dist/assets/mcp-CCpSelOh.js +1 -0
- package/client/dist/assets/mcp-CUAN6ORK.js +1 -0
- package/client/dist/assets/mcp-CqbRxRTE.js +1 -0
- package/client/dist/assets/mcp-DP2YfVhO.js +1 -0
- package/client/dist/assets/mcp-DUVQamDz.js +1 -0
- package/client/dist/assets/narration-B-ynWTpn.js +1 -0
- package/client/dist/assets/narration-Bj_laZwg.js +1 -0
- package/client/dist/assets/narration-BxHpmMv_.js +1 -0
- package/client/dist/assets/narration-C1Px0-0j.js +1 -0
- package/client/dist/assets/narration-CAXhGbzM.js +1 -0
- package/client/dist/assets/narration-DQ1l_Kq6.js +1 -0
- package/client/dist/assets/narration-XISXwqZd.js +1 -0
- package/client/dist/assets/narration-kwzfglQo.js +1 -0
- package/client/dist/assets/nav-1-Hh2kOz.js +1 -0
- package/client/dist/assets/nav-B34QkESm.js +1 -0
- package/client/dist/assets/nav-Bap_UXAq.js +1 -0
- package/client/dist/assets/{nav-pYuXq7sf.js → nav-BwxXIB24.js} +1 -1
- package/client/dist/assets/nav-Ch-zHBG5.js +1 -0
- package/client/dist/assets/nav-CygC_WN-.js +1 -0
- package/client/dist/assets/{nav-iwjCg5FR.js → nav-KnnLQtOQ.js} +1 -1
- package/client/dist/assets/nav-m00uxYUG.js +1 -0
- package/client/dist/assets/packet-BQ2tXfJI.js +1 -0
- package/client/dist/assets/packet-BdpOJ1Cy.js +1 -0
- package/client/dist/assets/packet-C3Ievb9R.js +1 -0
- package/client/dist/assets/packet-C4zJIG0Y.js +1 -0
- package/client/dist/assets/packet-Cx-zRuWn.js +1 -0
- package/client/dist/assets/packet-DUTGX52M.js +1 -0
- package/client/dist/assets/packet-DhsKtUPB.js +1 -0
- package/client/dist/assets/packet-z3LJ8Zyy.js +1 -0
- package/client/dist/assets/project-repositories-DYhTvwQ1.js +1 -0
- package/client/dist/assets/provider-capabilities-B-wOHfLP.js +1 -0
- package/client/dist/assets/settings-BBt2xtDQ.js +1 -0
- package/client/dist/assets/settings-BJB9RKJj.js +1 -0
- package/client/dist/assets/settings-CHwQR2rB.js +1 -0
- package/client/dist/assets/settings-CrMi3kSi.js +1 -0
- package/client/dist/assets/settings-DKyhDGD1.js +1 -0
- package/client/dist/assets/settings-Deupji9c.js +1 -0
- package/client/dist/assets/settings-DqRMmwAM.js +1 -0
- package/client/dist/assets/settings-J4rj6vo-.js +1 -0
- package/client/dist/assets/setup-2xGgu4Sk.js +1 -0
- package/client/dist/assets/setup-Ba11l2JA.js +1 -0
- package/client/dist/assets/setup-BzW4kMok.js +1 -0
- package/client/dist/assets/setup-COzwYhkJ.js +1 -0
- package/client/dist/assets/setup-CRVULhtF.js +1 -0
- package/client/dist/assets/setup-DgvlxwpE.js +1 -0
- package/client/dist/assets/setup-Dw_wYeEY.js +1 -0
- package/client/dist/assets/setup-ZPtEeJPW.js +1 -0
- package/client/dist/assets/spending-BqbdPm_4.js +1 -0
- package/client/dist/assets/square-Ci-PFcFe.js +1 -0
- package/client/dist/assets/{terminal-BFRZnMPP.js → terminal-BAzpHtpY.js} +1 -1
- package/client/dist/assets/{terminal-IahE4LW9.js → terminal-C7dHeR3x.js} +1 -1
- package/client/dist/assets/{terminal-tITa81iz.js → terminal-CMla5Qsz.js} +1 -1
- package/client/dist/assets/{terminal-BZiIu3rf.js → terminal-CdNXH-n9.js} +1 -1
- package/client/dist/assets/{terminal-ScjyXNxQ.js → terminal-Cw5bZsmV.js} +1 -1
- package/client/dist/assets/{terminal-C2NAd7BW.js → terminal-DFUP4eNv.js} +1 -1
- package/client/dist/assets/{terminal-d7GadXbN.js → terminal-DGqljeK_.js} +1 -1
- package/client/dist/assets/{terminal-QpXZU2Bn.js → terminal-cU70NodO.js} +1 -1
- package/client/dist/assets/useDesktop-RSMTyy7V.js +1 -0
- package/client/dist/assets/useSharedWebSocket-BOdS5_Iz.js +2 -0
- package/client/dist/index.html +34 -35
- package/docs/README.md +3 -0
- package/docs/agent-live-steering.md +57 -0
- package/docs/ci-cd.md +57 -0
- package/docs/code-explorer.md +48 -0
- package/docs/codex.md +12 -1
- package/docs/features/detachable-mission-windows.md +59 -0
- package/docs/guide/de/integrations/5-mcp-server.md +13 -9
- package/docs/guide/de/integrations/6-agent-chat.md +1 -0
- package/docs/guide/en/integrations/5-mcp-server.md +13 -9
- package/docs/guide/en/integrations/6-agent-chat.md +1 -0
- package/docs/guide/es/integrations/5-mcp-server.md +13 -9
- package/docs/guide/es/integrations/6-agent-chat.md +1 -0
- package/docs/guide/fr/integrations/5-mcp-server.md +13 -9
- package/docs/guide/fr/integrations/6-agent-chat.md +1 -0
- package/docs/guide/it/integrations/5-mcp-server.md +13 -9
- package/docs/guide/it/integrations/6-agent-chat.md +1 -0
- package/docs/guide/ja/integrations/5-mcp-server.md +13 -9
- package/docs/guide/ja/integrations/6-agent-chat.md +1 -0
- package/docs/guide/pt/integrations/5-mcp-server.md +13 -9
- package/docs/guide/pt/integrations/6-agent-chat.md +1 -0
- package/docs/guide/zh/integrations/5-mcp-server.md +13 -9
- package/docs/guide/zh/integrations/6-agent-chat.md +1 -0
- package/docs/internals/README.md +1 -0
- package/docs/internals/browser-capture-performance.md +55 -3
- package/docs/internals/browser-login-popups.md +45 -0
- package/docs/internals/browser-native-retina-audit.md +39 -0
- package/docs/internals/ci-cd-audit.md +39 -0
- package/docs/internals/core-runtime-updates.md +68 -0
- package/docs/internals/embedded-browser-native-webview-evaluation.md +2 -0
- package/docs/internals/implementation-reliability-audit.md +93 -0
- package/docs/internals/interactive-jobs.md +110 -6
- package/docs/internals/mcp-mission-audit.md +76 -0
- package/docs/internals/project-builder.md +404 -42
- package/docs/internals/safe-pr-review-flow.md +52 -10
- package/docs/internals/startup-recovery-audit.md +58 -0
- package/docs/mcp.md +74 -41
- package/docs/mission-processes.md +59 -0
- package/docs/multi-repo-projects.md +51 -0
- package/docs/platforms/windows-parity.md +70 -0
- package/docs/platforms/windows.md +13 -11
- package/docs/running-pipelines.md +14 -0
- package/mcp-bridge/dist/specrails-mcp.js +7186 -0
- package/package.json +9 -4
- package/server/dist/agent-chat-manager.js +537 -68
- package/server/dist/agent-chat-router.js +87 -6
- package/server/dist/agent-context-resolver.js +129 -25
- package/server/dist/agent-defaults.js +19 -11
- package/server/dist/agent-input-store.js +206 -0
- package/server/dist/agent-mcp-config.js +54 -15
- package/server/dist/agent-operator-prompt.js +255 -65
- package/server/dist/agent-spec-framing.js +202 -0
- package/server/dist/agent-steering.js +218 -0
- package/server/dist/agent-store.js +153 -0
- package/server/dist/api-not-found.js +8 -0
- package/server/dist/background-process-control.js +164 -0
- package/server/dist/background-process-service.js +61 -0
- package/server/dist/background-process-store.js +242 -0
- package/server/dist/background-windows-bootstrap.js +238 -0
- package/server/dist/blueprint-chat-manager.js +476 -62
- package/server/dist/blueprint-commit.js +21 -1
- package/server/dist/blueprint-draft-parser.js +122 -17
- package/server/dist/blueprint-generation.js +238 -0
- package/server/dist/blueprint-operator-prompt.js +91 -63
- package/server/dist/blueprint-router.js +55 -3
- package/server/dist/blueprint-spec-fixtures.js +85 -0
- package/server/dist/blueprint-spec-quality.js +57 -16
- package/server/dist/blueprint-store.js +92 -1
- package/server/dist/browser-capture-manager.js +86 -30
- package/server/dist/browser-playwright.js +168 -45
- package/server/dist/browser-viewport.js +26 -0
- package/server/dist/chat-manager.js +23 -15
- package/server/dist/chromium-archive.cjs +83 -0
- package/server/dist/chromium-resolver.js +72 -64
- package/server/dist/code-activity.js +145 -0
- package/server/dist/code-explorer-router.js +714 -114
- package/server/dist/core-compat.js +28 -1
- package/server/dist/core-execution.js +111 -0
- package/server/dist/core-package.js +4 -16
- package/server/dist/core-runtime.js +202 -0
- package/server/dist/core-update-manager.js +161 -60
- package/server/dist/core-update-state.js +29 -0
- package/server/dist/db.js +66 -35
- package/server/dist/delivery-evidence.js +142 -39
- package/server/dist/desktop-db.js +239 -43
- package/server/dist/desktop-router.js +109 -9
- package/server/dist/dev-ports.js +8 -3
- package/server/dist/file-provenance.js +34 -22
- package/server/dist/file-story-manager.js +62 -64
- package/server/dist/file-story.js +118 -35
- package/server/dist/file-summary-generator.js +46 -5
- package/server/dist/file-summary-manager.js +355 -106
- package/server/dist/framework-manager.js +98 -110
- package/server/dist/framework-reseed.js +76 -10
- package/server/dist/git-diagnostics.js +2 -2
- package/server/dist/headroom-manager.js +38 -3
- package/server/dist/host-control.js +52 -0
- package/server/dist/index.js +43 -2
- package/server/dist/interactive-job-session.js +149 -16
- package/server/dist/internal-api.js +48 -0
- package/server/dist/jira/jira-materializer.js +1 -0
- package/server/dist/json-tolerant.js +174 -0
- package/server/dist/legacy-migration.js +4 -2
- package/server/dist/loop-command-catalog.js +83 -21
- package/server/dist/loop-constants.js +6 -1
- package/server/dist/loop-decider.js +11 -1
- package/server/dist/loop-executors.js +194 -45
- package/server/dist/loop-factory.js +11 -4
- package/server/dist/loop-graph.js +90 -4
- package/server/dist/loop-run-manager.js +301 -69
- package/server/dist/loop-shell-invocation.js +21 -0
- package/server/dist/loop-step-idle.js +55 -0
- package/server/dist/loop-templates.js +31 -7
- package/server/dist/mcp/agent-capability.js +37 -4
- package/server/dist/mcp/guide.js +149 -36
- package/server/dist/mcp/mcp-admin-router.js +20 -4
- package/server/dist/mcp/mcp-server.js +89 -43
- package/server/dist/mcp/mcp-tiers.js +6 -5
- package/server/dist/mcp/mcp-token.js +3 -1
- package/server/dist/mcp/resources.js +5 -4
- package/server/dist/mcp/tools/catalog.js +4 -0
- package/server/dist/mcp/tools/code.js +125 -14
- package/server/dist/mcp/tools/context.js +153 -0
- package/server/dist/mcp/tools/git.js +15 -5
- package/server/dist/mcp/tools/jobs.js +84 -71
- package/server/dist/mcp/tools/loops.js +17 -6
- package/server/dist/mcp/tools/meta.js +74 -27
- package/server/dist/mcp/tools/mission.js +29 -0
- package/server/dist/mcp/tools/projects.js +22 -6
- package/server/dist/mcp/tools/rails.js +48 -11
- package/server/dist/mcp/tools/specs.js +86 -14
- package/server/dist/mcp/tools/support.js +1 -1
- package/server/dist/mcp/tools/types.js +117 -43
- package/server/dist/mcp/tools/watch.js +144 -51
- package/server/dist/milestone-chain-store.js +164 -0
- package/server/dist/milestone-chain.js +487 -0
- package/server/dist/milestone-progress.js +348 -0
- package/server/dist/mobile/mobile-devices.js +10 -7
- package/server/dist/mobile/mobile-gateway.js +2 -0
- package/server/dist/mobile/mobile-missions.js +214 -0
- package/server/dist/mobile/mobile-redact.js +17 -3
- package/server/dist/mobile/mobile-router.js +46 -4
- package/server/dist/mobile/mobile-ws.js +49 -4
- package/server/dist/multi-repo-bases.js +56 -0
- package/server/dist/multi-repo-checkout.js +101 -0
- package/server/dist/multi-repo-delivery.js +100 -0
- package/server/dist/multi-repo-execution-store.js +65 -0
- package/server/dist/multi-repo-execution.js +453 -0
- package/server/dist/offline-assemble.js +10 -8
- package/server/dist/openspec-runtime-plugin-commands.json +18 -0
- package/server/dist/openspec-runtime-plugin.js +120 -0
- package/server/dist/plugins/codex-spawn.js +49 -0
- package/server/dist/plugins/serena/manifest.js +2 -2
- package/server/dist/plugins/serena/templates/instructions.md +16 -0
- package/server/dist/pr-publisher.js +1 -1
- package/server/dist/profiles-router.js +3 -18
- package/server/dist/project-code-discovery.js +142 -0
- package/server/dist/project-git.js +19 -21
- package/server/dist/project-registry.js +272 -20
- package/server/dist/project-repositories.js +157 -0
- package/server/dist/project-repository-provenance.js +31 -0
- package/server/dist/project-router-background-processes.js +105 -0
- package/server/dist/project-router-git.js +75 -16
- package/server/dist/project-router-jobs.js +2 -126
- package/server/dist/project-router-loop-runs.js +72 -2
- package/server/dist/project-router-tickets.js +53 -8
- package/server/dist/project-router.js +239 -38
- package/server/dist/provider-detection.js +18 -6
- package/server/dist/provider-limit.js +64 -0
- package/server/dist/providers/claude-adapter.js +26 -1
- package/server/dist/providers/claude-background-tasks.js +18 -0
- package/server/dist/providers/claude-live-session.js +383 -0
- package/server/dist/providers/codex-adapter.js +19 -0
- package/server/dist/providers/codex-live-session.js +545 -0
- package/server/dist/providers/gemini-adapter.js +1 -0
- package/server/dist/providers/live-session-types.js +12 -0
- package/server/dist/providers/live-session.js +13 -0
- package/server/dist/providers/terminal-result.js +24 -0
- package/server/dist/queue-manager.js +2 -0
- package/server/dist/rail-isolated-launch.js +141 -16
- package/server/dist/rail-pr-decision.js +364 -99
- package/server/dist/rail-pr-store.js +24 -10
- package/server/dist/rail-worktree-release.js +34 -2
- package/server/dist/rail-worktrees-store.js +4 -4
- package/server/dist/rails-router.js +249 -55
- package/server/dist/repo-lock.js +92 -17
- package/server/dist/review-packet.js +23 -13
- package/server/dist/schemas/file-summary.v1.json +59 -59
- package/server/dist/schemas/profile.v1.json +137 -137
- package/server/dist/setup-manager.js +52 -8
- package/server/dist/shell-integration/bash-shim.bash +45 -0
- package/server/dist/shell-integration/fish-shim.fish +36 -0
- package/server/dist/shell-integration/powershell-shim.ps1 +48 -0
- package/server/dist/shell-integration/zsh-shim.zsh +47 -0
- package/server/dist/smash-runner.js +1 -0
- package/server/dist/spawn-lifecycle.js +44 -27
- package/server/dist/spec-contract-prompt.js +143 -0
- package/server/dist/spec-draft-parser.js +6 -1
- package/server/dist/spec-models.js +1 -0
- package/server/dist/stuck-run-detector.js +1 -0
- package/server/dist/terminal-manager.js +21 -1
- package/server/dist/terminal-shell-integration.js +4 -1
- package/server/dist/transient-children.js +619 -230
- package/server/dist/util/cli-prompt.js +78 -5
- package/server/dist/util/sqlite-migrations.js +20 -0
- package/server/dist/util/win-spawn.js +18 -3
- package/server/dist/util/windows-provider-shell.js +29 -0
- package/server/dist/verification-sentinel.js +14 -0
- package/server/dist/vitest-setup.js +2 -0
- package/server/dist/windows-job-supervisor.js +133 -0
- package/server/dist/workspace-manager.js +9 -30
- package/server/dist/worktree-manager.js +17 -2
- package/server/dist/worktree-overlay.js +3 -1
- package/client/dist/assets/ActivityFeedPage-tAQcWs1R.js +0 -1
- package/client/dist/assets/AgentBrowserCapture-BX8BNae5.js +0 -1
- package/client/dist/assets/AgentModeAnalyticsPane-BVAqCL0K.js +0 -2
- package/client/dist/assets/AgentModeCodePane-9XfqQc9c.js +0 -2
- package/client/dist/assets/AgentModeJobsPane-BCjLsPhc.js +0 -1
- package/client/dist/assets/AgentsPage-C8J_42sm.js +0 -87
- package/client/dist/assets/AnalyticsPage-BtQuyfJm.js +0 -1
- package/client/dist/assets/CodePage-BZ2MwdCu.js +0 -2
- package/client/dist/assets/DesktopAnalyticsPage-Bh_29V4g.js +0 -1
- package/client/dist/assets/ExportDropdown-BrtfWzEG.js +0 -1
- package/client/dist/assets/InteractiveJobComposer-BCZiSfzc.js +0 -19
- package/client/dist/assets/JobDetailModal-NAJmuYIT.js +0 -1
- package/client/dist/assets/JobDetailPage-fE0ZycUX.js +0 -1
- package/client/dist/assets/JobsPage-z5M_HVJG.js +0 -1
- package/client/dist/assets/LoopBuilderPage-j1FQS47c.js +0 -7
- package/client/dist/assets/LoopPreviewModal-DhDJjdCe.js +0 -1
- package/client/dist/assets/LoopsPage-Ll7zORZb.js +0 -1
- package/client/dist/assets/MinimizedChatsContext-Bd3OqR_S.js +0 -1
- package/client/dist/assets/PluginsPage-DN4kGvJt.js +0 -2
- package/client/dist/assets/ProjectSettingsDialog-OgsgxjzF.js +0 -1
- package/client/dist/assets/ReviewPacketPage-DFog4sXn.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-L2XxqiOD.js +0 -1
- package/client/dist/assets/TicketDetailModal-CsF-AWZX.js +0 -14
- package/client/dist/assets/Trans-Bsz9_gyq.js +0 -1
- package/client/dist/assets/agent-BQgKv_2F.js +0 -1
- package/client/dist/assets/agent-C1NRDJqL.js +0 -1
- package/client/dist/assets/agent-CLNleiy6.js +0 -1
- package/client/dist/assets/agent-CmceArkQ.js +0 -1
- package/client/dist/assets/agent-D3UxQ3SR.js +0 -1
- package/client/dist/assets/agent-DB1JeE64.js +0 -1
- package/client/dist/assets/agent-DXkHcQ-D.js +0 -1
- package/client/dist/assets/agent-DjJJJ2M8.js +0 -1
- package/client/dist/assets/auth-D_5bQv5W.js +0 -1
- package/client/dist/assets/ban-E4EaZe3a.js +0 -1
- package/client/dist/assets/bot-DzuuuC5R.js +0 -1
- package/client/dist/assets/browser-BgqHDMXP.js +0 -1
- package/client/dist/assets/browser-CsKJtrpv.js +0 -1
- package/client/dist/assets/browser-Cu58EpZU.js +0 -1
- package/client/dist/assets/browser-CvXOJm-j.js +0 -1
- package/client/dist/assets/browser-DOrFh1c7.js +0 -1
- package/client/dist/assets/browser-DQv_Jo7x.js +0 -1
- package/client/dist/assets/browser-LPgxvJu2.js +0 -1
- package/client/dist/assets/browser-eL-3MIEI.js +0 -1
- package/client/dist/assets/builder-0IWtosUm.js +0 -1
- package/client/dist/assets/builder-Bf2N6XWn.js +0 -1
- package/client/dist/assets/builder-BnqaaBkT.js +0 -1
- package/client/dist/assets/builder-BxxfGgAO.js +0 -1
- package/client/dist/assets/builder-C5IIgWsq.js +0 -1
- package/client/dist/assets/builder-CHuahItu.js +0 -1
- package/client/dist/assets/builder-CjWosXL_.js +0 -1
- package/client/dist/assets/builder-CpCIOoKj.js +0 -1
- package/client/dist/assets/code-CHPkOkDS.js +0 -1
- package/client/dist/assets/commands-6tYQih5m.js +0 -1
- package/client/dist/assets/commands-BK2QinXN.js +0 -1
- package/client/dist/assets/commands-C2Nca76h.js +0 -1
- package/client/dist/assets/commands-CKdLihNX.js +0 -1
- package/client/dist/assets/commands-CYIBTAlc.js +0 -1
- package/client/dist/assets/commands-CjUtYJIM.js +0 -1
- package/client/dist/assets/commands-Cq_u_8y9.js +0 -1
- package/client/dist/assets/commands-D_ZHYQug.js +0 -1
- package/client/dist/assets/common-6MLbD-jM.js +0 -1
- package/client/dist/assets/common-BKGEu4rm.js +0 -1
- package/client/dist/assets/common-BNbnv8cE.js +0 -1
- package/client/dist/assets/common-BqGWtDbt.js +0 -1
- package/client/dist/assets/common-DBtTzeYm.js +0 -1
- package/client/dist/assets/common-DEW3Nr8n.js +0 -1
- package/client/dist/assets/common-DHsv9N5d.js +0 -1
- package/client/dist/assets/common-mkrEcW-Y.js +0 -1
- package/client/dist/assets/dashboard-B9GhC5ku.js +0 -1
- package/client/dist/assets/dashboard-CBnv6zOI.js +0 -1
- package/client/dist/assets/dashboard-CaP0fU87.js +0 -1
- package/client/dist/assets/dashboard-D4ZZ4x84.js +0 -1
- package/client/dist/assets/dashboard-DmuTQBX8.js +0 -1
- package/client/dist/assets/dashboard-DynLYj3d.js +0 -1
- package/client/dist/assets/dashboard-zj4gGFJ1.js +0 -1
- package/client/dist/assets/dialog-CdWCb02j.js +0 -45
- package/client/dist/assets/dist-bVqfYmby.js +0 -1
- package/client/dist/assets/dist-js-CWeUdf5Z.js +0 -1
- package/client/dist/assets/formatDistanceToNow-DQCvMgUc.js +0 -1
- package/client/dist/assets/getTimezoneOffsetInMilliseconds-C16cxSe1.js +0 -1
- package/client/dist/assets/git-refresh-wTW0rO0Z.js +0 -1
- package/client/dist/assets/i18n-hnX2DPmo.js +0 -2
- package/client/dist/assets/index-DIhMEAVw.js +0 -66
- package/client/dist/assets/index-DwygcU7s.css +0 -2
- package/client/dist/assets/mcp-B8X8wBLu.js +0 -1
- package/client/dist/assets/mcp-C2AojZZN.js +0 -1
- package/client/dist/assets/mcp-D8BT78_L.js +0 -1
- package/client/dist/assets/mcp-Df5RWBNk.js +0 -1
- package/client/dist/assets/mcp-Dj7BgMQW.js +0 -1
- package/client/dist/assets/mcp-Q7iT7rcz.js +0 -1
- package/client/dist/assets/mcp-YlvNvJbW.js +0 -1
- package/client/dist/assets/mcp-mKFpTSRb.js +0 -1
- package/client/dist/assets/narration-4Z2VUhZw.js +0 -1
- package/client/dist/assets/narration-BGuiEDj3.js +0 -1
- package/client/dist/assets/narration-BuSoqRmv.js +0 -1
- package/client/dist/assets/narration-CB9t29fy.js +0 -1
- package/client/dist/assets/narration-CU3x8FHD.js +0 -1
- package/client/dist/assets/narration-CWeXhfP5.js +0 -1
- package/client/dist/assets/narration-DRaDnhT5.js +0 -1
- package/client/dist/assets/narration-DtEbQgCw.js +0 -1
- package/client/dist/assets/nav-ApJVg3xu.js +0 -1
- package/client/dist/assets/nav-BKNky1Bg.js +0 -1
- package/client/dist/assets/nav-C6vWWKYx.js +0 -1
- package/client/dist/assets/nav-CXJ6Aw89.js +0 -1
- package/client/dist/assets/nav-CsmFBIDf.js +0 -1
- package/client/dist/assets/nav-DjkmQJjd.js +0 -1
- package/client/dist/assets/packet-B1IxaL5f.js +0 -1
- package/client/dist/assets/packet-Bh5kkbiB.js +0 -1
- package/client/dist/assets/packet-By8fqYxW.js +0 -1
- package/client/dist/assets/packet-CZdvA44E.js +0 -1
- package/client/dist/assets/packet-CrjHRQCP.js +0 -1
- package/client/dist/assets/packet-Dwi2pTtx.js +0 -1
- package/client/dist/assets/packet-_-ZIa0IR.js +0 -1
- package/client/dist/assets/packet-n0W6E1Hn.js +0 -1
- package/client/dist/assets/play-DNlrawbS.js +0 -1
- package/client/dist/assets/provider-capabilities-Doej9lfa.js +0 -1
- package/client/dist/assets/settings-Bd0x4TBa.js +0 -1
- package/client/dist/assets/settings-C1-7cXzC.js +0 -1
- package/client/dist/assets/settings-CAFaT38b.js +0 -1
- package/client/dist/assets/settings-Ct3v1nW2.js +0 -1
- package/client/dist/assets/settings-DHh7_IF5.js +0 -1
- package/client/dist/assets/settings-DQXAmdcv.js +0 -1
- package/client/dist/assets/settings-guzlhpup.js +0 -1
- package/client/dist/assets/settings-sZfTPMEH.js +0 -1
- package/client/dist/assets/setup-3jWaoVUO.js +0 -1
- package/client/dist/assets/setup-BjgRneb2.js +0 -1
- package/client/dist/assets/setup-BzFIjv-f.js +0 -1
- package/client/dist/assets/setup-C4VfQsxE.js +0 -1
- package/client/dist/assets/setup-DfUkpDbN.js +0 -1
- package/client/dist/assets/setup-ECe90Pmu.js +0 -1
- package/client/dist/assets/setup-dlqC4Jmm.js +0 -1
- package/client/dist/assets/setup-jwfLMiM2.js +0 -1
- package/client/dist/assets/spending-EC9xqio-.js +0 -1
- package/client/dist/assets/useDesktop-BQVt8lFd.js +0 -1
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRepositoryExecutionReferences = exports.migrateMultiRepoExecution = void 0;
|
|
4
|
+
exports.listRepositoryDeliveries = listRepositoryDeliveries;
|
|
5
|
+
exports.refreshRepositoryDeliveryGroup = refreshRepositoryDeliveryGroup;
|
|
6
|
+
exports.launchMultiRepositoryRail = launchMultiRepositoryRail;
|
|
7
|
+
const ids_1 = require("./ids");
|
|
8
|
+
const db_1 = require("./db");
|
|
9
|
+
const integration_branch_1 = require("./integration-branch");
|
|
10
|
+
const project_repositories_1 = require("./project-repositories");
|
|
11
|
+
const repo_lock_1 = require("./repo-lock");
|
|
12
|
+
const worktree_manager_1 = require("./worktree-manager");
|
|
13
|
+
const workspace_resolution_1 = require("./workspace-resolution");
|
|
14
|
+
const rail_isolated_launch_1 = require("./rail-isolated-launch");
|
|
15
|
+
const rail_pr_store_1 = require("./rail-pr-store");
|
|
16
|
+
const agent_chat_registry_1 = require("./agent-chat-registry");
|
|
17
|
+
const rail_pr_ticket_effects_1 = require("./rail-pr-ticket-effects");
|
|
18
|
+
const multi_repo_execution_store_1 = require("./multi-repo-execution-store");
|
|
19
|
+
var multi_repo_execution_store_2 = require("./multi-repo-execution-store");
|
|
20
|
+
Object.defineProperty(exports, "migrateMultiRepoExecution", { enumerable: true, get: function () { return multi_repo_execution_store_2.migrateMultiRepoExecution; } });
|
|
21
|
+
Object.defineProperty(exports, "getRepositoryExecutionReferences", { enumerable: true, get: function () { return multi_repo_execution_store_2.getRepositoryExecutionReferences; } });
|
|
22
|
+
function listRepositoryDeliveries(db, parentId) {
|
|
23
|
+
return db.prepare('SELECT * FROM rail_pr_deliveries WHERE parent_delivery_id = ? ORDER BY rowid').all(parentId);
|
|
24
|
+
}
|
|
25
|
+
function repositorySnapshot(row, manifest) {
|
|
26
|
+
const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
|
|
27
|
+
const repo = manifest.repositories.find((entry) => entry.repositoryId === row.repository_id);
|
|
28
|
+
return {
|
|
29
|
+
repositoryId: row.repository_id, name: repo?.name ?? row.repository_id, path: row.repository_path,
|
|
30
|
+
deliveryId: row.id, baseBranch: row.base_branch, integrationBranch: repo?.integrationBranch ?? row.base_branch,
|
|
31
|
+
branch: row.branch ?? (snap.branches.length === 1 ? snap.branches[0].branch : null),
|
|
32
|
+
deliverySha: row.delivery_sha ?? (snap.branches.length === 1 ? snap.branches[0].finalSha ?? null : null),
|
|
33
|
+
decision: row.decision, implementationOutcome: snap.implementationOutcome, deliveryOutcome: snap.deliveryOutcome,
|
|
34
|
+
statusCode: snap.statusCode, statusDetail: snap.statusDetail, prUrl: row.pr_url, prNumber: row.pr_number,
|
|
35
|
+
worktreeIds: snap.worktreeIds, runIds: snap.runIds,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Projection is durable: late clients receive the same group as live cards. */
|
|
39
|
+
function refreshRepositoryDeliveryGroup(db, parentId, opts = {}) {
|
|
40
|
+
const parent = (0, rail_pr_store_1.getPrDelivery)(db, parentId);
|
|
41
|
+
const manifest = (0, multi_repo_execution_store_1.readExecutionManifest)(parent?.execution_manifest);
|
|
42
|
+
if (!parent || !manifest || ['merged', 'completed', 'discarded', 'superseded'].includes(parent.decision))
|
|
43
|
+
return parent;
|
|
44
|
+
const children = listRepositoryDeliveries(db, parentId);
|
|
45
|
+
if (opts.startup && children.length < manifest.selectedRepositoryIds.length) {
|
|
46
|
+
(0, rail_pr_store_1.transitionDecision)(db, parent.id, parent.decision, 'pr_failed', {
|
|
47
|
+
implementationOutcome: 'unknown', deliveryOutcome: 'blocked', statusCode: 'settlement_interrupted',
|
|
48
|
+
statusDetail: 'The previous process stopped before all repository worktrees were allocated. Existing work was preserved; revise the group to retry.',
|
|
49
|
+
repositoryDeliveries: children.map((row) => repositorySnapshot(row, manifest)),
|
|
50
|
+
});
|
|
51
|
+
return (0, rail_pr_store_1.getPrDelivery)(db, parentId);
|
|
52
|
+
}
|
|
53
|
+
if (children.length === 0)
|
|
54
|
+
return parent;
|
|
55
|
+
const snapshots = children.map((row) => repositorySnapshot(row, manifest));
|
|
56
|
+
const finished = children.length === manifest.selectedRepositoryIds.length && children.every((row) => row.decision !== 'building');
|
|
57
|
+
const accepted = children.filter((row) => row.decision === 'merged' || row.decision === 'completed');
|
|
58
|
+
const active = children.filter((row) => row.decision !== 'no_changes' && row.decision !== 'merged' && row.decision !== 'completed');
|
|
59
|
+
let decision = parent.decision;
|
|
60
|
+
const patch = {
|
|
61
|
+
repositoryDeliveries: snapshots,
|
|
62
|
+
runIds: [...new Set(snapshots.flatMap((row) => row.runIds))],
|
|
63
|
+
worktreeIds: [...new Set(snapshots.flatMap((row) => row.worktreeIds))],
|
|
64
|
+
branches: children.flatMap((row) => (0, rail_pr_store_1.toPrDeliverySnapshot)(row).branches.map((unit) => ({ ...unit, repositoryId: row.repository_id }))),
|
|
65
|
+
cleanupWarnings: children.flatMap((row) => (0, rail_pr_store_1.toPrDeliverySnapshot)(row).cleanupWarnings),
|
|
66
|
+
safetyArchives: children.flatMap((row) => (0, rail_pr_store_1.toPrDeliverySnapshot)(row).safetyArchives),
|
|
67
|
+
};
|
|
68
|
+
if (finished) {
|
|
69
|
+
const successes = children.filter((row) => row.implementation_outcome === 'succeeded').length;
|
|
70
|
+
patch.implementationOutcome = successes === children.length ? 'succeeded' : successes ? 'partially_succeeded' : 'failed';
|
|
71
|
+
const completeAcceptance = children.every((row) => row.implementation_outcome === 'succeeded' && (0, rail_pr_store_1.toPrDeliverySnapshot)(row).branches.every((unit) => unit.implementationOutcome !== 'failed' && unit.deliveryOutcome !== 'blocked' && unit.deliveryOutcome !== 'not_started'));
|
|
72
|
+
if (accepted.length === children.length && completeAcceptance) {
|
|
73
|
+
decision = children.some((row) => row.decision === 'merged') ? 'merged' : 'completed';
|
|
74
|
+
patch.deliveryOutcome = 'delivered';
|
|
75
|
+
patch.statusCode = 'merged';
|
|
76
|
+
patch.statusDetail = null;
|
|
77
|
+
}
|
|
78
|
+
else if (accepted.length === children.length) {
|
|
79
|
+
decision = 'pr_failed';
|
|
80
|
+
patch.deliveryOutcome = 'blocked';
|
|
81
|
+
patch.statusCode = 'partial_delivery';
|
|
82
|
+
patch.statusDetail = 'Only part of the shared implementation was delivered. Revise the group to complete the outstanding scope.';
|
|
83
|
+
}
|
|
84
|
+
else if (children.every((row) => row.decision === 'discarded')) {
|
|
85
|
+
decision = 'discarded';
|
|
86
|
+
patch.deliveryOutcome = 'not_started';
|
|
87
|
+
patch.statusCode = 'discarded';
|
|
88
|
+
}
|
|
89
|
+
else if (children.every((row) => row.decision === 'no_changes')) {
|
|
90
|
+
decision = 'no_changes';
|
|
91
|
+
patch.deliveryOutcome = 'no_changes';
|
|
92
|
+
patch.statusCode = 'no_changes';
|
|
93
|
+
}
|
|
94
|
+
else if (children.some((row) => row.decision === 'implementation_failed')) {
|
|
95
|
+
decision = 'implementation_failed';
|
|
96
|
+
patch.deliveryOutcome = 'blocked';
|
|
97
|
+
patch.statusCode = 'implementation_failed';
|
|
98
|
+
}
|
|
99
|
+
else if (children.some((row) => row.decision === 'pr_failed')) {
|
|
100
|
+
decision = 'pr_failed';
|
|
101
|
+
patch.deliveryOutcome = children.some((row) => row.delivery_outcome === 'blocked') ? 'blocked' : 'retryable_failure';
|
|
102
|
+
patch.statusCode = children.find((row) => row.decision === 'pr_failed')?.status_code ?? 'delivery_failed';
|
|
103
|
+
}
|
|
104
|
+
else if (active.length > 0 && active.every((row) => row.decision === 'pr_ready')) {
|
|
105
|
+
decision = 'pr_ready';
|
|
106
|
+
patch.deliveryOutcome = 'delivered';
|
|
107
|
+
patch.statusCode = 'pr_ready';
|
|
108
|
+
}
|
|
109
|
+
else if (active.length > 0 && active.every((row) => row.decision === 'pr_draft' || row.decision === 'pr_ready')) {
|
|
110
|
+
decision = 'pr_draft';
|
|
111
|
+
patch.deliveryOutcome = 'delivered';
|
|
112
|
+
patch.statusCode = 'pr_draft_ready';
|
|
113
|
+
}
|
|
114
|
+
else if (active.length > 0 && active.every((row) => row.decision === 'pr_closed')) {
|
|
115
|
+
decision = 'pr_closed';
|
|
116
|
+
patch.deliveryOutcome = 'delivered';
|
|
117
|
+
patch.statusCode = 'pr_closed';
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
decision = 'on_review';
|
|
121
|
+
patch.deliveryOutcome = accepted.length > 0 ? 'partial' : 'ready';
|
|
122
|
+
patch.statusCode = accepted.length > 0 ? 'partial_delivery' : 'ready_for_review';
|
|
123
|
+
}
|
|
124
|
+
if (accepted.length > 0 && accepted.length < children.length) {
|
|
125
|
+
patch.deliveryOutcome = 'partial';
|
|
126
|
+
patch.statusCode = 'partial_delivery';
|
|
127
|
+
patch.statusDetail = `${accepted.length}/${children.length} repositories accepted. The shared spec remains pending until every repository is accepted.`;
|
|
128
|
+
}
|
|
129
|
+
else if (patch.statusDetail === undefined) {
|
|
130
|
+
patch.statusDetail = children.find((row) => row.status_detail)?.status_detail ?? null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (decision === 'merged' || decision === 'completed' || decision === 'discarded') {
|
|
134
|
+
// Parent acceptance and its shared-ticket outbox MUST commit together. A
|
|
135
|
+
// restart after the last child accepted can safely recreate this projection.
|
|
136
|
+
const accepted = decision !== 'discarded';
|
|
137
|
+
db.transaction(() => {
|
|
138
|
+
const token = parent.operation_token ?? (0, ids_1.newId)();
|
|
139
|
+
const claimedHere = !parent.operation_token;
|
|
140
|
+
if (claimedHere && !(0, rail_pr_store_1.claimPrDeliveryOperation)(db, parent.id, parent.decision, accepted ? 'merge-local' : 'discard', token))
|
|
141
|
+
return;
|
|
142
|
+
try {
|
|
143
|
+
(0, rail_pr_ticket_effects_1.transitionClaimedDecisionWithTicketEffect)(db, parent.id, parent.decision, decision, token, patch, {
|
|
144
|
+
deliveryId: parent.id, ticketIds: (0, rail_pr_store_1.toPrDeliverySnapshot)(parent).ticketIds,
|
|
145
|
+
targetStatus: accepted ? 'done' : 'todo', jiraAction: accepted ? 'merged' : 'discard', prUrl: null,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
if (claimedHere)
|
|
150
|
+
(0, rail_pr_store_1.releasePrDeliveryOperation)(db, parent.id, token);
|
|
151
|
+
}
|
|
152
|
+
})();
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
(0, rail_pr_store_1.transitionDecision)(db, parent.id, parent.decision, decision, patch);
|
|
156
|
+
}
|
|
157
|
+
return (0, rail_pr_store_1.getPrDelivery)(db, parentId);
|
|
158
|
+
}
|
|
159
|
+
function emitGroup(ctx, parentId, post = false) {
|
|
160
|
+
const row = (0, rail_pr_store_1.getPrDelivery)(ctx.db, parentId);
|
|
161
|
+
if (!row)
|
|
162
|
+
return;
|
|
163
|
+
const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
|
|
164
|
+
try {
|
|
165
|
+
ctx.broadcast((0, rail_pr_store_1.toRailPrStateMessage)(ctx.project.id, snap));
|
|
166
|
+
}
|
|
167
|
+
catch { /* durable projection is authoritative */ }
|
|
168
|
+
if (row.origin_conversation_id) {
|
|
169
|
+
const agent = (0, agent_chat_registry_1.getAgentChatManager)();
|
|
170
|
+
const envelope = (0, rail_pr_store_1.toPrDecisionCardEnvelope)(ctx.project.id, snap);
|
|
171
|
+
try {
|
|
172
|
+
if (post)
|
|
173
|
+
agent?.postPrDecisionCard(row.origin_conversation_id, envelope);
|
|
174
|
+
else
|
|
175
|
+
agent?.updatePrDecisionCard(row.origin_conversation_id, envelope);
|
|
176
|
+
}
|
|
177
|
+
catch { /* a disconnected origin must not alter execution */ }
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function deferred() {
|
|
181
|
+
let resolve;
|
|
182
|
+
let reject;
|
|
183
|
+
const promise = new Promise((yes, no) => { resolve = yes; reject = no; });
|
|
184
|
+
return { promise, resolve, reject };
|
|
185
|
+
}
|
|
186
|
+
/** One pipeline per spec/batch; allocation and settlement compose the proven
|
|
187
|
+
* single-repository implementation without launching an independent AI per repo. */
|
|
188
|
+
async function launchMultiRepositoryRail(input, io = {}) {
|
|
189
|
+
const { ctx } = input;
|
|
190
|
+
const members = (0, project_repositories_1.getProjectRepositories)(ctx.project);
|
|
191
|
+
const primary = members.find((repo) => repo.isPrimary) ?? members[0];
|
|
192
|
+
const requested = input.repositoryIds ?? [primary.id];
|
|
193
|
+
if (requested.length === 0 || new Set(requested).size !== requested.length)
|
|
194
|
+
throw new Error('repositoryIds must contain distinct registered repositories');
|
|
195
|
+
const selected = requested.map((id) => {
|
|
196
|
+
const repo = members.find((entry) => entry.id === id);
|
|
197
|
+
if (!repo)
|
|
198
|
+
throw new Error(`Unknown project repository: ${id}`);
|
|
199
|
+
if (repo.kind !== 'git')
|
|
200
|
+
throw new Error(`Repository ${repo.name} is context-only; isolated write targets must be Git repositories`);
|
|
201
|
+
return { ...repo };
|
|
202
|
+
});
|
|
203
|
+
if (new Set(selected.map((repo) => (0, repo_lock_1.repositoryLockKey)(repo.path))).size !== selected.length) {
|
|
204
|
+
throw new Error('An execution cannot target the same physical Git repository more than once');
|
|
205
|
+
}
|
|
206
|
+
if (input.explicitPrTarget && selected.length !== 1)
|
|
207
|
+
throw new Error('An explicit pull request target must name one repository');
|
|
208
|
+
const artifactRepositoryId = selected.find((repo) => repo.isPrimary)?.id ?? selected[0].id;
|
|
209
|
+
const graph = structuredClone(input.loopGraph);
|
|
210
|
+
for (const node of graph.nodes) {
|
|
211
|
+
if (node.type !== 'shell')
|
|
212
|
+
continue;
|
|
213
|
+
if (selected.length === 1 && !node.data?.repositoryId)
|
|
214
|
+
node.data = { ...node.data, repositoryId: selected[0].id };
|
|
215
|
+
if (input.loopId === 'factory:sdd-quick-openspec' && node.id === 'archive' && !node.data?.repositoryId) {
|
|
216
|
+
node.data = { ...node.data, repositoryId: artifactRepositoryId };
|
|
217
|
+
}
|
|
218
|
+
if (typeof node.data?.repositoryId !== 'string' || !selected.some((repo) => repo.id === node.data?.repositoryId)) {
|
|
219
|
+
throw new Error(`Shell step ${node.id} requires an explicit selected repositoryId`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const git = io.git ?? worktree_manager_1.defaultGitRunner;
|
|
223
|
+
const integrationBranches = new Map();
|
|
224
|
+
// Validate all targets before allocating any worktree or delivery child.
|
|
225
|
+
for (const repo of selected) {
|
|
226
|
+
const result = await git.run(['rev-parse', '--verify', 'HEAD'], repo.path);
|
|
227
|
+
if (result.code !== 0 || !/^[a-f0-9]{40,64}$/i.test(result.stdout.trim()))
|
|
228
|
+
throw new Error(`Repository ${repo.name} has no readable commit`);
|
|
229
|
+
if (input.repositoryBaseBranches?.[repo.id]) {
|
|
230
|
+
const target = await (0, integration_branch_1.resolveIntegrationBranch)(git, { repoDir: repo.path, projectSetting: repo.integrationBranch ?? (repo.isPrimary ? (0, db_1.getProjectSettings)(ctx.db).integrationBranch : undefined) });
|
|
231
|
+
integrationBranches.set(repo.id, target.branch);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const previousParentId = input.revision?.ofDeliveryId ?? input.repositoryContinuation?.deliveryId;
|
|
235
|
+
const previousParent = previousParentId ? (0, rail_pr_store_1.getPrDelivery)(ctx.db, previousParentId) : undefined;
|
|
236
|
+
const previousManifest = (0, multi_repo_execution_store_1.readExecutionManifest)(previousParent?.execution_manifest);
|
|
237
|
+
const previousChildren = previousParentId ? listRepositoryDeliveries(ctx.db, previousParentId) : [];
|
|
238
|
+
if (previousParentId && (!previousParent || !previousManifest ||
|
|
239
|
+
selected.length !== previousManifest.selectedRepositoryIds.length ||
|
|
240
|
+
selected.some((repo) => !previousManifest.selectedRepositoryIds.includes(repo.id)))) {
|
|
241
|
+
throw new Error('A repository delivery revision must keep its exact registered repository scope');
|
|
242
|
+
}
|
|
243
|
+
for (const previous of previousChildren) {
|
|
244
|
+
if (previous.operation_token)
|
|
245
|
+
throw new Error('A repository delivery action is still in progress');
|
|
246
|
+
if (previous.repository_path !== selected.find((repo) => repo.id === previous.repository_id)?.path) {
|
|
247
|
+
throw new Error('The repository location changed since the delivery; restore it before revising');
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
const artifactExecution = (io.resolveExecution ?? workspace_resolution_1.resolveProjectExecution)(ctx.project);
|
|
251
|
+
const parentId = (0, ids_1.newId)();
|
|
252
|
+
const effectiveScope = previousChildren.some((row) => row.pr_url && row.branch) ? 'all' : input.scope;
|
|
253
|
+
const groups = input.ticketIds.length === 0 || effectiveScope === 'all' ? [input.ticketIds] : input.ticketIds.map((id) => [id]);
|
|
254
|
+
const runIds = new Map(groups.map((ids) => [ids[0] ?? 0, (0, ids_1.newId)()]));
|
|
255
|
+
const gates = new Map([...runIds.values()].map((id) => [id, deferred()]));
|
|
256
|
+
// Every rejection has a sink even if allocation fails before a child subscribes.
|
|
257
|
+
for (const gate of gates.values())
|
|
258
|
+
void gate.promise.catch(() => { });
|
|
259
|
+
const requests = new Map();
|
|
260
|
+
const settledChildren = new Set();
|
|
261
|
+
const childSettlements = [];
|
|
262
|
+
const results = new Map();
|
|
263
|
+
let aborted = false;
|
|
264
|
+
let allocationComplete = false;
|
|
265
|
+
let groupFinished = false;
|
|
266
|
+
const manifest = {
|
|
267
|
+
version: 1, groupId: parentId, projectId: ctx.project.id, primaryRepositoryId: primary.id,
|
|
268
|
+
artifactRepositoryId, selectedRepositoryIds: selected.map((repo) => repo.id), repositories: [],
|
|
269
|
+
};
|
|
270
|
+
const generation = (0, rail_pr_store_1.createPrDeliveryGeneration)(ctx.db, {
|
|
271
|
+
id: parentId, railIndex: input.railIndex, loopId: input.loopId, railKey: `${input.railIndex}-${input.loopId}`,
|
|
272
|
+
ticketIds: input.ticketIds, baseBranch: input.baseBranch ?? '', loopName: input.loopName,
|
|
273
|
+
originSurface: input.originSurface ?? 'dashboard', originConversationId: input.originConversationId,
|
|
274
|
+
specSnapshot: (0, rail_isolated_launch_1.buildSpecSnapshot)(ctx, input.ticketIds),
|
|
275
|
+
...(input.revision ? { revisionNote: input.revision.note, revisionOf: input.revision.ofDeliveryId } : {}),
|
|
276
|
+
}, input.revision ? { id: input.revision.ofDeliveryId, decision: input.revision.decision } : input.repositoryContinuation ? { id: input.repositoryContinuation.deliveryId, decision: input.repositoryContinuation.decision } : null);
|
|
277
|
+
for (const child of previousChildren) {
|
|
278
|
+
if (!['merged', 'completed', 'discarded', 'superseded'].includes(child.decision))
|
|
279
|
+
(0, rail_pr_store_1.transitionDecision)(ctx.db, child.id, child.decision, 'superseded');
|
|
280
|
+
}
|
|
281
|
+
(0, rail_pr_store_1.transitionDecision)(ctx.db, parentId, 'building', 'building', { executionManifest: manifest, runIds: [...runIds.values()] });
|
|
282
|
+
try {
|
|
283
|
+
input.onPrDeliveryCreated?.(parentId);
|
|
284
|
+
}
|
|
285
|
+
catch { /* durable group hydration remains available */ }
|
|
286
|
+
emitGroup(ctx, parentId, true);
|
|
287
|
+
const finishGroup = () => {
|
|
288
|
+
if (aborted || groupFinished || !allocationComplete || settledChildren.size !== selected.length)
|
|
289
|
+
return;
|
|
290
|
+
groupFinished = true;
|
|
291
|
+
const failures = [];
|
|
292
|
+
for (const [runId, result] of results) {
|
|
293
|
+
try {
|
|
294
|
+
ctx.onLoopRunFinished(runId, result.outcome, { ticketCompletionStatus: 'on_review', ...(result.stallReason ? { stallReason: result.stallReason } : {}) });
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
failures.push(error instanceof Error ? error.message : String(error));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (failures.length > 0) {
|
|
301
|
+
const detail = `The shared run could not finish its ticket settlement: ${failures.join('; ')}`;
|
|
302
|
+
for (const child of listRepositoryDeliveries(ctx.db, parentId)) {
|
|
303
|
+
const snapshot = (0, rail_pr_store_1.toPrDeliverySnapshot)(child);
|
|
304
|
+
(0, rail_pr_store_1.transitionDecision)(ctx.db, child.id, child.decision, 'pr_failed', {
|
|
305
|
+
deliveryOutcome: 'blocked', statusCode: 'settlement_interrupted', statusDetail: detail,
|
|
306
|
+
branches: snapshot.branches.map((unit) => ({ ...unit, deliveryOutcome: 'blocked', statusCode: 'settlement_interrupted', statusDetail: detail })),
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
refreshRepositoryDeliveryGroup(ctx.db, parentId);
|
|
311
|
+
emitGroup(ctx, parentId);
|
|
312
|
+
};
|
|
313
|
+
try {
|
|
314
|
+
for (const repository of selected) {
|
|
315
|
+
const childSettlement = deferred();
|
|
316
|
+
const previous = previousChildren.find((row) => row.repository_id === repository.id);
|
|
317
|
+
const previousRepository = previousManifest?.repositories.find((row) => row.repositoryId === repository.id);
|
|
318
|
+
const previousBaseBranch = previous && ['merged', 'completed'].includes(previous.decision)
|
|
319
|
+
? previousRepository?.integrationBranch ?? previous.base_branch
|
|
320
|
+
: previous?.base_branch;
|
|
321
|
+
const oldSnapshot = previous ? (0, rail_pr_store_1.toPrDeliverySnapshot)(previous) : null;
|
|
322
|
+
const revisionBranches = new Map();
|
|
323
|
+
if (oldSnapshot && !['merged', 'completed', 'discarded'].includes(oldSnapshot.decision) && !previous?.pr_url) {
|
|
324
|
+
for (const unit of oldSnapshot.branches) {
|
|
325
|
+
if (unit.finalSha)
|
|
326
|
+
revisionBranches.set(unit.ticketId, { branch: unit.branch, sha: unit.finalSha });
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
const continuation = previous?.pr_url && previous.branch && previous.delivery_sha && previous.pr_number &&
|
|
330
|
+
(previous.decision === 'pr_draft' || previous.decision === 'pr_ready')
|
|
331
|
+
? { deliveryId: previous.id, decision: previous.decision, branch: previous.branch,
|
|
332
|
+
baseBranch: previous.base_branch, prUrl: previous.pr_url, prNumber: previous.pr_number, deliverySha: previous.delivery_sha }
|
|
333
|
+
: undefined;
|
|
334
|
+
const manager = Object.create(ctx.loopRunManager);
|
|
335
|
+
manager.run = (request) => {
|
|
336
|
+
const gate = gates.get(request.runId);
|
|
337
|
+
if (!gate)
|
|
338
|
+
throw new Error('Repository allocation changed the coordinated ticket scope');
|
|
339
|
+
const byRepository = requests.get(request.runId) ?? new Map();
|
|
340
|
+
byRepository.set(repository.id, request);
|
|
341
|
+
requests.set(request.runId, byRepository);
|
|
342
|
+
return gate.promise;
|
|
343
|
+
};
|
|
344
|
+
const childCtx = {
|
|
345
|
+
...ctx,
|
|
346
|
+
project: { ...ctx.project, path: repository.path },
|
|
347
|
+
loopRunManager: manager,
|
|
348
|
+
railLoopRuns: new Map(),
|
|
349
|
+
onLoopRunFinished: () => { },
|
|
350
|
+
jiraSyncManager: Object.assign(Object.create(ctx.jiraSyncManager), { onRailLaunch: () => { } }),
|
|
351
|
+
broadcast: (message) => { if (message.type !== 'rail.pr_state')
|
|
352
|
+
ctx.broadcast(message); },
|
|
353
|
+
};
|
|
354
|
+
await (0, rail_isolated_launch_1.launchIsolatedRail)({
|
|
355
|
+
...input, ctx: childCtx, scope: effectiveScope, loopGraph: graph,
|
|
356
|
+
revision: input.revision && previous ? { ...input.revision, ofDeliveryId: previous.id, decision: previous.decision } : undefined,
|
|
357
|
+
requiredPrContinuation: continuation,
|
|
358
|
+
explicitPrTarget: continuation?.prNumber ? { prNumber: continuation.prNumber } : input.explicitPrTarget,
|
|
359
|
+
originConversationId: undefined,
|
|
360
|
+
baseBranch: input.repositoryBaseBranches?.[repository.id] ?? (repository.isPrimary ? input.baseBranch ?? previousBaseBranch : previousBaseBranch),
|
|
361
|
+
onPrDeliveryCreated: undefined,
|
|
362
|
+
repositoryExecution: {
|
|
363
|
+
parentDeliveryId: parentId, repositoryId: repository.id, primary: repository.isPrimary, runIds, revisionBranches, isAborted: () => aborted, expectedBaseSha: input.repositoryBaseShas?.[repository.id],
|
|
364
|
+
onSettled: (id) => {
|
|
365
|
+
if (id)
|
|
366
|
+
settledChildren.add(id);
|
|
367
|
+
try {
|
|
368
|
+
finishGroup();
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
// The existing ledger and child snapshots let startup reconciliation
|
|
372
|
+
// recover even if a database failure interrupts the final projection.
|
|
373
|
+
console.error('[multi-repo] group settlement interrupted:', error);
|
|
374
|
+
}
|
|
375
|
+
finally {
|
|
376
|
+
childSettlement.resolve(undefined);
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
}, { ...io, resolveExecution: () => artifactExecution });
|
|
381
|
+
childSettlements.push(childSettlement.promise);
|
|
382
|
+
const child = listRepositoryDeliveries(ctx.db, parentId).find((row) => row.repository_id === repository.id);
|
|
383
|
+
const ledger = ctx.db.prepare('SELECT * FROM rail_worktrees WHERE id IN (SELECT value FROM json_each(?))').all(child.worktree_ids);
|
|
384
|
+
// worktree_ids is normally written at settlement; allocation is already durable in the ledger.
|
|
385
|
+
const allocated = ledger.length ? ledger : ctx.db.prepare('SELECT * FROM rail_worktrees WHERE repository_id = ? AND run_id IN (SELECT value FROM json_each(?))').all(repository.id, JSON.stringify([...runIds.values()]));
|
|
386
|
+
for (const worktree of allocated) {
|
|
387
|
+
const head = await git.run(['rev-parse', '--verify', 'HEAD'], worktree.worktree_path);
|
|
388
|
+
if (head.code !== 0 || !/^[a-f0-9]{40,64}$/i.test(head.stdout.trim()))
|
|
389
|
+
throw new Error(`Cannot freeze HEAD for ${repository.name}`);
|
|
390
|
+
manifest.repositories.push({ repositoryId: repository.id, name: repository.name, sourcePath: repository.path,
|
|
391
|
+
gitCommonDir: (0, repo_lock_1.repositoryLockKey)(repository.path), baseBranch: child.base_branch, integrationBranch: integrationBranches.get(repository.id) ?? previousRepository?.integrationBranch ?? child.base_branch, baseSha: head.stdout.trim(),
|
|
392
|
+
worktreePath: worktree.worktree_path, branch: worktree.branch, worktreeId: worktree.id });
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
for (const [runId, byRepository] of requests) {
|
|
396
|
+
if (byRepository.size !== selected.length)
|
|
397
|
+
throw new Error(`Run ${runId} is missing a repository allocation`);
|
|
398
|
+
}
|
|
399
|
+
if (requests.size !== groups.length)
|
|
400
|
+
throw new Error('The launch did not allocate every coordinated run');
|
|
401
|
+
allocationComplete = true;
|
|
402
|
+
// Serialize first; no provider starts until every repository snapshot exists.
|
|
403
|
+
(0, rail_pr_store_1.transitionDecision)(ctx.db, parentId, 'building', 'building', {
|
|
404
|
+
executionManifest: manifest, worktreeIds: manifest.repositories.map((repo) => repo.worktreeId),
|
|
405
|
+
});
|
|
406
|
+
for (const child of listRepositoryDeliveries(ctx.db, parentId)) {
|
|
407
|
+
(0, rail_pr_store_1.transitionDecision)(ctx.db, child.id, 'building', 'building', { executionManifest: { ...manifest, selectedRepositoryIds: [child.repository_id], repositories: manifest.repositories.filter((repo) => repo.repositoryId === child.repository_id) } });
|
|
408
|
+
}
|
|
409
|
+
refreshRepositoryDeliveryGroup(ctx.db, parentId);
|
|
410
|
+
emitGroup(ctx, parentId);
|
|
411
|
+
for (const [runId, byRepository] of requests) {
|
|
412
|
+
const primaryRequest = byRepository.get(artifactRepositoryId) ?? byRepository.values().next().value;
|
|
413
|
+
const runManifest = {
|
|
414
|
+
...manifest,
|
|
415
|
+
repositories: manifest.repositories.filter((repo) => byRepository.get(repo.repositoryId)?.repoDir === repo.worktreePath),
|
|
416
|
+
};
|
|
417
|
+
ctx.railLoopRuns.set(runId, { railIndex: input.railIndex, ticketIds: primaryRequest.spec?.ticketIds ?? [], requiresTerminalIntent: true });
|
|
418
|
+
const resultPromise = ctx.loopRunManager.run({ ...primaryRequest, graph, executionManifest: runManifest });
|
|
419
|
+
try {
|
|
420
|
+
ctx.jiraSyncManager.onRailLaunch(primaryRequest.spec?.ticketIds ?? [], runId);
|
|
421
|
+
}
|
|
422
|
+
catch { /* non-fatal */ }
|
|
423
|
+
void resultPromise.then((result) => { results.set(runId, result); gates.get(runId).resolve(result); }, (error) => {
|
|
424
|
+
results.set(runId, { runId, outcome: 'failed' });
|
|
425
|
+
gates.get(runId).reject(error);
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return [...runIds.values()];
|
|
429
|
+
}
|
|
430
|
+
catch (error) {
|
|
431
|
+
aborted = true;
|
|
432
|
+
allocationComplete = true;
|
|
433
|
+
for (const gate of gates.values())
|
|
434
|
+
gate.reject(error);
|
|
435
|
+
await Promise.all(childSettlements);
|
|
436
|
+
if (generation.superseded && (0, rail_pr_store_1.failPrDeliveryAndRestoreSuperseded)(ctx.db, parentId, generation.superseded)) {
|
|
437
|
+
for (const previous of previousChildren) {
|
|
438
|
+
const live = (0, rail_pr_store_1.getPrDelivery)(ctx.db, previous.id);
|
|
439
|
+
if (live?.decision === 'superseded' && previous.decision !== 'superseded')
|
|
440
|
+
(0, rail_pr_store_1.transitionDecision)(ctx.db, previous.id, 'superseded', previous.decision);
|
|
441
|
+
}
|
|
442
|
+
emitGroup(ctx, generation.superseded.id);
|
|
443
|
+
}
|
|
444
|
+
const row = (0, rail_pr_store_1.getPrDelivery)(ctx.db, parentId);
|
|
445
|
+
if (row?.decision === 'building')
|
|
446
|
+
(0, rail_pr_store_1.transitionDecision)(ctx.db, parentId, 'building', 'pr_failed', {
|
|
447
|
+
implementationOutcome: 'failed', deliveryOutcome: 'blocked', statusCode: 'delivery_failed',
|
|
448
|
+
statusDetail: error instanceof Error ? error.message : String(error), executionManifest: manifest,
|
|
449
|
+
});
|
|
450
|
+
emitGroup(ctx, parentId);
|
|
451
|
+
throw error;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
@@ -9,7 +9,7 @@ const child_process_1 = require("child_process");
|
|
|
9
9
|
const fs_1 = require("fs");
|
|
10
10
|
const path_1 = require("path");
|
|
11
11
|
const win_spawn_1 = require("./util/win-spawn");
|
|
12
|
-
const
|
|
12
|
+
const core_runtime_1 = require("./core-runtime");
|
|
13
13
|
const bundled_openspec_1 = require("./bundled-openspec");
|
|
14
14
|
const path_resolver_1 = require("./path-resolver");
|
|
15
15
|
const framework_manager_1 = require("./framework-manager");
|
|
@@ -41,10 +41,10 @@ const providers_1 = require("./providers");
|
|
|
41
41
|
* fallback outside the packaged desktop app.
|
|
42
42
|
*/
|
|
43
43
|
function spawnBundledCoreInit(args, cwd) {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
if (!cli || !coreRoot)
|
|
44
|
+
const runtime = (0, core_runtime_1.resolveCoreRuntime)();
|
|
45
|
+
if (!runtime)
|
|
47
46
|
return null;
|
|
47
|
+
const { cli, root: coreRoot } = runtime;
|
|
48
48
|
const fullArgs = [cli, 'init', ...args];
|
|
49
49
|
const env = { ...(0, win_spawn_1.windowsSpawnEnv)(), SPECRAILS_CORE_SCRIPT_DIR: coreRoot, SPECRAILS_RELOCATE: '1' };
|
|
50
50
|
const openspecCli = (0, bundled_openspec_1.getBundledOpenspecCli)();
|
|
@@ -67,7 +67,7 @@ function spawnBundledCoreInit(args, cwd) {
|
|
|
67
67
|
}
|
|
68
68
|
/** True when the bundled specrails-core is present (offline assemble possible). */
|
|
69
69
|
function hasOfflineCore() {
|
|
70
|
-
return (0,
|
|
70
|
+
return (0, core_runtime_1.resolveCoreRuntime)() !== null;
|
|
71
71
|
}
|
|
72
72
|
const WHICH_CMD = process.platform === 'win32' ? 'where' : 'which';
|
|
73
73
|
/** Resolve a core binary override to an absolute path (mirrors SetupManager). */
|
|
@@ -107,7 +107,7 @@ function spawnNpxCoreInit(args, cwd) {
|
|
|
107
107
|
* missing/corrupted bundle returns false → the "reinstall the app" error.
|
|
108
108
|
*/
|
|
109
109
|
function canAssembleProject() {
|
|
110
|
-
return (0,
|
|
110
|
+
return (0, core_runtime_1.resolveCoreRuntime)() !== null || process.env.SPECRAILS_IS_DESKTOP !== '1';
|
|
111
111
|
}
|
|
112
112
|
function buildQuickInstallConfigYaml(provider, defaultModel) {
|
|
113
113
|
// Matches serializeInstallConfigYaml's shape (specrails-core tui-installer
|
|
@@ -172,7 +172,7 @@ async function assembleProjectOffline(opts) {
|
|
|
172
172
|
const materialize = opts.io?.materialize ?? ((provs) => {
|
|
173
173
|
try {
|
|
174
174
|
const fm = new framework_manager_1.FrameworkManager({ broadcast: () => { } });
|
|
175
|
-
const mat = fm.materialize(
|
|
175
|
+
const mat = fm.materialize(undefined, provs);
|
|
176
176
|
if (mat.ran && mat.errors.length > 0) {
|
|
177
177
|
console.warn(`[offline-assemble] framework materialize had errors: ${mat.errors.map((e) => `${e.provider}: ${e.message}`).join('; ')}`);
|
|
178
178
|
}
|
|
@@ -188,7 +188,9 @@ async function assembleProjectOffline(opts) {
|
|
|
188
188
|
const assembleOne = async (provider) => {
|
|
189
189
|
const configPath = (0, install_config_path_1.installConfigPathForProvider)({ slug, path: projectPath }, provider);
|
|
190
190
|
(0, fs_1.mkdirSync)((0, path_1.dirname)(configPath), { recursive: true });
|
|
191
|
-
(0, fs_1.
|
|
191
|
+
if (!opts.preserveExistingConfig || !(0, fs_1.existsSync)(configPath)) {
|
|
192
|
+
(0, fs_1.writeFileSync)(configPath, buildQuickInstallConfigYaml(provider, defaultModelForProvider(opts, provider)), 'utf-8');
|
|
193
|
+
}
|
|
192
194
|
const child = spawnInit(['--yes', '--from-config', configPath], projectPath);
|
|
193
195
|
if (!child) {
|
|
194
196
|
throw new Error('specrails-core is not available — reinstall the Specrails app');
|