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
|
@@ -11,28 +11,13 @@ const path_1 = __importDefault(require("path"));
|
|
|
11
11
|
const framework_manager_1 = require("./framework-manager");
|
|
12
12
|
const semver_lite_1 = require("./semver-lite");
|
|
13
13
|
const win_spawn_1 = require("./util/win-spawn");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* staging dir, materializes its framework into `~/.specrails/framework/<version>`
|
|
22
|
-
* and atomically swaps `framework/current` to it — every project workspace that
|
|
23
|
-
* symlinks `current/...` jumps to the new core with NO restart and NO per-project
|
|
24
|
-
* `npx`. The previous `framework/<version>` dir is left intact (non-destructive).
|
|
25
|
-
*
|
|
26
|
-
* Detection is deliberately simple (KISS): npm `latest` strictly greater than the
|
|
27
|
-
* installed `framework/current` version ⇒ an update is available. There is no
|
|
28
|
-
* compatibility-range gate; the floor is the app-bundled core (the update only
|
|
29
|
-
* ever moves the pointer UP — FrameworkManager.versionCheck has an anti-downgrade
|
|
30
|
-
* guard so the next startup never reverts a manual update).
|
|
31
|
-
*
|
|
32
|
-
* The whole feature is gated on a bundled core being present (desktop mode); in
|
|
33
|
-
* dev / non-desktop mode `isAvailable()` is false and projects use the legacy npx
|
|
34
|
-
* path, so a core "update" would have no effect and the UI shows "unavailable".
|
|
35
|
-
*/
|
|
14
|
+
const bundled_core_1 = require("./bundled-core");
|
|
15
|
+
const core_runtime_1 = require("./core-runtime");
|
|
16
|
+
const artifact_registry_1 = require("./artifact-registry");
|
|
17
|
+
/** Voluntary Core updates retain the complete npm package and dependencies,
|
|
18
|
+
* publish its framework, then await every project refresh. Partial refreshes
|
|
19
|
+
* remain explicitly pending across restart and can retry without the network.
|
|
20
|
+
* Older packages/frameworks remain available for diagnosis and recovery. */
|
|
36
21
|
exports.CORE_PACKAGE = 'specrails-core';
|
|
37
22
|
const REGISTRY_URL = `https://registry.npmjs.org/${exports.CORE_PACKAGE}/latest`;
|
|
38
23
|
const CHECK_TIMEOUT_MS = 10_000;
|
|
@@ -47,6 +32,9 @@ class CoreUpdateManager {
|
|
|
47
32
|
latestVersion = null;
|
|
48
33
|
lastCheckedAt = null;
|
|
49
34
|
updating = false;
|
|
35
|
+
pendingVersion = null;
|
|
36
|
+
migrationError = null;
|
|
37
|
+
reseed;
|
|
50
38
|
constructor(opts = {}) {
|
|
51
39
|
this.home = opts.home;
|
|
52
40
|
this.broadcast = opts.broadcast;
|
|
@@ -56,31 +44,49 @@ class CoreUpdateManager {
|
|
|
56
44
|
this.makeFrameworkFn =
|
|
57
45
|
opts.makeFramework ??
|
|
58
46
|
((coreRoot) => new framework_manager_1.FrameworkManager({ home: this.home, broadcast: this.broadcast, coreRoot }));
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
47
|
+
this.reseed = opts.reseed ?? (async () => []);
|
|
48
|
+
try {
|
|
49
|
+
const cached = JSON.parse(fs_1.default.readFileSync(path_1.default.join((0, core_runtime_1.managedCoreRoot)(this.home), 'update-status.json'), 'utf8'));
|
|
50
|
+
if (typeof cached.latestVersion === 'string' && (0, semver_lite_1.isValidVersion)(cached.latestVersion) && Number.isFinite(cached.lastCheckedAt)) {
|
|
51
|
+
this.latestVersion = cached.latestVersion;
|
|
52
|
+
this.lastCheckedAt = cached.lastCheckedAt;
|
|
53
|
+
}
|
|
54
|
+
if (typeof cached.pendingVersion === 'string' && (0, semver_lite_1.isValidVersion)(cached.pendingVersion)) {
|
|
55
|
+
this.pendingVersion = cached.pendingVersion;
|
|
56
|
+
this.migrationError = typeof cached.migrationError === 'string' ? cached.migrationError : 'Core project refresh was interrupted. Retry to finish updating project files.';
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch { /* first launch / cache unavailable: installed state is independent */ }
|
|
63
60
|
}
|
|
64
61
|
/** True when the bundled-framework system is active (a bundled core is present). */
|
|
65
62
|
isAvailable() {
|
|
66
|
-
return this.
|
|
63
|
+
return (0, core_runtime_1.getCoreRuntimeStatus)(this.home).runtime !== null || (0, framework_manager_1.readCurrentFrameworkVersion)(this.home) !== null;
|
|
67
64
|
}
|
|
68
65
|
/** Current status — no network (uses the cached latest from the last check). */
|
|
69
66
|
getStatus() {
|
|
70
|
-
const
|
|
71
|
-
const bundledVersion =
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
const selected = (0, core_runtime_1.getCoreRuntimeStatus)(this.home);
|
|
68
|
+
const bundledVersion = (0, bundled_core_1.getBundledCoreVersion)();
|
|
69
|
+
const frameworkVersion = (0, framework_manager_1.readCurrentFrameworkVersion)(this.home);
|
|
70
|
+
const currentVersion = frameworkVersion ?? selected.runtime?.version ?? null;
|
|
71
|
+
const updateAvailable = this.pendingVersion !== null ||
|
|
72
|
+
this.latestVersion != null &&
|
|
73
|
+
currentVersion != null &&
|
|
74
|
+
((0, semver_lite_1.isNewer)(this.latestVersion, currentVersion) || selected.error !== null && this.latestVersion === currentVersion) &&
|
|
75
|
+
Number(this.latestVersion.split('.')[0]) <= 5;
|
|
76
76
|
return {
|
|
77
|
-
available:
|
|
77
|
+
available: this.isAvailable(),
|
|
78
78
|
currentVersion,
|
|
79
79
|
bundledVersion,
|
|
80
80
|
latestVersion: this.latestVersion,
|
|
81
81
|
updateAvailable,
|
|
82
82
|
updating: this.updating,
|
|
83
83
|
lastCheckedAt: this.lastCheckedAt,
|
|
84
|
+
runtimeVersion: selected.runtime?.version ?? null,
|
|
85
|
+
runtimeSource: selected.runtime?.source ?? null,
|
|
86
|
+
frameworkVersion,
|
|
87
|
+
runtimeError: selected.error,
|
|
88
|
+
pendingVersion: this.pendingVersion,
|
|
89
|
+
migrationError: this.migrationError,
|
|
84
90
|
};
|
|
85
91
|
}
|
|
86
92
|
/** Hit npm for the latest published version, cache it, return refreshed status. */
|
|
@@ -91,6 +97,7 @@ class CoreUpdateManager {
|
|
|
91
97
|
}
|
|
92
98
|
this.latestVersion = latest.trim().replace(/^[v=]+/, '');
|
|
93
99
|
this.lastCheckedAt = Date.now();
|
|
100
|
+
this.persistStatus();
|
|
94
101
|
return this.getStatus();
|
|
95
102
|
}
|
|
96
103
|
/**
|
|
@@ -106,12 +113,15 @@ class CoreUpdateManager {
|
|
|
106
113
|
if (!this.isAvailable()) {
|
|
107
114
|
return { ok: false, error: 'Core updates are unavailable in this build.' };
|
|
108
115
|
}
|
|
109
|
-
const requested = (targetVersion ?? this.latestVersion ?? '').trim().replace(/^[v=]+/, '');
|
|
116
|
+
const requested = (targetVersion ?? this.pendingVersion ?? this.latestVersion ?? '').trim().replace(/^[v=]+/, '');
|
|
110
117
|
if (!requested || !(0, semver_lite_1.isValidVersion)(requested)) {
|
|
111
118
|
return { ok: false, error: 'No valid target version to update to. Check for updates first.' };
|
|
112
119
|
}
|
|
120
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(requested) || ![4, 5].includes(Number(requested.split('.')[0]))) {
|
|
121
|
+
return { ok: false, error: 'This Desktop supports Core 4 and 5. Update Desktop before installing another major version.' };
|
|
122
|
+
}
|
|
113
123
|
const current = (0, framework_manager_1.readCurrentFrameworkVersion)(this.home);
|
|
114
|
-
if (current && !(0, semver_lite_1.isNewer)(requested, current)) {
|
|
124
|
+
if (current && !(0, semver_lite_1.isNewer)(requested, current) && !(requested === current && ((0, core_runtime_1.getCoreRuntimeStatus)(this.home).error || this.pendingVersion === requested))) {
|
|
115
125
|
return { ok: false, error: `Already on ${current}; ${requested} is not newer.` };
|
|
116
126
|
}
|
|
117
127
|
this.updating = true;
|
|
@@ -122,39 +132,112 @@ class CoreUpdateManager {
|
|
|
122
132
|
// loader) against process.argv[1] (the literal spawn arg) — a symlinked
|
|
123
133
|
// staging path makes them differ, so main() never runs and every
|
|
124
134
|
// install-framework/swap-current child exits 0 as a silent no-op.
|
|
125
|
-
|
|
135
|
+
let tmp;
|
|
126
136
|
try {
|
|
127
|
-
|
|
128
|
-
const
|
|
137
|
+
tmp = fs_1.default.mkdtempSync(path_1.default.join(realTmpDir(), 'core-update-'));
|
|
138
|
+
const retained = path_1.default.join((0, core_runtime_1.managedCoreRoot)(this.home), requested, 'node_modules', exports.CORE_PACKAGE);
|
|
139
|
+
if ((0, core_runtime_1.readCoreRuntime)(retained, 'managed')?.version === requested) {
|
|
140
|
+
// A project migration retry can finish fully offline.
|
|
141
|
+
// Force JS traversal: Node 22's native directory copy mishandles Unicode
|
|
142
|
+
// Windows profiles (nodejs/node#61878). Both copy targets are fresh
|
|
143
|
+
// staging directories, so native file replacement is avoided too.
|
|
144
|
+
fs_1.default.cpSync(path_1.default.dirname(path_1.default.dirname(retained)), tmp, { recursive: true, filter: () => true, mode: fs_1.default.constants.COPYFILE_FICLONE });
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
this.npmInstallFn(`${exports.CORE_PACKAGE}@${requested}`, tmp);
|
|
148
|
+
}
|
|
149
|
+
let coreRoot = path_1.default.join(tmp, 'node_modules', exports.CORE_PACKAGE);
|
|
129
150
|
const cli = path_1.default.join(coreRoot, 'dist', 'installer', 'cli.js');
|
|
130
151
|
if (!fs_1.default.existsSync(cli)) {
|
|
131
152
|
throw new Error('downloaded core is missing dist/installer/cli.js');
|
|
132
153
|
}
|
|
154
|
+
const staged = (0, core_runtime_1.readCoreRuntime)(coreRoot, 'managed');
|
|
155
|
+
if (!staged || staged.version !== requested)
|
|
156
|
+
throw new Error(`Downloaded Core version does not match requested ${requested}.`);
|
|
157
|
+
const installed = staged.version;
|
|
158
|
+
// Retain the complete npm installation, including sibling dependencies.
|
|
159
|
+
// Publication is a same-filesystem rename and occurs before current moves.
|
|
160
|
+
const store = (0, core_runtime_1.managedCoreRoot)(this.home);
|
|
161
|
+
fs_1.default.mkdirSync(store, { recursive: true, mode: 0o700 });
|
|
162
|
+
const destination = path_1.default.join(store, installed);
|
|
163
|
+
if ((0, core_runtime_1.readCoreRuntime)(path_1.default.join(destination, 'node_modules', exports.CORE_PACKAGE), 'managed')?.version !== installed) {
|
|
164
|
+
const staging = fs_1.default.mkdtempSync(path_1.default.join(store, '.stage-'));
|
|
165
|
+
let retainedBackup = null;
|
|
166
|
+
try {
|
|
167
|
+
fs_1.default.cpSync(tmp, staging, { recursive: true, filter: () => true, mode: fs_1.default.constants.COPYFILE_FICLONE });
|
|
168
|
+
try {
|
|
169
|
+
fs_1.default.lstatSync(destination);
|
|
170
|
+
const backup = fs_1.default.mkdtempSync(path_1.default.join(store, `.previous-${installed}-`));
|
|
171
|
+
retainedBackup = path_1.default.join(backup, 'installation');
|
|
172
|
+
fs_1.default.renameSync(destination, retainedBackup);
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (error.code !== 'ENOENT')
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
fs_1.default.renameSync(staging, destination);
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
// Restore only when publication never created a destination. The
|
|
182
|
+
// retained previous installation is never deleted, even on success.
|
|
183
|
+
if (retainedBackup && !fs_1.default.existsSync(destination))
|
|
184
|
+
fs_1.default.renameSync(retainedBackup, destination);
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
finally {
|
|
188
|
+
fs_1.default.rmSync(staging, { recursive: true, force: true });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
coreRoot = path_1.default.join(destination, 'node_modules', exports.CORE_PACKAGE);
|
|
192
|
+
if ((0, core_runtime_1.readCoreRuntime)(coreRoot, 'managed')?.version !== installed)
|
|
193
|
+
throw new Error('The retained Core package could not be verified. Retry the update.');
|
|
133
194
|
const fm = this.makeFrameworkFn(coreRoot);
|
|
134
|
-
// The version actually installed (npm may resolve a dist-tag/range).
|
|
135
|
-
const installed = fm.bundledVersion() ?? requested;
|
|
136
195
|
this.emit('materializing', { version: installed });
|
|
137
196
|
const providers = uniqueProviders(this.providersFn());
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
197
|
+
(0, artifact_registry_1.withFileLock)(this.home, () => {
|
|
198
|
+
const now = (0, framework_manager_1.readCurrentFrameworkVersion)(this.home);
|
|
199
|
+
if (now && (0, semver_lite_1.isNewer)(now, installed))
|
|
200
|
+
throw new Error(`Core advanced to ${now} while downloading; refusing to downgrade.`);
|
|
201
|
+
const mat = fm.materialize(installed, providers);
|
|
202
|
+
if (!mat.ran) {
|
|
203
|
+
throw new Error('framework materialize did not run (no usable core)');
|
|
204
|
+
}
|
|
205
|
+
if (mat.errors.length > 0) {
|
|
206
|
+
throw new Error(`framework materialize failed: ${mat.errors.map((e) => `${e.provider}: ${e.message}`).join('; ')}`);
|
|
207
|
+
}
|
|
208
|
+
// A materialize that reports no errors but ALSO no materialized providers
|
|
209
|
+
// wrote nothing — swapping `current` at a nonexistent version dir would
|
|
210
|
+
// fail downstream with a misleading "swap-current failed". Surface the
|
|
211
|
+
// real condition instead (mirrors FrameworkManager.versionCheck's guard).
|
|
212
|
+
if (mat.providers.length === 0) {
|
|
213
|
+
throw new Error(`framework materialize completed without materializing any provider (requested: ${providers.join(', ') || 'none'})`);
|
|
214
|
+
}
|
|
215
|
+
// Recovery state is mandatory before publication. If this write fails,
|
|
216
|
+
// current stays on the previous usable version and no project is reseeded.
|
|
217
|
+
this.pendingVersion = installed;
|
|
218
|
+
this.migrationError = null;
|
|
219
|
+
this.persistStatus(true);
|
|
220
|
+
const swapped = fm.swapCurrentDetailed(installed);
|
|
221
|
+
if (!swapped.ok) {
|
|
222
|
+
throw new Error(`framework swap-current failed${swapped.detail ? `: ${swapped.detail}` : ''}`);
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
const projects = await this.reseed(installed);
|
|
226
|
+
const failed = projects.filter(project => project.error);
|
|
227
|
+
if (failed.length)
|
|
228
|
+
throw new Error(`Core ${installed} is installed, but project refresh failed: ${failed.map(project => `${project.projectId}: ${project.error}`).join('; ')}. Retry the update to finish refreshing project files.`);
|
|
229
|
+
this.pendingVersion = null;
|
|
230
|
+
this.migrationError = null;
|
|
231
|
+
// Installation is not a registry-latest check. Preserve its cached value
|
|
232
|
+
// and timestamp, including a known version newer than this target.
|
|
233
|
+
try {
|
|
234
|
+
this.persistStatus(true);
|
|
151
235
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
throw
|
|
236
|
+
catch (error) {
|
|
237
|
+
this.pendingVersion = installed;
|
|
238
|
+
throw error;
|
|
155
239
|
}
|
|
156
|
-
this.
|
|
157
|
-
this.lastCheckedAt = Date.now();
|
|
240
|
+
this.updating = false;
|
|
158
241
|
this.emit('done', { version: installed });
|
|
159
242
|
// Reuse the existing app-level event so any listener that reacts to a
|
|
160
243
|
// framework version bump (e.g. core-version banners) refreshes too.
|
|
@@ -163,19 +246,37 @@ class CoreUpdateManager {
|
|
|
163
246
|
}
|
|
164
247
|
catch (err) {
|
|
165
248
|
const message = err instanceof Error ? err.message : String(err);
|
|
249
|
+
if (this.pendingVersion) {
|
|
250
|
+
this.migrationError = message;
|
|
251
|
+
this.persistStatus();
|
|
252
|
+
}
|
|
253
|
+
this.updating = false;
|
|
166
254
|
this.emit('error', { message });
|
|
167
255
|
return { ok: false, error: message };
|
|
168
256
|
}
|
|
169
257
|
finally {
|
|
170
258
|
this.updating = false;
|
|
171
259
|
try {
|
|
172
|
-
|
|
260
|
+
if (tmp)
|
|
261
|
+
fs_1.default.rmSync(tmp, { recursive: true, force: true });
|
|
173
262
|
}
|
|
174
263
|
catch {
|
|
175
264
|
/* best-effort temp cleanup */
|
|
176
265
|
}
|
|
177
266
|
}
|
|
178
267
|
}
|
|
268
|
+
persistStatus(required = false) {
|
|
269
|
+
try {
|
|
270
|
+
const root = (0, core_runtime_1.managedCoreRoot)(this.home);
|
|
271
|
+
fs_1.default.mkdirSync(root, { recursive: true, mode: 0o700 });
|
|
272
|
+
(0, artifact_registry_1.atomicWrite)(path_1.default.join(root, 'update-status.json'), JSON.stringify({ latestVersion: this.latestVersion, lastCheckedAt: this.lastCheckedAt, pendingVersion: this.pendingVersion, migrationError: this.migrationError }));
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
if (required)
|
|
276
|
+
throw new Error(`Could not persist Core update recovery state: ${error instanceof Error ? error.message : String(error)}`);
|
|
277
|
+
// A registry-cache failure does not erase the installed version.
|
|
278
|
+
}
|
|
279
|
+
}
|
|
179
280
|
emit(phase, extra) {
|
|
180
281
|
this.safeBroadcast({ type: 'core_update.progress', phase, ...extra });
|
|
181
282
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.coreUpdatePendingPath = void 0;
|
|
7
|
+
exports.assertWorkspaceCoreReady = assertWorkspaceCoreReady;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const core_runtime_1 = require("./core-runtime");
|
|
11
|
+
const coreUpdatePendingPath = (workspace) => path_1.default.join(workspace, '.specrails', 'core-update-pending.json');
|
|
12
|
+
exports.coreUpdatePendingPath = coreUpdatePendingPath;
|
|
13
|
+
/** Reading the project remains available; only implementation setup calls this. */
|
|
14
|
+
function assertWorkspaceCoreReady(workspace, home) {
|
|
15
|
+
let pending = fs_1.default.existsSync((0, exports.coreUpdatePendingPath)(workspace));
|
|
16
|
+
// If a workspace was read-only and its marker could not be created, the
|
|
17
|
+
// durable global migration still prevents a launch using its old seed.
|
|
18
|
+
try {
|
|
19
|
+
const target = JSON.parse(fs_1.default.readFileSync(path_1.default.join((0, core_runtime_1.managedCoreRoot)(home), 'update-status.json'), 'utf8')).pendingVersion;
|
|
20
|
+
if (typeof target === 'string' && target) {
|
|
21
|
+
const recorded = fs_1.default.readFileSync(path_1.default.join(workspace, '.specrails', 'specrails-version'), 'utf8').trim();
|
|
22
|
+
pending ||= recorded !== target;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch { /* no pending global migration / uninstalled workspace */ }
|
|
26
|
+
if (pending) {
|
|
27
|
+
throw new Error('This project has an unfinished Core update. Retry the Core update in Settings before starting an implementation.');
|
|
28
|
+
}
|
|
29
|
+
}
|
package/server/dist/db.js
CHANGED
|
@@ -60,6 +60,10 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
60
60
|
const path_1 = __importDefault(require("path"));
|
|
61
61
|
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
62
62
|
const secure_fs_1 = require("./util/secure-fs");
|
|
63
|
+
const sqlite_migrations_1 = require("./util/sqlite-migrations");
|
|
64
|
+
const multi_repo_execution_store_1 = require("./multi-repo-execution-store");
|
|
65
|
+
const project_repository_provenance_1 = require("./project-repository-provenance");
|
|
66
|
+
const file_story_1 = require("./file-story");
|
|
63
67
|
/** Backfill only terminal Safe-PR rows whose ticket ownership is unambiguous.
|
|
64
68
|
* Eligibility is intentionally deferred to the outbox drainer, which freezes
|
|
65
69
|
* only candidates still parked at on_review in the external ticket JSON. */
|
|
@@ -1501,6 +1505,45 @@ const MIGRATIONS = [
|
|
|
1501
1505
|
db.exec(`ALTER TABLE rail_pr_deliveries ADD COLUMN revision_of TEXT`);
|
|
1502
1506
|
}
|
|
1503
1507
|
},
|
|
1508
|
+
// Migration 58: premium-milestone-progress — server-durable milestone launch
|
|
1509
|
+
// chains. One row per sequential "Launch Milestone": the chunk plan, the
|
|
1510
|
+
// chunk in flight (rail / runs / delivery), the branch the next chunk stacks
|
|
1511
|
+
// on, and a CAS status. The partial unique index enforces ONE non-terminal
|
|
1512
|
+
// chain per milestone. Additive; nothing else references it.
|
|
1513
|
+
(db) => {
|
|
1514
|
+
db.exec(`
|
|
1515
|
+
CREATE TABLE IF NOT EXISTS milestone_launch_chains (
|
|
1516
|
+
id TEXT PRIMARY KEY,
|
|
1517
|
+
milestone_n INTEGER NOT NULL,
|
|
1518
|
+
milestone_id TEXT NOT NULL,
|
|
1519
|
+
mode TEXT NOT NULL,
|
|
1520
|
+
chunks TEXT NOT NULL DEFAULT '[]',
|
|
1521
|
+
next_chunk INTEGER NOT NULL DEFAULT 0,
|
|
1522
|
+
current_rail_index INTEGER,
|
|
1523
|
+
current_run_ids TEXT NOT NULL DEFAULT '[]',
|
|
1524
|
+
current_delivery_id TEXT,
|
|
1525
|
+
integration_branch TEXT,
|
|
1526
|
+
head_branch TEXT,
|
|
1527
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
1528
|
+
pause_reason TEXT,
|
|
1529
|
+
launched TEXT NOT NULL DEFAULT '[]',
|
|
1530
|
+
last_run_outcome TEXT,
|
|
1531
|
+
auto_advance INTEGER NOT NULL DEFAULT 1,
|
|
1532
|
+
retry_chunk INTEGER,
|
|
1533
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1534
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1535
|
+
);
|
|
1536
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_milestone_chains_active
|
|
1537
|
+
ON milestone_launch_chains(milestone_n) WHERE status IN ('running','waiting','paused','awaiting_approval');
|
|
1538
|
+
CREATE INDEX IF NOT EXISTS idx_milestone_chains_status ON milestone_launch_chains(status);
|
|
1539
|
+
`);
|
|
1540
|
+
},
|
|
1541
|
+
// Migration 59: coordinated repository execution and grouped delivery.
|
|
1542
|
+
multi_repo_execution_store_1.migrateMultiRepoExecution,
|
|
1543
|
+
// Migration 60: repository-scoped provenance and code identity.
|
|
1544
|
+
project_repository_provenance_1.migrateRepositoryProvenance,
|
|
1545
|
+
// Migration 61: version and evidence identity of recorded-change explanations.
|
|
1546
|
+
file_story_1.migrateFileStoryMetadata,
|
|
1504
1547
|
];
|
|
1505
1548
|
function applyMigrations(db) {
|
|
1506
1549
|
// Ensure the migrations table exists (migration 1 creates it, but we need
|
|
@@ -1511,26 +1554,7 @@ function applyMigrations(db) {
|
|
|
1511
1554
|
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1512
1555
|
)
|
|
1513
1556
|
`);
|
|
1514
|
-
|
|
1515
|
-
.map((r) => r.version));
|
|
1516
|
-
for (let i = 0; i < MIGRATIONS.length; i++) {
|
|
1517
|
-
const version = i + 1;
|
|
1518
|
-
if (!appliedVersions.has(version)) {
|
|
1519
|
-
// M8: run each migration body and its version INSERT atomically. SQLite DDL
|
|
1520
|
-
// is transactional, so a crash/failure mid-migration now rolls back the
|
|
1521
|
-
// whole body instead of leaving a half-applied schema with the version
|
|
1522
|
-
// unrecorded — which under the old code re-ran a bare `ALTER TABLE ADD
|
|
1523
|
-
// COLUMN` on next startup and bricked it forever with 'duplicate column
|
|
1524
|
-
// name'. With this, a failed migration leaves nothing applied and re-runs
|
|
1525
|
-
// cleanly. (Pre-existing half-applied DBs are contained by the per-project
|
|
1526
|
-
// load isolation in project-registry.ts — one bad DB no longer kills the app.)
|
|
1527
|
-
const tx = db.transaction(() => {
|
|
1528
|
-
MIGRATIONS[i](db);
|
|
1529
|
-
db.prepare('INSERT OR IGNORE INTO schema_migrations (version) VALUES (?)').run(version);
|
|
1530
|
-
});
|
|
1531
|
-
tx();
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1557
|
+
(0, sqlite_migrations_1.applyNumberedMigrations)(db, MIGRATIONS);
|
|
1534
1558
|
}
|
|
1535
1559
|
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
1536
1560
|
function initDb(dbPath) {
|
|
@@ -1540,21 +1564,27 @@ function initDb(dbPath) {
|
|
|
1540
1564
|
(0, secure_fs_1.secureDir)(dir); // H-13: owner-only data dir
|
|
1541
1565
|
}
|
|
1542
1566
|
const db = new better_sqlite3_1.default(dbPath);
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1567
|
+
try {
|
|
1568
|
+
db.pragma('journal_mode = WAL');
|
|
1569
|
+
db.pragma('foreign_keys = ON');
|
|
1570
|
+
// Under load, QueueManager / ChatManager / FileSummaryManager write the same
|
|
1571
|
+
// per-project DB concurrently with /analytics reads. Wait up to 5s on a lock
|
|
1572
|
+
// instead of throwing SQLITE_BUSY, and cap the WAL so a long checkpoint can't
|
|
1573
|
+
// grow it without bound.
|
|
1574
|
+
db.pragma('busy_timeout = 5000');
|
|
1575
|
+
db.pragma('journal_size_limit = 10000000'); // ~10 MB
|
|
1576
|
+
applyMigrations(db);
|
|
1577
|
+
// H-13: restrict the db + its WAL sidecars to 0600 (jobs.sqlite holds chat
|
|
1578
|
+
// transcripts and verbatim terminal command history). After migrations the
|
|
1579
|
+
// WAL/SHM files exist, so this covers them too.
|
|
1580
|
+
(0, secure_fs_1.secureDbFile)(dbPath);
|
|
1581
|
+
// Orphan sweep: cancel any in-flight proposals from a previous server session
|
|
1582
|
+
db.prepare("UPDATE proposals SET status = 'cancelled', updated_at = ? WHERE status IN ('exploring', 'refining')").run(new Date().toISOString());
|
|
1583
|
+
}
|
|
1584
|
+
catch (err) {
|
|
1585
|
+
db.close();
|
|
1586
|
+
throw err;
|
|
1587
|
+
}
|
|
1558
1588
|
return db;
|
|
1559
1589
|
}
|
|
1560
1590
|
function createJob(db, job) {
|
|
@@ -2008,6 +2038,7 @@ exports.DEFAULT_FREESTYLE_PRE_PROMPT = [
|
|
|
2008
2038
|
'Work independently until the feature is done: write the code, the tests, update docs as needed, and make sure everything builds and the test suite passes.',
|
|
2009
2039
|
'Do NOT follow any structured architect/developer/reviewer pipeline — use your own judgement and the repo conventions.',
|
|
2010
2040
|
'Never ask for confirmation; there is no human to answer. Choose the recommended option and proceed.',
|
|
2041
|
+
'Run every command in the FOREGROUND and wait for it to finish — never background a command (no run_in_background, no trailing `&`): your reply ends the step and anything still running is killed with its output lost.',
|
|
2011
2042
|
].join('\n');
|
|
2012
2043
|
exports.WORKTREE_ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
2013
2044
|
const WORKTREE_ENV_MAX_NAMES = 64;
|