specrails-desktop 2.57.0 → 2.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/cli/dist/args.js +10 -4
- package/cli/dist/help.js +1 -1
- package/client/dist/assets/{ActivityFeedPage-DdMNmVBk.js → ActivityFeedPage-BQGppIR0.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-CeerUf--.js → AgentBrowserCapture-PI-cxyxi.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-BjGb-8rh.js → AgentModeAnalyticsPane-mQsOqdXx.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-8XRkQEo_.js → AgentModeCodePane-BL-vpmlY.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-BN3dgJOA.js → AgentModeJobsPane-DR_06oqH.js} +1 -1
- package/client/dist/assets/AgentsPage-BKIKjm_1.js +118 -0
- package/client/dist/assets/{AnalyticsPage-CyfhYiBn.js → AnalyticsPage-069npRVo.js} +1 -1
- package/client/dist/assets/{CodePage-C2Nf-Q5W.js → CodePage-Alitorrv.js} +2 -2
- package/client/dist/assets/DesktopAnalyticsPage-qtWAPM47.js +1 -0
- package/client/dist/assets/{DocsDialog-Br3bczCp.js → DocsDialog-DwL6rgcT.js} +1 -1
- package/client/dist/assets/{DocsPage-BcDr2cBm.js → DocsPage-BA1hiJZ-.js} +1 -1
- package/client/dist/assets/{ExportDropdown-BVGKEgkd.js → ExportDropdown-BcMpvV89.js} +1 -1
- package/client/dist/assets/InteractiveJobComposer-B3H1YHr6.js +19 -0
- package/client/dist/assets/JobDetailModal-XZQ9eAAy.js +1 -0
- package/client/dist/assets/{JobDetailPage-vBbNeRuz.js → JobDetailPage-B-SIaq_q.js} +1 -1
- package/client/dist/assets/{JobsPage-CJCtPhIz.js → JobsPage-iQXAv2mx.js} +1 -1
- package/client/dist/assets/LoopBuilderPage-B_gbFAHn.js +1 -0
- package/client/dist/assets/LoopPreviewModal-je5pSCf-.js +1 -0
- package/client/dist/assets/LoopsPage-BZwcY5cu.js +2 -0
- package/client/dist/assets/{MinimizedChatsContext-D3QzgV0B.js → MinimizedChatsContext-CNx_0bZu.js} +1 -1
- package/client/dist/assets/{PluginsPage-DOpTV75p.js → PluginsPage-DFocnoHX.js} +2 -2
- package/client/dist/assets/{ProjectSettingsDialog-Dkwrn0z1.js → ProjectSettingsDialog-Bh3S6EBB.js} +1 -1
- package/client/dist/assets/{RepositoryDeliveries-Du2UCf1a.js → RepositoryDeliveries-BiwJuS8r.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-hPGZNRBm.js → RepositoryScopeSelector-C2mvWBQ6.js} +1 -1
- package/client/dist/assets/{ReviewPacketPage-DcOq-UTA.js → ReviewPacketPage-CrAf-WDy.js} +2 -2
- package/client/dist/assets/TemplatePreviewModal-C7DordpN.js +1 -0
- package/client/dist/assets/{TicketDetailModalContext-DAK-NoK6.js → TicketDetailModalContext-B-DySpKL.js} +1 -1
- package/client/dist/assets/{Trans-DEbgkuAY.js → Trans-D3AfDylf.js} +1 -1
- package/client/dist/assets/agentRuntime-BeUb3g9g.js +1 -0
- package/client/dist/assets/agentRuntime-Bg9tbmqm.js +1 -0
- package/client/dist/assets/agentRuntime-D-GJVGkj.js +1 -0
- package/client/dist/assets/agentRuntime-D2__CVI_.js +1 -0
- package/client/dist/assets/agentRuntime-D35dGVOP.js +1 -0
- package/client/dist/assets/agentRuntime-DGz_IqKW.js +1 -0
- package/client/dist/assets/agentRuntime-O1liDt6G.js +1 -0
- package/client/dist/assets/agentRuntime-hInH9Fzj.js +1 -0
- package/client/dist/assets/agentstudio-B2CTtQgZ.js +1 -0
- package/client/dist/assets/agentstudio-BWAKeGgB.js +1 -0
- package/client/dist/assets/{agentstudio-DR7doNBV.js → agentstudio-Cja8Sjcp.js} +1 -1
- package/client/dist/assets/agentstudio-DtfPcr99.js +1 -0
- package/client/dist/assets/agentstudio-QdAJIDef.js +1 -0
- package/client/dist/assets/agentstudio-X70BKf6u.js +1 -0
- package/client/dist/assets/agentstudio-fLXpRGIi.js +1 -0
- package/client/dist/assets/agentstudio-qXKqVnWS.js +1 -0
- package/client/dist/assets/{analytics-jzCkOec3.js → analytics-B1DIQd4m.js} +1 -1
- package/client/dist/assets/{analytics-CoEzWPx4.js → analytics-BAIZ9vE_.js} +1 -1
- package/client/dist/assets/{analytics-DjLlE7jS.js → analytics-BTqgmgBd.js} +1 -1
- package/client/dist/assets/analytics-BWynXPEm.js +1 -0
- package/client/dist/assets/{analytics-nZIjjtCc.js → analytics-DGcUsQ44.js} +1 -1
- package/client/dist/assets/{analytics-BNgZ1Nj7.js → analytics-GnSnpJ4W.js} +1 -1
- package/client/dist/assets/{analytics-DFh5lSOl.js → analytics-TWgYaoO0.js} +1 -1
- package/client/dist/assets/{analytics-DZp-DS2U.js → analytics-kJy6Tuko.js} +1 -1
- package/client/dist/assets/builder-C0FyvM83.js +1 -0
- package/client/dist/assets/builder-C1neIYGR.js +1 -0
- package/client/dist/assets/builder-CvnFm0im.js +1 -0
- package/client/dist/assets/builder-CzW5ovyI.js +1 -0
- package/client/dist/assets/builder-D06L7iPy.js +1 -0
- package/client/dist/assets/builder-DGETbtZj.js +1 -0
- package/client/dist/assets/builder-DXEJUlC0.js +1 -0
- package/client/dist/assets/builder-DyQperXU.js +1 -0
- package/client/dist/assets/common-BCK7c9Pv.js +1 -0
- package/client/dist/assets/common-C0BOdeNi.js +1 -0
- package/client/dist/assets/common-C4Yvvhp6.js +1 -0
- package/client/dist/assets/{common-BrlwEnL7.js → common-DmsclwjP.js} +1 -1
- package/client/dist/assets/common-DpLWwgI1.js +1 -0
- package/client/dist/assets/common-OCvl3c8t.js +1 -0
- package/client/dist/assets/common-c0aujEZC.js +1 -0
- package/client/dist/assets/common-od8WThlf.js +1 -0
- package/client/dist/assets/dashboard-B1ndRHuC.js +1 -0
- package/client/dist/assets/dashboard-BX7KXiqA.js +1 -0
- package/client/dist/assets/dashboard-B_BSNxcN.js +1 -0
- package/client/dist/assets/dashboard-CCeFN7-V.js +1 -0
- package/client/dist/assets/dashboard-CRl0WtFJ.js +1 -0
- package/client/dist/assets/dashboard-XGdQ5mjw.js +1 -0
- package/client/dist/assets/dashboard-_oltA6Jd.js +1 -0
- package/client/dist/assets/dashboard-bAuf5KVk.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-Cc2u5FwQ.js → formatDistanceToNow-aBss1Nai.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-BHm2U-w1.js → getTimezoneOffsetInMilliseconds-DOGj1Mfz.js} +1 -1
- package/client/dist/assets/index-BS7KCWkV.css +2 -0
- package/client/dist/assets/{index-Cxb288Rj.js → index-C4Mv6tV6.js} +32 -32
- package/client/dist/assets/{jira-api-DrGxiD9p.js → jira-api-BYbEPlkr.js} +1 -1
- package/client/dist/assets/{jobs-DSp9DoD_.js → jobs-6_-r75yC.js} +1 -1
- package/client/dist/assets/{jobs-C6qmvUAi.js → jobs-B1yqyId5.js} +1 -1
- package/client/dist/assets/{jobs-DoFaEl9g.js → jobs-BFuV7ttH.js} +1 -1
- package/client/dist/assets/{jobs-DTQO08nJ.js → jobs-BKa8LuwA.js} +1 -1
- package/client/dist/assets/{jobs-DrF8Do8s.js → jobs-BKiK-ZWh.js} +1 -1
- package/client/dist/assets/{jobs-DLHdDkHc.js → jobs-DmKV7b7d.js} +1 -1
- package/client/dist/assets/{jobs-C9j2PuwW.js → jobs-KG4Sn12X.js} +1 -1
- package/client/dist/assets/{jobs-Dpw6AEOP.js → jobs-pPv4KWjb.js} +1 -1
- package/client/dist/assets/loop-layout-BF8xMiNv.js +7 -0
- package/client/dist/assets/loops-B4_D-nbg.js +1 -0
- package/client/dist/assets/loops-BJDY9FTh.js +1 -0
- package/client/dist/assets/loops-BO3V8244.js +1 -0
- package/client/dist/assets/loops-C-hZK8pf.js +1 -0
- package/client/dist/assets/loops-CDOWZ0ci.js +1 -0
- package/client/dist/assets/loops-Dv849ckF.js +1 -0
- package/client/dist/assets/loops-Q9LIgGkq.js +1 -0
- package/client/dist/assets/loops-eUnCfLjC.js +1 -0
- package/client/dist/assets/{project-repositories-9Wzs0coQ.js → project-repositories-CSnfzUpg.js} +1 -1
- package/client/dist/assets/settings-3o4Ntzi5.js +1 -0
- package/client/dist/assets/settings-B97jlkwD.js +1 -0
- package/client/dist/assets/settings-BTaT_bsS.js +1 -0
- package/client/dist/assets/settings-CT8w7WiC.js +1 -0
- package/client/dist/assets/settings-Cvr8_tvh.js +1 -0
- package/client/dist/assets/settings-Dn1qgAC8.js +1 -0
- package/client/dist/assets/settings-EShDdg4J.js +1 -0
- package/client/dist/assets/settings-tfLhQZRN.js +1 -0
- package/client/dist/assets/{setup-Dwzt5nO1.js → setup-CBMu3tqH.js} +1 -1
- package/client/dist/assets/{setup-B5FHuxvB.js → setup-CPh-e6J2.js} +1 -1
- package/client/dist/assets/{setup-DpqzaEEA.js → setup-CRKLp_ke.js} +1 -1
- package/client/dist/assets/{setup-CROyqD5N.js → setup-Cy302v4J.js} +1 -1
- package/client/dist/assets/{setup-C9Fy9PKQ.js → setup-D681vTPf.js} +1 -1
- package/client/dist/assets/{setup-BihzXadx.js → setup-DYK0VBkE.js} +1 -1
- package/client/dist/assets/{setup-BtC6Hg4K.js → setup-KAuiIiVs.js} +1 -1
- package/client/dist/assets/{setup-zLEDnG7N.js → setup-OGX-oCfI.js} +1 -1
- package/client/dist/assets/{spending-T5GM7wpn.js → spending-HBSk-6jv.js} +1 -1
- package/client/dist/assets/{useDesktop-QogiN0zR.js → useDesktop-0unHDBJJ.js} +1 -1
- package/client/dist/assets/useRuntimeRuns-BN1rhyEm.js +1 -0
- package/client/dist/assets/{useSharedWebSocket-Dz-HI6De.js → useSharedWebSocket-BZMrX4jr.js} +2 -2
- package/client/dist/index.html +25 -25
- package/docs/agent-live-steering.md +16 -0
- package/docs/cli.md +7 -7
- package/docs/codex.md +2 -2
- package/docs/customizing.md +1 -1
- package/docs/gemini.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/guide/de/integrations/7-local-engines.md +1 -1
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/de/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/en/integrations/7-local-engines.md +1 -1
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/en/pipeline/5-the-loop-builder.md +34 -5
- package/docs/guide/en/settings/3-pipeline-telemetry-and-diagnostics.md +1 -1
- package/docs/guide/es/integrations/7-local-engines.md +1 -1
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/es/pipeline/5-the-loop-builder.md +30 -5
- package/docs/guide/es/settings/3-pipeline-telemetry-and-diagnostics.md +1 -2
- package/docs/guide/fr/integrations/7-local-engines.md +1 -1
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/it/integrations/7-local-engines.md +1 -1
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/it/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/ja/integrations/7-local-engines.md +1 -1
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/pt/integrations/7-local-engines.md +1 -1
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/zh/integrations/7-local-engines.md +1 -1
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +24 -5
- package/docs/internals/api-reference.md +2 -2
- package/docs/internals/ci-performance.md +71 -0
- package/docs/internals/companion-rails-as-loops-contract.md +4 -3
- package/docs/internals/configuration.md +3 -3
- package/docs/internals/core-runtime-updates.md +3 -2
- package/docs/internals/interactive-jobs.md +2 -2
- package/docs/internals/loop-step-log-explorer.md +42 -0
- package/docs/internals/mission-rail-cards.md +1 -1
- package/docs/internals/operations-runbook.md +22 -0
- package/docs/internals/programmatic-agent-runtime.md +130 -7
- package/docs/internals/project-builder.md +35 -16
- package/docs/internals/source-map.md +48 -2
- package/docs/kimi.md +2 -2
- package/docs/local-providers.md +1 -1
- package/docs/running-pipelines.md +26 -18
- package/docs/tracking-cost.md +10 -1
- package/package.json +2 -1
- package/server/dist/core-compat.js +8 -3
- package/server/dist/core-execution.js +49 -3
- package/server/dist/db/migrations.js +101 -0
- package/server/dist/desktop-db.js +28 -0
- package/server/dist/desktop-router.js +2 -0
- package/server/dist/mcp/guide.js +6 -3
- package/server/dist/mcp/tools/jobs.js +14 -1
- package/server/dist/mcp/tools/loops.js +17 -8
- package/server/dist/mcp/tools/rails.js +3 -3
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +313 -9
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-controls-router.js +34 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-controls.js +203 -21
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-effective-config.js +46 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-engines.js +10 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-loader.js +68 -3
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +16 -8
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-package-gc.js +81 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-package-lock.js +37 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-package.js +30 -24
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention-host.js +87 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention-quarantine.js +231 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention-records.js +32 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention.js +102 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +12 -7
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +57 -13
- package/server/dist/modules/agents/runtime/agent-catalog.js +32 -0
- package/server/dist/modules/agents/runtime/agent-refine-manager.js +12 -0
- package/server/dist/modules/agents/runtime/agent-role-descriptor.js +64 -0
- package/server/dist/modules/agents/runtime/profiles-router.js +26 -34
- package/server/dist/modules/builder/runtime/milestone-chain.js +121 -73
- package/server/dist/modules/delivery/runtime/definition-fork.js +158 -0
- package/server/dist/modules/delivery/runtime/delivery-evidence.js +56 -10
- package/server/dist/modules/delivery/runtime/isolated-settlement-reconstruction.js +99 -0
- package/server/dist/modules/delivery/runtime/isolated-settlement-store.js +53 -0
- package/server/dist/modules/delivery/runtime/multi-repo-execution-store.js +3 -1
- package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +388 -203
- package/server/dist/modules/delivery/runtime/rail-launch-parser.js +3 -2
- package/server/dist/modules/delivery/runtime/rail-pr-store.js +6 -1
- package/server/dist/modules/delivery/runtime/rails-router.js +66 -10
- package/server/dist/modules/execution/runtime/queue-manager.js +11 -2
- package/server/dist/modules/loops/runtime/builtin-loops.js +70 -0
- package/server/dist/modules/loops/runtime/definition-cancellation.js +31 -0
- package/server/dist/modules/loops/runtime/legacy-launch-telemetry.js +78 -0
- package/server/dist/modules/loops/runtime/loop-command-catalog.js +13 -12
- package/server/dist/modules/loops/runtime/loop-compat.js +219 -0
- package/server/dist/modules/loops/runtime/loop-core-factory.js +42 -0
- package/server/dist/modules/loops/runtime/loop-definition-controls.js +48 -0
- package/server/dist/modules/loops/runtime/loop-definition-events.js +145 -0
- package/server/dist/modules/loops/runtime/loop-definition-recovery.js +106 -0
- package/server/dist/modules/loops/runtime/loop-definition-run.js +36 -0
- package/server/dist/modules/loops/runtime/loop-definition.js +246 -0
- package/server/dist/modules/loops/runtime/loop-effect.js +10 -1
- package/server/dist/modules/loops/runtime/loop-executors.js +63 -3
- package/server/dist/modules/loops/runtime/loop-factory.js +35 -15
- package/server/dist/modules/loops/runtime/loop-graph.js +84 -8
- package/server/dist/modules/loops/runtime/loop-migration.js +36 -0
- package/server/dist/modules/loops/runtime/loop-preview.js +10 -0
- package/server/dist/modules/loops/runtime/loop-run-manager.js +206 -13
- package/server/dist/modules/loops/runtime/loop-runs-store.js +271 -7
- package/server/dist/modules/loops/runtime/loop-templates.js +205 -45
- package/server/dist/modules/loops/runtime/loops-router.js +246 -29
- package/server/dist/modules/loops/runtime/loops-store.js +140 -20
- package/server/dist/modules/missions/runtime/agent-operator-prompt.js +14 -11
- package/server/dist/modules/specs/runtime/spec-addenda.js +28 -0
- package/server/dist/project-registry.js +87 -51
- package/server/dist/project-router-jobs.js +17 -6
- package/server/dist/project-router-loop-runs.js +200 -0
- package/server/dist/project-router-spending.js +17 -0
- package/server/dist/project-router.js +8 -6
- package/server/dist/schemas/agent-runtime.schema.json +93 -1
- package/server/dist/schemas/workflow-definition.schema.json +312 -0
- package/server/dist/vitest-setup.js +22 -0
- package/server/dist/worktree-overlay.js +1 -1
- package/client/dist/assets/AgentsPage-DfHWgP_x.js +0 -87
- package/client/dist/assets/DesktopAnalyticsPage-tc0p4jJW.js +0 -1
- package/client/dist/assets/InteractiveJobComposer-DFPpdg2D.js +0 -19
- package/client/dist/assets/JobDetailModal-BdOv-l-M.js +0 -1
- package/client/dist/assets/LoopBuilderPage-BemvUOxy.js +0 -7
- package/client/dist/assets/LoopPreviewModal-C6hNAeYN.js +0 -1
- package/client/dist/assets/LoopsPage-BZr0quvh.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-Cejcquah.js +0 -1
- package/client/dist/assets/agentRuntime-BUimiX__.js +0 -1
- package/client/dist/assets/agentRuntime-BcN97sAB.js +0 -1
- package/client/dist/assets/agentRuntime-Ckyg-ahT.js +0 -1
- package/client/dist/assets/agentRuntime-DJCwyX4t.js +0 -1
- package/client/dist/assets/agentRuntime-DVzPJOl0.js +0 -1
- package/client/dist/assets/agentRuntime-V9AZTG3c.js +0 -1
- package/client/dist/assets/agentRuntime-bAAjw1vw.js +0 -1
- package/client/dist/assets/agentRuntime-v4qKAYH-.js +0 -1
- package/client/dist/assets/agentstudio-BNUth0uj.js +0 -1
- package/client/dist/assets/agentstudio-BNdB5hkr.js +0 -1
- package/client/dist/assets/agentstudio-C7-bt8FO.js +0 -1
- package/client/dist/assets/agentstudio-C8uNchpV.js +0 -1
- package/client/dist/assets/agentstudio-CKabyMlg.js +0 -1
- package/client/dist/assets/agentstudio-CN2pokQu.js +0 -1
- package/client/dist/assets/agentstudio-y2dVDXeM.js +0 -1
- package/client/dist/assets/analytics-BlypLLR6.js +0 -1
- package/client/dist/assets/builder-765NeYTp.js +0 -1
- package/client/dist/assets/builder-8MG3V6ea.js +0 -1
- package/client/dist/assets/builder-B-1UBs5K.js +0 -1
- package/client/dist/assets/builder-BTiGnPT0.js +0 -1
- package/client/dist/assets/builder-Cx9Rz-7u.js +0 -1
- package/client/dist/assets/builder-DKFMELBl.js +0 -1
- package/client/dist/assets/builder-OcmKrC0h.js +0 -1
- package/client/dist/assets/builder-P9qVBXFZ.js +0 -1
- package/client/dist/assets/common-B5AZNYMH.js +0 -1
- package/client/dist/assets/common-BFZ0c_vN.js +0 -1
- package/client/dist/assets/common-BttQx3z4.js +0 -1
- package/client/dist/assets/common-CM65k_-e.js +0 -1
- package/client/dist/assets/common-D4mvFFlu.js +0 -1
- package/client/dist/assets/common-TZ9Ny96S.js +0 -1
- package/client/dist/assets/common-nFpSF4GC.js +0 -1
- package/client/dist/assets/dashboard-B9uWNGO2.js +0 -1
- package/client/dist/assets/dashboard-BIwmO9wc.js +0 -1
- package/client/dist/assets/dashboard-BV4vOZkR.js +0 -1
- package/client/dist/assets/dashboard-Bf6MPVsM.js +0 -1
- package/client/dist/assets/dashboard-C8klWVvZ.js +0 -1
- package/client/dist/assets/dashboard-D1ORhPF0.js +0 -1
- package/client/dist/assets/dashboard-DSubvs9x.js +0 -1
- package/client/dist/assets/dashboard-px_vlRx_.js +0 -1
- package/client/dist/assets/index-C51x61Bz.css +0 -2
- package/client/dist/assets/loops-B7YpGizO.js +0 -1
- package/client/dist/assets/loops-BomD2J-h.js +0 -1
- package/client/dist/assets/loops-BrQHSQw3.js +0 -1
- package/client/dist/assets/loops-BvBwvTPA.js +0 -1
- package/client/dist/assets/loops-CODk6Slz.js +0 -1
- package/client/dist/assets/loops-DC6k-Ym-.js +0 -1
- package/client/dist/assets/loops-DSEg8-uY.js +0 -1
- package/client/dist/assets/loops-DhCoXD_v.js +0 -1
- package/client/dist/assets/settings-BsehKpty.js +0 -1
- package/client/dist/assets/settings-CQWob3SB.js +0 -1
- package/client/dist/assets/settings-CgCl0hzy.js +0 -1
- package/client/dist/assets/settings-DLRLd22L.js +0 -1
- package/client/dist/assets/settings-Dn5prAFl.js +0 -1
- package/client/dist/assets/settings-HZSu-K4l.js +0 -1
- package/client/dist/assets/settings-p4OVIyRh.js +0 -1
- package/client/dist/assets/settings-rddaldUp.js +0 -1
- package/client/dist/assets/useRuntimeRuns-Dqmz9fS9.js +0 -1
- package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +0 -126
- package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +0 -114
- package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/server/dist/modules/loops/runtime/loop-templates-ported.js +0 -675
- /package/client/dist/assets/{LoopBuilderPage-DtxX27Jz.css → loop-layout-DtxX27Jz.css} +0 -0
|
@@ -22,7 +22,7 @@ const json_tolerant_1 = require("../../../json-tolerant");
|
|
|
22
22
|
const pr_follow_up_scope_1 = require("./pr-follow-up-scope");
|
|
23
23
|
exports.RAIL_LAUNCH_FENCE = 'rail-launch';
|
|
24
24
|
exports.RAIL_LAUNCH_PROPOSAL_VERSION = 1;
|
|
25
|
-
exports.RAIL_LAUNCH_MODES = ['implement', '
|
|
25
|
+
exports.RAIL_LAUNCH_MODES = ['implement', 'freestyle', 'loop'];
|
|
26
26
|
const FENCE_RE = /```rail-launch[^\S\n]*\n([\s\S]*?)\n[^\S\n]*```/g;
|
|
27
27
|
const OPEN_FENCE = '```rail-launch';
|
|
28
28
|
const EXCERPT_MAX = 160;
|
|
@@ -71,7 +71,8 @@ function coerceRailLaunchProposal(value) {
|
|
|
71
71
|
if (ticketIds.length === 0)
|
|
72
72
|
return { ok: false, reason: 'no_tickets' };
|
|
73
73
|
const modeRaw = optString(value.mode)?.toLowerCase().replace(/_/g, '-') ?? 'implement';
|
|
74
|
-
|
|
74
|
+
// The removed Batch mode folds into implement (one aggregate run per rail).
|
|
75
|
+
const mode = modeRaw === 'batch' || modeRaw === 'batch-implement' ? 'implement' : modeRaw;
|
|
75
76
|
if (!exports.RAIL_LAUNCH_MODES.includes(mode))
|
|
76
77
|
return { ok: false, reason: 'invalid_mode' };
|
|
77
78
|
const newRailRaw = value.newRail;
|
|
@@ -322,11 +322,16 @@ function reconcileFailedBuildingPrDeliveries(db, opts = {}) {
|
|
|
322
322
|
const uniqueRunIds = [...new Set(runIds)];
|
|
323
323
|
const placeholders = uniqueRunIds.map(() => '?').join(',');
|
|
324
324
|
const runs = db
|
|
325
|
-
.prepare(`SELECT id, status, final_outcome FROM loop_runs WHERE id IN (${placeholders})`)
|
|
325
|
+
.prepare(`SELECT id, status, final_outcome, engine_version, restart_reason FROM loop_runs WHERE id IN (${placeholders})`)
|
|
326
326
|
.all(...uniqueRunIds);
|
|
327
327
|
if (runs.length !== uniqueRunIds.length || runs.some((run) => run.status !== 'completed')) {
|
|
328
328
|
if (!opts.startup)
|
|
329
329
|
continue;
|
|
330
|
+
if (runs.length === uniqueRunIds.length && runs.some(run => run.engine_version === 2 && run.status === 'paused' && run.restart_reason === 'restart') && runs.every(run => run.status === 'completed' || run.engine_version === 2 && run.status === 'paused' && run.restart_reason === 'restart')) {
|
|
331
|
+
db.prepare("UPDATE rail_pr_deliveries SET status_code='restart_pending', status_detail=? WHERE id=? AND decision='building'")
|
|
332
|
+
.run('The retained Core execution awaits recovery or delivery settlement after restart.', row.id);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
330
335
|
if (transitionDecision(db, row.id, 'building', 'pr_failed', {
|
|
331
336
|
implementationOutcome: 'unknown',
|
|
332
337
|
deliveryOutcome: 'blocked',
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.normalizeRailMode = normalizeRailMode;
|
|
6
7
|
exports.prDeliveryRevisionAllowed = prDeliveryRevisionAllowed;
|
|
7
8
|
exports.createRailsRouter = createRailsRouter;
|
|
8
9
|
const pr_follow_up_1 = require("./pr-follow-up");
|
|
@@ -25,7 +26,9 @@ const agent_defaults_1 = require("../../agents/runtime/agent-defaults");
|
|
|
25
26
|
const profile_manager_1 = require("../../agents/runtime/profile-manager");
|
|
26
27
|
const spec_models_1 = require("../../specs/runtime/spec-models");
|
|
27
28
|
const workspace_resolution_1 = require("../../../workspace-resolution");
|
|
29
|
+
const agent_runtime_loader_1 = require("../../agent-runtime/runtime/agent-runtime-loader");
|
|
28
30
|
const loop_factory_1 = require("../../loops/runtime/loop-factory");
|
|
31
|
+
const builtin_loops_1 = require("../../loops/runtime/builtin-loops");
|
|
29
32
|
const loop_constants_1 = require("../../loops/runtime/loop-constants");
|
|
30
33
|
const loop_command_catalog_1 = require("../../loops/runtime/loop-command-catalog");
|
|
31
34
|
const loop_graph_1 = require("../../loops/runtime/loop-graph");
|
|
@@ -34,6 +37,7 @@ const rail_pr_store_1 = require("./rail-pr-store");
|
|
|
34
37
|
const loop_effect_1 = require("../../loops/runtime/loop-effect");
|
|
35
38
|
const review_packet_1 = require("./review-packet");
|
|
36
39
|
const delivery_evidence_1 = require("./delivery-evidence");
|
|
40
|
+
const loop_definition_recovery_1 = require("../../loops/runtime/loop-definition-recovery");
|
|
37
41
|
const accept_ladder_1 = require("../../execution/runtime/accept-ladder");
|
|
38
42
|
const rail_pr_decision_1 = require("./rail-pr-decision");
|
|
39
43
|
const active_pr_continuation_1 = require("./active-pr-continuation");
|
|
@@ -56,7 +60,14 @@ const agent_runtime_controls_router_1 = require("../../agent-runtime/runtime/age
|
|
|
56
60
|
const ticket_store_1 = require("../../specs/runtime/ticket-store");
|
|
57
61
|
const spec_addenda_1 = require("../../specs/runtime/spec-addenda");
|
|
58
62
|
const process_admission_1 = require("../../../process-admission");
|
|
59
|
-
const VALID_MODES = new Set(['implement', '
|
|
63
|
+
const VALID_MODES = new Set(['implement', 'freestyle', 'loop']);
|
|
64
|
+
/** Input aliases of the removed Batch mode. `implement` already runs every rail
|
|
65
|
+
* ticket in one aggregate run, so stored/agent/mobile `batch-implement` (or
|
|
66
|
+
* `batch`) requests are normalized to it at the HTTP boundary. */
|
|
67
|
+
const REMOVED_BATCH_MODES = new Set(['batch-implement', 'batch']);
|
|
68
|
+
function normalizeRailMode(mode) {
|
|
69
|
+
return typeof mode === 'string' && REMOVED_BATCH_MODES.has(mode) ? 'implement' : mode;
|
|
70
|
+
}
|
|
60
71
|
function prDeliveryContinuesTickets(delivery, ticketIds) {
|
|
61
72
|
if (delivery.decision !== 'pr_draft' && delivery.decision !== 'pr_ready')
|
|
62
73
|
return false;
|
|
@@ -136,6 +147,20 @@ function onReviewTicketIds(c) {
|
|
|
136
147
|
return new Set();
|
|
137
148
|
}
|
|
138
149
|
}
|
|
150
|
+
/** Map an engine-availability refusal to the launch's 409 body; rethrow others. */
|
|
151
|
+
async function engineSupportRejection(manager, graph, loopId) {
|
|
152
|
+
try {
|
|
153
|
+
await manager.assertEngineSupport?.(graph);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
157
|
+
const code = /^(legacy_engine_unavailable|engine_unsupported):/.exec(message)?.[1];
|
|
158
|
+
if (!code)
|
|
159
|
+
throw error;
|
|
160
|
+
return { error: code, loopId, detail: message.slice(code.length + 1).trim() };
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
139
164
|
function createRailsRouter() {
|
|
140
165
|
const router = (0, express_1.Router)({ mergeParams: true });
|
|
141
166
|
function ctx(req) {
|
|
@@ -318,7 +343,12 @@ function createRailsRouter() {
|
|
|
318
343
|
// per-rail profile. Preserve them (an explicit body value still wins).
|
|
319
344
|
const current = (0, rails_store_1.getRail)(c.db, railIndex);
|
|
320
345
|
const body = req.body ?? {};
|
|
321
|
-
const
|
|
346
|
+
const requestedMode = normalizeRailMode(body.mode);
|
|
347
|
+
if (requestedMode !== undefined && (typeof requestedMode !== 'string' || !VALID_MODES.has(requestedMode))) {
|
|
348
|
+
res.status(400).json({ error: 'mode must be "implement", "freestyle" or "loop"' });
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
const mode = typeof requestedMode === 'string' ? requestedMode : String(normalizeRailMode(current.mode));
|
|
322
352
|
const profileName = 'profileName' in body ? body.profileName : current.profileName;
|
|
323
353
|
// Preserve the rail's AI engine across ticket reassignment (undefined →
|
|
324
354
|
// setRailTickets re-reads the current value), so it isn't silently wiped.
|
|
@@ -478,7 +508,8 @@ function createRailsRouter() {
|
|
|
478
508
|
res.status(400).json({ error: 'invalid_runtime_provider_override' });
|
|
479
509
|
return;
|
|
480
510
|
}
|
|
481
|
-
|
|
511
|
+
// Non-string values fail the VALID_MODES check below.
|
|
512
|
+
let mode = normalizeRailMode(req.body?.mode ?? 'implement');
|
|
482
513
|
const { repositoryIds: rawRepositoryIds, baseDeliveryIds, profileName, aiEngine, model, loopId: rawLoopId, reasoning_effort, originConversationId, originSurface, targetPrNumber, revisionOfDeliveryId, revisionNote, baseBranch: rawBaseBranch, followUp: rawFollowUp } = req.body ?? {};
|
|
483
514
|
// PR review follow-up (pr-follow-up-fixes): a typed, bounded, FROZEN scope
|
|
484
515
|
// for "resolve these review comments". It rides the delivery row and every
|
|
@@ -566,7 +597,7 @@ function createRailsRouter() {
|
|
|
566
597
|
mode = fmode;
|
|
567
598
|
}
|
|
568
599
|
if (!VALID_MODES.has(mode)) {
|
|
569
|
-
res.status(400).json({ error: 'mode must be "implement", "
|
|
600
|
+
res.status(400).json({ error: 'mode must be "implement", "freestyle" or "loop"' });
|
|
570
601
|
return;
|
|
571
602
|
}
|
|
572
603
|
// A bare legacy mode (MCP tools, mobile, direct REST — no loopId) must run
|
|
@@ -795,11 +826,31 @@ function createRailsRouter() {
|
|
|
795
826
|
let loopGraph;
|
|
796
827
|
let loopName;
|
|
797
828
|
if ((0, loop_factory_1.isFactoryLoopId)(loopId)) {
|
|
798
|
-
|
|
829
|
+
let capabilities;
|
|
830
|
+
try {
|
|
831
|
+
capabilities = (await (0, agent_runtime_loader_1.loadCoreAgentRuntime)()).api?.capabilities;
|
|
832
|
+
}
|
|
833
|
+
catch { /* Existing Core remains supported through the legacy factory. */ }
|
|
834
|
+
// Editable built-ins: an edited row runs its Published graph (or the
|
|
835
|
+
// last Published snapshot while an edit is Draft); otherwise the
|
|
836
|
+
// current code default for this Core.
|
|
837
|
+
const f = (0, builtin_loops_1.resolveBuiltinLoop)(c.desktopDb, loopId, capabilities);
|
|
799
838
|
if (!f) {
|
|
800
839
|
res.status(404).json({ error: 'Factory loop not found' });
|
|
801
840
|
return;
|
|
802
841
|
}
|
|
842
|
+
if (f.source !== 'default') {
|
|
843
|
+
const validation = (0, loop_graph_1.validateLoopGraph)(f.graph);
|
|
844
|
+
if (!validation.valid) {
|
|
845
|
+
res.status(422).json({ error: 'Loop graph is invalid', errors: validation.errors });
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
const rejection = await engineSupportRejection(c.loopRunManager, f.graph, loopId);
|
|
849
|
+
if (rejection) {
|
|
850
|
+
res.status(409).json(rejection);
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
803
854
|
loopGraph = f.graph;
|
|
804
855
|
loopName = f.name;
|
|
805
856
|
}
|
|
@@ -826,6 +877,11 @@ function createRailsRouter() {
|
|
|
826
877
|
res.status(400).json({ error: 'This loop runs standalone — launch it from the Loops page, not a rail.' });
|
|
827
878
|
return;
|
|
828
879
|
}
|
|
880
|
+
const rejection = await engineSupportRejection(c.loopRunManager, loop.graph, loopId);
|
|
881
|
+
if (rejection) {
|
|
882
|
+
res.status(409).json(rejection);
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
829
885
|
loopGraph = loop.graph;
|
|
830
886
|
loopName = loop.name;
|
|
831
887
|
}
|
|
@@ -1311,11 +1367,10 @@ function createRailsRouter() {
|
|
|
1311
1367
|
res.status(202).json({ jobId, jobIds, railIndex, mode });
|
|
1312
1368
|
return;
|
|
1313
1369
|
}
|
|
1314
|
-
// Implement
|
|
1315
|
-
//
|
|
1370
|
+
// Implement creates a single job with all ticket IDs (the removed Batch
|
|
1371
|
+
// mode is normalized to implement above).
|
|
1316
1372
|
const issueArgs = rail.ticketIds.map((id) => `#${id}`).join(' ');
|
|
1317
|
-
const
|
|
1318
|
-
const command = `/specrails:${commandName} ${issueArgs} --yes`;
|
|
1373
|
+
const command = `/specrails:implement ${issueArgs} --yes`;
|
|
1319
1374
|
const job = c.queueManager.enqueue(command, 'normal', { profileName: resolvedProfile, provider: railProvider });
|
|
1320
1375
|
jobId = job.id;
|
|
1321
1376
|
c.railJobs.set(jobId, { railIndex, mode, ticketIds: [...rail.ticketIds] });
|
|
@@ -1470,7 +1525,8 @@ function createRailsRouter() {
|
|
|
1470
1525
|
const existing = (0, delivery_evidence_1.readSettleEvidence)(row.settle_evidence);
|
|
1471
1526
|
if (existing) {
|
|
1472
1527
|
const pipelineDir = path_1.default.join((0, workspace_resolution_1.resolveProjectExecution)({ slug: c.project.slug, path: c.project.path }).specrailsDir, 'pipeline');
|
|
1473
|
-
const
|
|
1528
|
+
const definitionStatuses = await (0, loop_definition_recovery_1.probeDefinitionRuns)({ db: c.db, cwd: c.project.path, env: process.env }, existing.units.filter(unit => !unit.runtime && unit.runId && (0, loop_runs_store_1.getLoopRun)(c.db, unit.runId)?.engine_version === 2).map(unit => unit.runId), true);
|
|
1529
|
+
const healed = (0, delivery_evidence_1.healRuntimeEvidence)(existing, pipelineDir, {}, definitionStatuses);
|
|
1474
1530
|
if (healed) {
|
|
1475
1531
|
(0, rail_pr_store_1.updatePrDeliverySettleEvidence)(c.db, row.id, healed);
|
|
1476
1532
|
row = { ...row, settle_evidence: JSON.stringify(healed) };
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.QueueManager = exports.FREESTYLE_COMMAND_RE = exports.InvalidJobDependencyError = exports.JobAlreadyTerminalError = exports.JobNotFoundError = exports.CodexNotFoundError = exports.ClaudeNotFoundError = exports.DEFAULT_ZOMBIE_TIMEOUT_MS = exports.distributeIntEvenly = exports.projectSupportsProfiles = exports.buildTelemetryEnv = void 0;
|
|
7
7
|
const budget_storage_1 = require("../adapters/budget-storage");
|
|
8
|
+
const legacy_launch_telemetry_1 = require("../../loops/runtime/legacy-launch-telemetry");
|
|
8
9
|
const __1 = require("..");
|
|
9
10
|
const usage_reader_1 = require("../adapters/usage-reader");
|
|
10
11
|
const __2 = require("..");
|
|
@@ -649,6 +650,11 @@ class QueueManager {
|
|
|
649
650
|
if (this._disposed)
|
|
650
651
|
throw new Error('Queue manager is shutting down');
|
|
651
652
|
}
|
|
653
|
+
_recordLegacySlashLaunch(job) {
|
|
654
|
+
if (this._db && this._projectId && (0, legacy_launch_telemetry_1.isLegacySlashCommand)(job.command)) {
|
|
655
|
+
(0, legacy_launch_telemetry_1.recordLegacyLaunch)(this._db, { kind: 'queue_manager_slash', projectId: this._projectId, runId: job.id });
|
|
656
|
+
}
|
|
657
|
+
}
|
|
652
658
|
enqueue(command, priorityOrOpts, opts, durableAdmission) {
|
|
653
659
|
this._assertMutable();
|
|
654
660
|
if (this._restoreBlocked) {
|
|
@@ -1692,6 +1698,7 @@ class QueueManager {
|
|
|
1692
1698
|
});
|
|
1693
1699
|
}
|
|
1694
1700
|
this._consumePendingSelections(jobId);
|
|
1701
|
+
this._recordLegacySlashLaunch(job);
|
|
1695
1702
|
const session = new interactive_job_session_1.InteractiveJobSession({
|
|
1696
1703
|
jobId,
|
|
1697
1704
|
projectId: this._projectId ?? '',
|
|
@@ -2053,8 +2060,9 @@ class QueueManager {
|
|
|
2053
2060
|
'- Skip any instructions that say "wait for user", "present for review", or "ask the user".\n' +
|
|
2054
2061
|
'- The pipeline must complete fully from start to finish in a single uninterrupted run.';
|
|
2055
2062
|
}
|
|
2056
|
-
// Local ticket store: implement
|
|
2063
|
+
// Local ticket store: implement jobs must read specs from
|
|
2057
2064
|
// .specrails/local-tickets.json — never from external trackers like Jira/Linear.
|
|
2065
|
+
// (`batch-implement` stays matched only for historical/replayed commands.)
|
|
2058
2066
|
if (/\/(specrails|sr):(implement|batch-implement)\b/.test(commandToRun)) {
|
|
2059
2067
|
systemAppend += '\n\nIMPORTANT: The ticket/spec data for this project is stored locally in .specrails/local-tickets.json. ' +
|
|
2060
2068
|
'You MUST read specs from this file. Do NOT attempt to fetch tickets from Jira, Linear, GitHub Issues, or any other external tracker. ' +
|
|
@@ -2081,7 +2089,7 @@ class QueueManager {
|
|
|
2081
2089
|
// `$skill_name` to invoke a skill from `.codex/skills/<name>/SKILL.md`.
|
|
2082
2090
|
// Translate `/specrails:<name>` → `$<name>` so codex picks up the
|
|
2083
2091
|
// matching skill natively (which our scaffold writes for every
|
|
2084
|
-
// claude slash command — propose-spec, implement,
|
|
2092
|
+
// claude slash command — propose-spec, implement,
|
|
2085
2093
|
// explore-spec, retry, …). This is the rail equivalent of the
|
|
2086
2094
|
// user typing `$implement #1 --yes` themselves in `codex`.
|
|
2087
2095
|
// Freestyle (capability-gated; currently Claude and Kimi): skip the slash
|
|
@@ -2460,6 +2468,7 @@ class QueueManager {
|
|
|
2460
2468
|
}
|
|
2461
2469
|
this._consumePendingSelections(jobId);
|
|
2462
2470
|
// spawnAiCli reroutes multi-line argv values through stdin on Windows.
|
|
2471
|
+
this._recordLegacySlashLaunch(job);
|
|
2463
2472
|
const child = (0, cli_prompt_1.spawnAiCli)(binary, args, {
|
|
2464
2473
|
env: (0, runtime_1.buildProviderEnv)(adapter, railSpawnOptions, spawnEnv),
|
|
2465
2474
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EDITABLE_BUILTIN_LOOP_IDS = void 0;
|
|
4
|
+
exports.probeCoreCapabilities = probeCoreCapabilities;
|
|
5
|
+
exports.builtinLoopDefaults = builtinLoopDefaults;
|
|
6
|
+
exports.ensureBuiltinLoops = ensureBuiltinLoops;
|
|
7
|
+
exports.resolveBuiltinLoop = resolveBuiltinLoop;
|
|
8
|
+
exports.restoreBuiltin = restoreBuiltin;
|
|
9
|
+
const registry_1 = require("../../../providers/registry");
|
|
10
|
+
const agent_runtime_loader_1 = require("../../agent-runtime/runtime/agent-runtime-loader");
|
|
11
|
+
const loop_factory_1 = require("./loop-factory");
|
|
12
|
+
const loops_store_1 = require("./loops-store");
|
|
13
|
+
/** Built-ins that exist as editable rows. Batch is an alias, never seeded. */
|
|
14
|
+
exports.EDITABLE_BUILTIN_LOOP_IDS = ['factory:implement', 'factory:freestyle', 'factory:sdd-quick-openspec'];
|
|
15
|
+
async function defaultCapabilities() {
|
|
16
|
+
return (await (0, agent_runtime_loader_1.loadCoreAgentRuntime)()).api?.capabilities;
|
|
17
|
+
}
|
|
18
|
+
function defaultFreestyleAvailable() {
|
|
19
|
+
return (0, registry_1.listAdapters)().some(adapter => adapter.capabilities.freestyle === true);
|
|
20
|
+
}
|
|
21
|
+
async function probeCoreCapabilities(env = {}) {
|
|
22
|
+
try {
|
|
23
|
+
return { capabilities: await (env.loadCapabilities ?? defaultCapabilities)(), known: true };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return { capabilities: undefined, known: false };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function toDefault(factory) {
|
|
30
|
+
return { id: factory.id, name: factory.name, description: factory.description, graph: factory.graph };
|
|
31
|
+
}
|
|
32
|
+
/** Current defaults of the seeded built-ins for these capabilities. */
|
|
33
|
+
function builtinLoopDefaults(capabilities, freestyleAvailable) {
|
|
34
|
+
return (0, loop_factory_1.factoryLoopsForCapabilities)(capabilities)
|
|
35
|
+
.filter(factory => exports.EDITABLE_BUILTIN_LOOP_IDS.includes(factory.id))
|
|
36
|
+
.filter(factory => factory.requiredCapability !== 'freestyle' || freestyleAvailable)
|
|
37
|
+
.map(toDefault);
|
|
38
|
+
}
|
|
39
|
+
/** Idempotent, concurrency-safe seeding/refresh. Returns the capability probe. */
|
|
40
|
+
async function ensureBuiltinLoops(db, env = {}) {
|
|
41
|
+
const probe = await probeCoreCapabilities(env);
|
|
42
|
+
const defaults = builtinLoopDefaults(probe.capabilities, (env.freestyleAvailable ?? defaultFreestyleAvailable)());
|
|
43
|
+
return { ...probe, ...(0, loops_store_1.seedBuiltinLoops)(db, defaults, { refresh: probe.known }) };
|
|
44
|
+
}
|
|
45
|
+
/** Resolve a `factory:*` id to the graph a launch must run. Read-only. */
|
|
46
|
+
function resolveBuiltinLoop(db, loopId, capabilities) {
|
|
47
|
+
const factory = (0, loop_factory_1.getFactoryLoop)(loopId, capabilities);
|
|
48
|
+
if (!factory)
|
|
49
|
+
return undefined;
|
|
50
|
+
const base = { id: factory.id, name: factory.name, description: factory.description, mode: factory.mode, graph: factory.graph, source: 'default' };
|
|
51
|
+
const row = db ? (0, loops_store_1.getBuiltinLoop)(db, factory.id) : undefined;
|
|
52
|
+
if (!row)
|
|
53
|
+
return base;
|
|
54
|
+
const named = { ...base, name: row.name, description: row.description ?? factory.description, row };
|
|
55
|
+
if (!row.builtinModified)
|
|
56
|
+
return named;
|
|
57
|
+
if (row.status === 'published')
|
|
58
|
+
return { ...named, graph: row.graph, source: 'edited' };
|
|
59
|
+
const snapshot = (0, loops_store_1.readPublishedLoopGraph)(db, row.id);
|
|
60
|
+
return snapshot ? { ...named, graph: snapshot, source: 'published-snapshot' } : named;
|
|
61
|
+
}
|
|
62
|
+
/** Reset a built-in row to its current default variant (Published). */
|
|
63
|
+
async function restoreBuiltin(db, id, env = {}) {
|
|
64
|
+
const row = (0, loops_store_1.getBuiltinLoop)(db, id);
|
|
65
|
+
if (!row)
|
|
66
|
+
return undefined;
|
|
67
|
+
const probe = await probeCoreCapabilities(env);
|
|
68
|
+
const factory = (0, loop_factory_1.getFactoryLoop)(id, probe.capabilities);
|
|
69
|
+
return factory ? (0, loops_store_1.restoreBuiltinLoop)(db, toDefault(factory)) : undefined;
|
|
70
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.finishDefinitionCancellation = finishDefinitionCancellation;
|
|
4
|
+
/** Acknowledgement is not settlement. Wait for Core to release its writer lease
|
|
5
|
+
* before Desktop replays terminal events and closes the original delivery. */
|
|
6
|
+
async function finishDefinitionCancellation(ports, timeoutMs = 90_000) {
|
|
7
|
+
const deadline = ports.now() + timeoutMs;
|
|
8
|
+
for (;;) {
|
|
9
|
+
if (ports.stopped())
|
|
10
|
+
return; // Startup recovery retains the durable Core intent.
|
|
11
|
+
const state = await ports.inspect();
|
|
12
|
+
if (ports.stopped())
|
|
13
|
+
return;
|
|
14
|
+
if (state.status === 'unavailable')
|
|
15
|
+
throw new Error('Cancellation was accepted, but retained Core status is unavailable');
|
|
16
|
+
if (!state.lease?.active) {
|
|
17
|
+
if (!['cancelled', 'succeeded'].includes(state.status) && !state.completion) {
|
|
18
|
+
// A writer can disappear after inbox admission. Core owns converting
|
|
19
|
+
// its expired lease and durable cancel request into terminal truth.
|
|
20
|
+
await ports.cancel();
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
await ports.settle();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (ports.now() >= deadline)
|
|
28
|
+
throw new Error('Cancellation is durable; Core has not released its execution lease yet');
|
|
29
|
+
await ports.wait(Math.min(1000, Math.max(1, deadline - ports.now())));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LEGACY_LAUNCH_KINDS = void 0;
|
|
4
|
+
exports.isLegacySlashCommand = isLegacySlashCommand;
|
|
5
|
+
exports.recordLegacyLaunch = recordLegacyLaunch;
|
|
6
|
+
exports.readLegacyLaunchSummary = readLegacyLaunchSummary;
|
|
7
|
+
/**
|
|
8
|
+
* Legacy-launch telemetry — the D8 retirement counter.
|
|
9
|
+
*
|
|
10
|
+
* Every launch that still runs through a pre-Core path appends one row to the
|
|
11
|
+
* per-project `legacy_launch_events` table (migration 66): the node-by-node
|
|
12
|
+
* loop traversal in LoopRunManager, the QueueManager slash command a bare rail
|
|
13
|
+
* mode enqueues, and the isolated-rail merge-back. The analytics page reads the
|
|
14
|
+
* summary so two releases can prove the counter stays at zero before D8.3–D8.5
|
|
15
|
+
* remove those paths. Nothing here changes how a launch runs.
|
|
16
|
+
*
|
|
17
|
+
* Append-only. A run-scoped event is idempotent per (kind, runId) so restart
|
|
18
|
+
* replay and retries never inflate the count; events without a run id count
|
|
19
|
+
* every call. Pure SQLite helpers; no Express, no process access.
|
|
20
|
+
*/
|
|
21
|
+
const node_crypto_1 = require("node:crypto");
|
|
22
|
+
exports.LEGACY_LAUNCH_KINDS = ['legacy_loop_traversal', 'queue_manager_slash', 'merge_back'];
|
|
23
|
+
/** Raw queue prompts support slash commands and Codex's $skill spelling. */
|
|
24
|
+
function isLegacySlashCommand(command) {
|
|
25
|
+
return /^\s*\/(?:[a-z0-9-]+:)?[a-z][a-z0-9-]*(?=\s|$)/i.test(command) ||
|
|
26
|
+
/^\s*\$[a-z][a-z0-9-]*(?=\s|$)/.test(command);
|
|
27
|
+
}
|
|
28
|
+
function assertIso(value, field) {
|
|
29
|
+
if (typeof value !== 'string' || !value.trim() || Number.isNaN(Date.parse(value))) {
|
|
30
|
+
throw new RangeError(`legacy launch telemetry: ${field} must be an ISO-8601 timestamp`);
|
|
31
|
+
}
|
|
32
|
+
return new Date(value).toISOString();
|
|
33
|
+
}
|
|
34
|
+
/** Record one legacy launch. Throws only on malformed input; callers that must
|
|
35
|
+
* never block a launch wrap the call. */
|
|
36
|
+
function recordLegacyLaunch(db, event) {
|
|
37
|
+
if (!exports.LEGACY_LAUNCH_KINDS.includes(event?.kind)) {
|
|
38
|
+
throw new TypeError(`legacy launch telemetry: unknown kind ${JSON.stringify(event?.kind)}`);
|
|
39
|
+
}
|
|
40
|
+
if (typeof event.projectId !== 'string' || !event.projectId.trim()) {
|
|
41
|
+
throw new TypeError('legacy launch telemetry: projectId is required');
|
|
42
|
+
}
|
|
43
|
+
if (event.runId !== undefined && (typeof event.runId !== 'string' || !event.runId.trim())) {
|
|
44
|
+
throw new TypeError('legacy launch telemetry: runId must be a non-empty string when present');
|
|
45
|
+
}
|
|
46
|
+
const at = event.at === undefined ? new Date().toISOString() : assertIso(event.at, 'at');
|
|
47
|
+
// The partial unique index on (kind, run_id) makes the run-scoped insert a
|
|
48
|
+
// no-op on replay; rows without a run id never collide.
|
|
49
|
+
db.prepare(`
|
|
50
|
+
INSERT OR IGNORE INTO legacy_launch_events (id, kind, project_id, run_id, at)
|
|
51
|
+
VALUES (?, ?, ?, ?, ?)
|
|
52
|
+
`).run((0, node_crypto_1.randomUUID)(), event.kind, event.projectId, event.runId ?? null, at);
|
|
53
|
+
}
|
|
54
|
+
/** Aggregate the counter, optionally from an ISO lower bound (inclusive). The
|
|
55
|
+
* bound is compared lexicographically, so a date-only `YYYY-MM-DD` works. */
|
|
56
|
+
function readLegacyLaunchSummary(db, since) {
|
|
57
|
+
const params = [];
|
|
58
|
+
let where = '';
|
|
59
|
+
if (since !== undefined) {
|
|
60
|
+
where = 'WHERE at >= ?';
|
|
61
|
+
params.push(assertIso(since, 'since'));
|
|
62
|
+
}
|
|
63
|
+
const rows = db.prepare(`
|
|
64
|
+
SELECT kind, COUNT(*) AS count, MAX(at) AS last_at
|
|
65
|
+
FROM legacy_launch_events ${where}
|
|
66
|
+
GROUP BY kind
|
|
67
|
+
`).all(...params);
|
|
68
|
+
const byKind = Object.fromEntries(exports.LEGACY_LAUNCH_KINDS.map((kind) => [kind, 0]));
|
|
69
|
+
let total = 0;
|
|
70
|
+
let lastAt = null;
|
|
71
|
+
for (const row of rows) {
|
|
72
|
+
byKind[row.kind] = (byKind[row.kind] ?? 0) + row.count;
|
|
73
|
+
total += row.count;
|
|
74
|
+
if (row.last_at && (lastAt === null || row.last_at > lastAt))
|
|
75
|
+
lastAt = row.last_at;
|
|
76
|
+
}
|
|
77
|
+
return { total, byKind, lastAt };
|
|
78
|
+
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* autonomous prompt.
|
|
14
14
|
*
|
|
15
15
|
* Each command declares its TICKET SCOPE:
|
|
16
|
-
* - `all` → one run over ALL the rail's tickets (`#1 #2 #3`). implement
|
|
16
|
+
* - `all` → one run over ALL the rail's tickets (`#1 #2 #3`). implement.
|
|
17
17
|
* - `per-ticket` → one run per ticket. Freestyle (and the default).
|
|
18
18
|
*
|
|
19
19
|
* Expansion order in the engine: `expandCommands()` FIRST (injects the ticket ids),
|
|
@@ -72,13 +72,6 @@ exports.LOOP_COMMANDS = [
|
|
|
72
72
|
coreCommand: 'implement',
|
|
73
73
|
ticketScope: 'all',
|
|
74
74
|
},
|
|
75
|
-
{
|
|
76
|
-
name: 'batch',
|
|
77
|
-
label: 'batch',
|
|
78
|
-
description: "Run all selected tickets as one frozen candidate through Core’s programmatic agent workflow.",
|
|
79
|
-
coreCommand: 'batch-implement',
|
|
80
|
-
ticketScope: 'all',
|
|
81
|
-
},
|
|
82
75
|
{
|
|
83
76
|
name: 'freestyle',
|
|
84
77
|
label: 'Freestyle',
|
|
@@ -226,7 +219,7 @@ exports.LOOP_COMMANDS = [
|
|
|
226
219
|
// native opsx command fall back to the `template` prompt. Archive is invoked via
|
|
227
220
|
// the `openspec` CLI in a shell node (provider-independent) and has no command.
|
|
228
221
|
// NOTE: opsx commands are confirmed on claude today; codex/gemini lean on the
|
|
229
|
-
// fallback until OpenSpec ships their native commands (see
|
|
222
|
+
// fallback until OpenSpec ships their native commands (see the legacy Quick SDD graph).
|
|
230
223
|
{
|
|
231
224
|
name: 'opsx:ff', label: 'opsx:ff', ticketScope: 'per-ticket',
|
|
232
225
|
description: 'OpenSpec fast-forward: create (or continue) a change and generate all its artifacts (proposal, specs, design, tasks). Native /opsx:ff (claude/gemini) or $opsx:ff (codex).',
|
|
@@ -310,7 +303,17 @@ exports.LOOP_COMMANDS = [
|
|
|
310
303
|
].join('\n'),
|
|
311
304
|
},
|
|
312
305
|
];
|
|
313
|
-
|
|
306
|
+
/** Hidden, unlisted aliases kept so saved loops keep working. `{{cmd:batch}}`
|
|
307
|
+
* belonged to the removed Batch mode; it now expands exactly like
|
|
308
|
+
* `{{cmd:implement}}` (one aggregate run over all the rail's tickets). */
|
|
309
|
+
const LOOP_COMMAND_ALIASES = { batch: 'implement' };
|
|
310
|
+
const COMMANDS_BY_NAME = new Map([
|
|
311
|
+
...exports.LOOP_COMMANDS.map((c) => [c.name, c]),
|
|
312
|
+
...Object.entries(LOOP_COMMAND_ALIASES).flatMap(([alias, target]) => {
|
|
313
|
+
const cmd = exports.LOOP_COMMANDS.find((c) => c.name === target);
|
|
314
|
+
return cmd ? [[alias, cmd]] : [];
|
|
315
|
+
}),
|
|
316
|
+
]);
|
|
314
317
|
function getLoopCommand(name) {
|
|
315
318
|
return COMMANDS_BY_NAME.get(name);
|
|
316
319
|
}
|
|
@@ -321,8 +324,6 @@ const CMD_TOKEN_RE = /\{\{\s*cmd:([\w:-]+)\s*\}\}/g;
|
|
|
321
324
|
* identical in shape to the rail's `/specrails:implement #1 #2 --yes`. Codex has
|
|
322
325
|
* no `/namespace:cmd` parser, so it invokes the equivalent `$<name>` skill. */
|
|
323
326
|
function nativeInvocation(coreCommand, provider, ids) {
|
|
324
|
-
if (provider === 'codex' && coreCommand === 'implement' && ids.length > 1)
|
|
325
|
-
coreCommand = 'batch-implement';
|
|
326
327
|
const head = provider === 'codex'
|
|
327
328
|
? `$${coreCommand}`
|
|
328
329
|
: provider === 'kimi'
|