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
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.watchTool = watchTool;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
|
-
//
|
|
7
|
-
const TERMINAL_PATTERNS = [
|
|
6
|
+
// Exact event types that mean an async operation has settled.
|
|
7
|
+
const TERMINAL_PATTERNS = new Set([
|
|
8
8
|
'job.finalized',
|
|
9
9
|
'rail.job_completed',
|
|
10
10
|
'rail.job_stopped',
|
|
@@ -16,6 +16,7 @@ const TERMINAL_PATTERNS = [
|
|
|
16
16
|
'ticket_ai_edit_error',
|
|
17
17
|
'agent_refine_ready',
|
|
18
18
|
'agent_refine_error',
|
|
19
|
+
'agent_refine_cancelled',
|
|
19
20
|
'smash.completed',
|
|
20
21
|
'smash.failed',
|
|
21
22
|
'smash.undone',
|
|
@@ -24,31 +25,51 @@ const TERMINAL_PATTERNS = [
|
|
|
24
25
|
'explore.contract_refine_failed',
|
|
25
26
|
'file.summary_updated',
|
|
26
27
|
'file.summary_failed',
|
|
28
|
+
'file.summary_skipped',
|
|
27
29
|
'setup_install_done',
|
|
28
30
|
'setup_error',
|
|
29
31
|
'plugin.installed',
|
|
30
32
|
'plugin.degraded',
|
|
31
|
-
];
|
|
33
|
+
]);
|
|
32
34
|
// Job statuses that mean a polled job has settled (see project-router-jobs.ts).
|
|
33
|
-
const TERMINAL_JOB_STATUSES = new Set(['completed', 'failed', 'canceled']);
|
|
35
|
+
const TERMINAL_JOB_STATUSES = new Set(['completed', 'failed', 'canceled', 'skipped', 'zombie_terminated']);
|
|
34
36
|
// Jobs are identified by UUIDs (server/ids.ts newId → randomUUID). When the ref
|
|
35
37
|
// looks like one, the wait loop also polls the job read as a fallback for jobs
|
|
36
38
|
// that never emit a watch-terminal event (e.g. rail-bypass `spawn` jobs).
|
|
37
39
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
38
40
|
const JOB_POLL_INTERVAL_MS = 5000;
|
|
39
|
-
const TIMEOUT_SUGGESTION = 'timeout ≠ failure — the operation may still be running. Re-watch with the same ref, or poll specrails_jobs(get)/specrails_specs(get) for current state.';
|
|
41
|
+
const TIMEOUT_SUGGESTION = 'timeout ≠ failure — the operation may still be running. Re-watch with the same ref and kind, or poll specrails_jobs(get)/specrails_loops(run_get)/specrails_specs(get) for current state.';
|
|
40
42
|
function isTerminal(type) {
|
|
41
|
-
return TERMINAL_PATTERNS.
|
|
43
|
+
return TERMINAL_PATTERNS.has(type);
|
|
42
44
|
}
|
|
43
45
|
function mentionsRef(msg, ref) {
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
// Identity must match exactly: arbitrary log/output text can mention another
|
|
47
|
+
// operation, and "job-1" must never settle when "job-10" finishes.
|
|
48
|
+
const record = msg;
|
|
49
|
+
if (['jobId', 'processId', 'requestId', 'conversationId', 'loopRunId', 'refineId', 'runId', 'sessionId']
|
|
50
|
+
.some((key) => record[key] === ref))
|
|
51
|
+
return true;
|
|
52
|
+
if (msg.type.startsWith('plugin.'))
|
|
53
|
+
return record.name === ref;
|
|
54
|
+
if (msg.type.startsWith('file.'))
|
|
55
|
+
return record.path === ref;
|
|
56
|
+
if (msg.type.startsWith('setup_'))
|
|
57
|
+
return record.projectId === ref;
|
|
58
|
+
if (msg.type === 'smash.undone')
|
|
59
|
+
return String(record.ticketId) === ref;
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
const MAX_EVENT_BYTES = 16_000;
|
|
63
|
+
const MAX_BUFFER_BYTES = 256_000;
|
|
64
|
+
function boundedEvent(msg) {
|
|
65
|
+
const json = JSON.stringify(msg);
|
|
66
|
+
if (json.length <= MAX_EVENT_BYTES)
|
|
67
|
+
return { event: msg, bytes: json.length };
|
|
68
|
+
const record = msg;
|
|
69
|
+
const identity = Object.fromEntries(Object.entries(record).filter(([key, value]) => ['type', 'projectId', 'jobId', 'processId', 'requestId', 'conversationId', 'loopRunId', 'refineId', 'runId', 'sessionId', 'status', 'name', 'path'].includes(key)
|
|
70
|
+
&& typeof value === 'string').map(([key, value]) => [key, value.slice(0, 1024)]));
|
|
71
|
+
const event = { ...identity, truncated: true, originalLength: json.length, preview: json.slice(0, 6000) };
|
|
72
|
+
return { event, bytes: JSON.stringify(event).length };
|
|
52
73
|
}
|
|
53
74
|
function watchTool() {
|
|
54
75
|
return {
|
|
@@ -58,95 +79,167 @@ function watchTool() {
|
|
|
58
79
|
'and return its events. Pass the reference (jobId / requestId / conversationId / loopRunId) returned by the action; projectId is optional ' +
|
|
59
80
|
'(defaults to the active project; app-level operations need none). ' +
|
|
60
81
|
'Resolves when a terminal event for that reference is seen, or after untilMs. ' +
|
|
61
|
-
'
|
|
82
|
+
'Use kind:"job" or kind:"loop_run" for durable recovery: reads current state immediately, then every 5s, including operations that finished before this call. UUID refs auto-detect jobs/loop runs. ' +
|
|
62
83
|
'Default untilMs 120000 is often shorter than a rail run (max 600000). ' +
|
|
63
|
-
'settled
|
|
84
|
+
'settled means terminal, NOT necessarily successful; inspect terminalEvent.status/outcome. Events are bounded/truncated to protect context; other operation kinds only observe future events. ' +
|
|
85
|
+
'settled:false with reason:"timeout" means TIMEOUT, not failure — re-watch or poll the domain read. Cancellation stops waiting without stopping the operation. ' +
|
|
86
|
+
'A new message in the owning mission ends only this wait immediately with reason:"user_update" so the agent can incorporate it; the underlying job/rail keeps running.',
|
|
64
87
|
tier: 'read',
|
|
65
88
|
inputSchema: {
|
|
66
89
|
projectId: zod_1.z
|
|
67
90
|
.string()
|
|
68
91
|
.optional()
|
|
69
92
|
.describe('Project id the operation runs in (defaults to the active project; omit for app-level operations)'),
|
|
70
|
-
ref: zod_1.z.string().describe('jobId / requestId / conversationId / loopRunId returned by the async action'),
|
|
93
|
+
ref: zod_1.z.string().min(1).describe('Exact jobId / requestId / conversationId / loopRunId returned by the async action'),
|
|
71
94
|
untilMs: zod_1.z.number().int().min(1000).max(600000).default(120000).describe('Max time to wait (ms)'),
|
|
72
95
|
kind: zod_1.z
|
|
73
|
-
.enum(['job'])
|
|
96
|
+
.enum(['job', 'loop_run'])
|
|
74
97
|
.optional()
|
|
75
|
-
.describe('
|
|
98
|
+
.describe('Durable result type: job or loop_run. Reads immediately and every 5s, even for non-UUID ids. Omit to auto-detect UUID jobs/loops or listen for other event kinds.'),
|
|
76
99
|
},
|
|
77
100
|
handler: (ctx, args) => {
|
|
78
101
|
// Optional + active-project resolution: an explicit projectId wins, else
|
|
79
|
-
// the active project.
|
|
80
|
-
//
|
|
81
|
-
// operations carry no projectId at all.
|
|
102
|
+
// the active project. App-level operations can have neither; exact
|
|
103
|
+
// operation identity still filters their events.
|
|
82
104
|
const projectId = args.projectId ?? (0, types_1.getActiveProject)(ctx) ?? undefined;
|
|
83
105
|
const ref = args.ref;
|
|
84
106
|
const untilMs = args.untilMs ?? 120000;
|
|
85
|
-
const
|
|
107
|
+
const kind = args.kind;
|
|
108
|
+
if (kind && !projectId)
|
|
109
|
+
throw new Error('Watching a job or loop_run requires projectId or an active project. Select the project or pass projectId.');
|
|
110
|
+
const shouldPoll = kind !== undefined || UUID_RE.test(ref);
|
|
86
111
|
return new Promise((resolve) => {
|
|
112
|
+
const readController = new AbortController();
|
|
113
|
+
const readCtx = { ...ctx, signal: ctx.signal
|
|
114
|
+
? AbortSignal.any([ctx.signal, readController.signal])
|
|
115
|
+
: readController.signal };
|
|
87
116
|
const events = [];
|
|
117
|
+
let eventCount = 0;
|
|
118
|
+
let bufferBytes = 0;
|
|
88
119
|
let done = false;
|
|
120
|
+
let poller;
|
|
121
|
+
let timer;
|
|
122
|
+
let unsub = () => { };
|
|
123
|
+
let unsubMission = () => { };
|
|
124
|
+
const addEvent = (msg) => {
|
|
125
|
+
if (done)
|
|
126
|
+
return;
|
|
127
|
+
const entry = boundedEvent(msg);
|
|
128
|
+
events.push(entry);
|
|
129
|
+
eventCount++;
|
|
130
|
+
bufferBytes += entry.bytes;
|
|
131
|
+
while (events.length > 50 || bufferBytes > MAX_BUFFER_BYTES) {
|
|
132
|
+
bufferBytes -= events.shift().bytes;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const aborted = () => finish(false, 'canceled');
|
|
89
136
|
const finish = (settled, reason) => {
|
|
90
137
|
if (done)
|
|
91
138
|
return;
|
|
92
139
|
done = true;
|
|
140
|
+
readController.abort();
|
|
93
141
|
clearTimeout(timer);
|
|
94
142
|
if (poller)
|
|
95
143
|
clearInterval(poller);
|
|
96
144
|
unsub();
|
|
145
|
+
unsubMission();
|
|
146
|
+
ctx.signal?.removeEventListener('abort', aborted);
|
|
97
147
|
resolve({
|
|
98
148
|
settled,
|
|
99
149
|
reason,
|
|
100
150
|
ref,
|
|
101
151
|
projectId: projectId ?? null,
|
|
102
|
-
eventCount
|
|
103
|
-
terminalEvent: settled ? events[events.length - 1] : null,
|
|
104
|
-
events: events.
|
|
105
|
-
...(
|
|
152
|
+
eventCount,
|
|
153
|
+
terminalEvent: settled ? events[events.length - 1]?.event ?? null : null,
|
|
154
|
+
events: events.map((entry) => entry.event),
|
|
155
|
+
...(reason === 'user_update' ? { operationStopped: false } : {}),
|
|
156
|
+
...(settled ? {} : { suggestion: reason === 'user_update'
|
|
157
|
+
? 'Waiting ended because the user updated this mission; the operation was NOT stopped and may still be running. Incorporate the user instructions received through the active mission input channel, then decide the next action from current state.'
|
|
158
|
+
: reason === 'canceled'
|
|
159
|
+
? 'Waiting was canceled; the operation was not stopped. Read its current state before deciding the next action.'
|
|
160
|
+
: TIMEOUT_SUGGESTION }),
|
|
106
161
|
});
|
|
107
162
|
};
|
|
108
|
-
|
|
163
|
+
if (ctx.signal?.aborted) {
|
|
164
|
+
aborted();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
ctx.signal?.addEventListener('abort', aborted, { once: true });
|
|
168
|
+
unsub = ctx.eventBus.onMessage((msg) => {
|
|
169
|
+
if (done)
|
|
170
|
+
return;
|
|
109
171
|
const msgProjectId = msg.projectId;
|
|
110
172
|
if (projectId && msgProjectId && msgProjectId !== projectId)
|
|
111
173
|
return;
|
|
112
174
|
if (!mentionsRef(msg, ref))
|
|
113
175
|
return;
|
|
114
|
-
|
|
176
|
+
addEvent(msg);
|
|
115
177
|
const type = msg.type ?? '';
|
|
178
|
+
// A loop's final job accounting may precede its durable loop outcome.
|
|
179
|
+
// Explicit kinds must wait for their own lifecycle, even if ids match.
|
|
180
|
+
if (kind === 'loop_run' && !type.startsWith('loop.run_'))
|
|
181
|
+
return;
|
|
182
|
+
if (kind === 'job' && type !== 'job.finalized' && !type.startsWith('rail.job_'))
|
|
183
|
+
return;
|
|
116
184
|
if (isTerminal(type))
|
|
117
185
|
finish(true, `terminal:${type}`);
|
|
118
186
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
187
|
+
if (ctx.onMissionInput) {
|
|
188
|
+
unsubMission = ctx.onMissionInput(() => finish(false, 'user_update'));
|
|
189
|
+
// Registration can synchronously report an already-pending input.
|
|
190
|
+
// finish then ran before its disposer was assigned; release it now.
|
|
191
|
+
if (done) {
|
|
192
|
+
unsubMission();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Subscribe BEFORE reading durable state, closing the fast-completion
|
|
197
|
+
// race. Never overlap reads or let a late response resurrect this wait.
|
|
198
|
+
if (shouldPoll && projectId) {
|
|
126
199
|
let polling = false;
|
|
127
|
-
|
|
200
|
+
const poll = async () => {
|
|
128
201
|
if (done || polling)
|
|
129
202
|
return;
|
|
130
203
|
polling = true;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
204
|
+
try {
|
|
205
|
+
const base = `/projects/${encodeURIComponent(projectId)}`;
|
|
206
|
+
if (kind !== 'loop_run') {
|
|
207
|
+
const result = await (0, types_1.apiCall)(readCtx, 'GET', `${base}/jobs/${encodeURIComponent(ref)}`).catch(() => null);
|
|
208
|
+
if (done)
|
|
209
|
+
return;
|
|
210
|
+
const job = result?.job;
|
|
211
|
+
if (job) {
|
|
212
|
+
if (typeof job.status === 'string' && TERMINAL_JOB_STATUSES.has(job.status)) {
|
|
213
|
+
addEvent({ type: 'job.poll_settled', projectId, jobId: ref, status: job.status });
|
|
214
|
+
finish(true, `poll:job:${job.status}`);
|
|
215
|
+
}
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (kind === 'job')
|
|
220
|
+
return;
|
|
221
|
+
const result = await (0, types_1.apiCall)(readCtx, 'GET', `${base}/loop-runs/${encodeURIComponent(ref)}`);
|
|
222
|
+
if (done)
|
|
223
|
+
return;
|
|
224
|
+
const run = result?.loopRun;
|
|
225
|
+
if (run?.status === 'completed') {
|
|
226
|
+
addEvent({ type: 'loop.poll_settled', projectId, loopRunId: ref, status: run.status, outcome: run.final_outcome ?? null });
|
|
227
|
+
finish(true, `poll:loop_run:${run.final_outcome ?? run.status}`);
|
|
137
228
|
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
// Unknown ref / transient read failure: stay subscribed, retry.
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
143
234
|
polling = false;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
poller = setInterval(() => { void poll(); }, JOB_POLL_INTERVAL_MS);
|
|
146
238
|
if (typeof poller.unref === 'function')
|
|
147
239
|
poller.unref();
|
|
240
|
+
void poll();
|
|
148
241
|
}
|
|
149
|
-
|
|
242
|
+
timer = setTimeout(() => finish(false, 'timeout'), untilMs);
|
|
150
243
|
// Do not keep the event loop alive solely for this watch.
|
|
151
244
|
if (typeof timer.unref === 'function')
|
|
152
245
|
timer.unref();
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Durable milestone launch chains (premium-milestone-progress, migration 58).
|
|
3
|
+
//
|
|
4
|
+
// One row per "Launch Milestone" in sequential mode: the chunk plan, the
|
|
5
|
+
// chunk currently in flight (rail / runs / delivery), the branch the next
|
|
6
|
+
// chunk stacks on, and a compare-and-set status so a settle is never advanced
|
|
7
|
+
// twice. Replaces the browser-local localStorage plan that died with the
|
|
8
|
+
// window and never stacked chunks.
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.ACTIVE_CHAIN_STATUSES = void 0;
|
|
11
|
+
exports.isActiveChainStatus = isActiveChainStatus;
|
|
12
|
+
exports.createChain = createChain;
|
|
13
|
+
exports.getChain = getChain;
|
|
14
|
+
exports.listActiveChains = listActiveChains;
|
|
15
|
+
exports.listChains = listChains;
|
|
16
|
+
exports.parseChunks = parseChunks;
|
|
17
|
+
exports.parseLaunched = parseLaunched;
|
|
18
|
+
exports.parseRunIds = parseRunIds;
|
|
19
|
+
exports.listChainsTouchingDelivery = listChainsTouchingDelivery;
|
|
20
|
+
exports.updateChain = updateChain;
|
|
21
|
+
exports.toChainSnapshot = toChainSnapshot;
|
|
22
|
+
exports.pauseChainsForDiscardedHead = pauseChainsForDiscardedHead;
|
|
23
|
+
exports.ACTIVE_CHAIN_STATUSES = new Set(['running', 'waiting', 'paused', 'awaiting_approval']);
|
|
24
|
+
function isActiveChainStatus(status) {
|
|
25
|
+
return exports.ACTIVE_CHAIN_STATUSES.has(status);
|
|
26
|
+
}
|
|
27
|
+
function iso(nowMs) {
|
|
28
|
+
return new Date(nowMs ?? Date.now()).toISOString();
|
|
29
|
+
}
|
|
30
|
+
function createChain(db, input) {
|
|
31
|
+
const ts = iso(input.nowMs);
|
|
32
|
+
db.prepare(`
|
|
33
|
+
INSERT INTO milestone_launch_chains
|
|
34
|
+
(id, milestone_n, milestone_id, mode, chunks, next_chunk, current_run_ids, integration_branch, status, launched, auto_advance, created_at, updated_at)
|
|
35
|
+
VALUES (?, ?, ?, ?, ?, 0, '[]', ?, ?, '[]', ?, ?, ?)
|
|
36
|
+
`).run(input.id, input.milestoneN, input.milestoneId, input.mode, JSON.stringify(input.chunks), input.integrationBranch, input.status ?? 'running', input.autoAdvance === false ? 0 : 1, ts, ts);
|
|
37
|
+
return getChain(db, input.id);
|
|
38
|
+
}
|
|
39
|
+
function getChain(db, id) {
|
|
40
|
+
return db.prepare('SELECT * FROM milestone_launch_chains WHERE id = ?').get(id);
|
|
41
|
+
}
|
|
42
|
+
/** Non-terminal chains (running / waiting / paused / awaiting_approval), oldest first. */
|
|
43
|
+
function listActiveChains(db) {
|
|
44
|
+
return db.prepare(`
|
|
45
|
+
SELECT * FROM milestone_launch_chains
|
|
46
|
+
WHERE status IN ('running','waiting','paused','awaiting_approval')
|
|
47
|
+
ORDER BY created_at ASC, rowid ASC
|
|
48
|
+
`).all();
|
|
49
|
+
}
|
|
50
|
+
/** Every chain, newest first (progress projection picks the newest per milestone). */
|
|
51
|
+
function listChains(db) {
|
|
52
|
+
return db.prepare('SELECT * FROM milestone_launch_chains ORDER BY created_at DESC, rowid DESC').all();
|
|
53
|
+
}
|
|
54
|
+
function parseChunks(row) {
|
|
55
|
+
try {
|
|
56
|
+
const parsed = JSON.parse(row.chunks);
|
|
57
|
+
return Array.isArray(parsed) ? parsed.filter((c) => Array.isArray(c)) : [];
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function parseLaunched(row) {
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(row.launched);
|
|
66
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function parseRunIds(row) {
|
|
73
|
+
try {
|
|
74
|
+
const parsed = JSON.parse(row.current_run_ids);
|
|
75
|
+
return Array.isArray(parsed) ? parsed.filter((v) => typeof v === 'string') : [];
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Chains whose launched chunks include this delivery (any status). */
|
|
82
|
+
function listChainsTouchingDelivery(db, deliveryId) {
|
|
83
|
+
return listChains(db).filter((row) => parseLaunched(row).some((l) => l.deliveryId === deliveryId));
|
|
84
|
+
}
|
|
85
|
+
const PATCH_COLUMNS = {
|
|
86
|
+
nextChunk: 'next_chunk',
|
|
87
|
+
currentRailIndex: 'current_rail_index',
|
|
88
|
+
currentRunIds: 'current_run_ids',
|
|
89
|
+
currentDeliveryId: 'current_delivery_id',
|
|
90
|
+
headBranch: 'head_branch',
|
|
91
|
+
status: 'status',
|
|
92
|
+
pauseReason: 'pause_reason',
|
|
93
|
+
launched: 'launched',
|
|
94
|
+
lastRunOutcome: 'last_run_outcome',
|
|
95
|
+
autoAdvance: 'auto_advance',
|
|
96
|
+
retryChunk: 'retry_chunk',
|
|
97
|
+
};
|
|
98
|
+
function patchValue(key, patch) {
|
|
99
|
+
const raw = patch[key];
|
|
100
|
+
if (key === 'currentRunIds' || key === 'launched')
|
|
101
|
+
return JSON.stringify(raw ?? []);
|
|
102
|
+
if (key === 'autoAdvance')
|
|
103
|
+
return raw ? 1 : 0;
|
|
104
|
+
return raw ?? null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Compare-and-set update: applies only while the row's status is one of
|
|
108
|
+
* `expected` (a string or a list). Returns true when a row changed.
|
|
109
|
+
*/
|
|
110
|
+
function updateChain(db, id, expected, patch, nowMs) {
|
|
111
|
+
const keys = Object.keys(patch).filter((k) => patch[k] !== undefined);
|
|
112
|
+
const setClause = keys.map((k) => `${PATCH_COLUMNS[k]} = ?`).concat('updated_at = ?').join(', ');
|
|
113
|
+
const values = keys.map((k) => patchValue(k, patch));
|
|
114
|
+
const expectedList = Array.isArray(expected) ? expected : [expected];
|
|
115
|
+
const placeholders = expectedList.map(() => '?').join(', ');
|
|
116
|
+
return db.prepare(`UPDATE milestone_launch_chains SET ${setClause} WHERE id = ? AND status IN (${placeholders})`)
|
|
117
|
+
.run(...values, iso(nowMs), id, ...expectedList).changes > 0;
|
|
118
|
+
}
|
|
119
|
+
function toChainSnapshot(row) {
|
|
120
|
+
return {
|
|
121
|
+
id: row.id,
|
|
122
|
+
milestoneN: row.milestone_n,
|
|
123
|
+
mode: row.mode,
|
|
124
|
+
status: row.status,
|
|
125
|
+
pauseReason: row.pause_reason,
|
|
126
|
+
autoAdvance: row.auto_advance !== 0,
|
|
127
|
+
nextChunk: row.next_chunk,
|
|
128
|
+
totalChunks: parseChunks(row).length,
|
|
129
|
+
currentRailIndex: row.current_rail_index,
|
|
130
|
+
headBranch: row.head_branch,
|
|
131
|
+
launched: parseLaunched(row),
|
|
132
|
+
updatedAt: row.updated_at,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* A delivery that a chain's later chunks build on was discarded by the user:
|
|
137
|
+
* pause every active chain whose launched chunks include it, and rewind the
|
|
138
|
+
* head to the previous launched chunk's delivery (`resolveBranch`), else null
|
|
139
|
+
* (= the integration branch). Returns the rows it paused.
|
|
140
|
+
*/
|
|
141
|
+
function pauseChainsForDiscardedHead(db, deliveryId, resolveBranch, nowMs) {
|
|
142
|
+
const paused = [];
|
|
143
|
+
for (const row of listActiveChains(db)) {
|
|
144
|
+
const launched = parseLaunched(row);
|
|
145
|
+
const idx = launched.findIndex((l) => l.deliveryId === deliveryId);
|
|
146
|
+
if (idx < 0)
|
|
147
|
+
continue;
|
|
148
|
+
let previous = null;
|
|
149
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
150
|
+
const id = launched[i].deliveryId;
|
|
151
|
+
if (!id)
|
|
152
|
+
continue;
|
|
153
|
+
previous = resolveBranch(id);
|
|
154
|
+
if (previous)
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
if (updateChain(db, row.id, row.status, { status: 'paused', pauseReason: 'head_discarded', headBranch: previous }, nowMs)) {
|
|
158
|
+
const fresh = getChain(db, row.id);
|
|
159
|
+
if (fresh)
|
|
160
|
+
paused.push(fresh);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return paused;
|
|
164
|
+
}
|