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
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assessLoopMigration = assessLoopMigration;
|
|
4
|
+
const loop_compat_1 = require("./loop-compat");
|
|
5
|
+
const loop_graph_1 = require("./loop-graph");
|
|
6
|
+
function assessLoopMigration(loops, ports) {
|
|
7
|
+
const entries = loops.map((loop) => {
|
|
8
|
+
const engine = (0, loop_graph_1.isDefinitionGraph)(loop.graph) ? 'core' : 'legacy';
|
|
9
|
+
const base = { id: loop.id, name: loop.name, status: loop.status, engine, hasLegacyGraph: loop.hasLegacyGraph === true };
|
|
10
|
+
if (ports.isRunning(loop.id))
|
|
11
|
+
return { ...base, state: 'running', issues: [] };
|
|
12
|
+
let graph = loop.graph;
|
|
13
|
+
if (engine === 'legacy') {
|
|
14
|
+
// No repository binding is guessed: a multi-repository shell without an
|
|
15
|
+
// explicit scope stays an actionable issue, exactly as in conversion.
|
|
16
|
+
const converted = (0, loop_compat_1.convertLegacyLoop)(loop.graph);
|
|
17
|
+
if (!converted.ok)
|
|
18
|
+
return { ...base, state: 'needs_attention', issues: converted.issues };
|
|
19
|
+
graph = converted.graph;
|
|
20
|
+
}
|
|
21
|
+
let result;
|
|
22
|
+
try {
|
|
23
|
+
result = ports.validate(loop, graph);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
result = { ok: false, errors: [{ code: 'definition_invalid', message: error instanceof Error ? error.message : 'Invalid workflow' }] };
|
|
27
|
+
}
|
|
28
|
+
if (result.ok)
|
|
29
|
+
return { ...base, state: engine === 'core' ? 'current' : 'convertible', issues: [] };
|
|
30
|
+
return { ...base, state: engine === 'core' ? 'invalid' : 'needs_attention', issues: result.errors };
|
|
31
|
+
});
|
|
32
|
+
const summary = { current: 0, invalid: 0, convertible: 0, needs_attention: 0, running: 0 };
|
|
33
|
+
for (const entry of entries)
|
|
34
|
+
summary[entry.state] += 1;
|
|
35
|
+
return { loops: entries, summary };
|
|
36
|
+
}
|
|
@@ -13,6 +13,8 @@ exports.previewLoop = previewLoop;
|
|
|
13
13
|
*/
|
|
14
14
|
const loop_command_catalog_1 = require("./loop-command-catalog");
|
|
15
15
|
const loop_graph_1 = require("./loop-graph");
|
|
16
|
+
const loop_definition_1 = require("./loop-definition");
|
|
17
|
+
const loop_graph_2 = require("./loop-graph");
|
|
16
18
|
const loop_constants_1 = require("./loop-constants");
|
|
17
19
|
/** Stand-in ticket so `{{spec.*}}` resolves to something readable in the preview. */
|
|
18
20
|
exports.SAMPLE_SPEC = {
|
|
@@ -50,6 +52,14 @@ function visitOrder(graph) {
|
|
|
50
52
|
function previewLoop(graph, opts) {
|
|
51
53
|
const spec = opts.spec ?? exports.SAMPLE_SPEC;
|
|
52
54
|
const steps = [];
|
|
55
|
+
if ((0, loop_graph_2.isDefinitionGraph)(graph)) {
|
|
56
|
+
const definition = (0, loop_definition_1.compileLoopToDefinition)(graph, { ...opts, spec });
|
|
57
|
+
for (const [prefix, body] of [['', definition], ...Object.entries(definition.components ?? {})])
|
|
58
|
+
for (const [id, node] of Object.entries(body.nodes)) {
|
|
59
|
+
steps.push({ nodeId: prefix ? `${prefix}/${id}` : id, kind: node.kind, label: node.label, text: JSON.stringify(node.params, null, 2) });
|
|
60
|
+
}
|
|
61
|
+
return { steps };
|
|
62
|
+
}
|
|
53
63
|
for (const node of visitOrder(graph)) {
|
|
54
64
|
const label = typeof node.data?.label === 'string' && node.data.label.trim() ? node.data.label.trim() : undefined;
|
|
55
65
|
let text = null;
|
|
@@ -11,6 +11,9 @@ exports.openspecChangeState = openspecChangeState;
|
|
|
11
11
|
exports.extractChangeId = extractChangeId;
|
|
12
12
|
exports.recoverOrphanLoopStepAccounting = recoverOrphanLoopStepAccounting;
|
|
13
13
|
const crypto_1 = require("crypto");
|
|
14
|
+
const loop_definition_events_1 = require("./loop-definition-events");
|
|
15
|
+
const legacy_launch_telemetry_1 = require("./legacy-launch-telemetry");
|
|
16
|
+
const loop_definition_run_1 = require("./loop-definition-run");
|
|
14
17
|
const spec_addenda_core_1 = require("../../specs/runtime/spec-addenda-core");
|
|
15
18
|
const path_1 = __importDefault(require("path"));
|
|
16
19
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -441,6 +444,7 @@ class LoopRunManager {
|
|
|
441
444
|
now;
|
|
442
445
|
options;
|
|
443
446
|
_disposed = false;
|
|
447
|
+
_definitionTasks = new Map();
|
|
444
448
|
_cancelled = new Set();
|
|
445
449
|
/** The currently-spawned child per run, so cancel/stop can actually KILL a
|
|
446
450
|
* blocked spawn (the cooperative `_cancelled` flag can't interrupt an await). */
|
|
@@ -478,6 +482,49 @@ class LoopRunManager {
|
|
|
478
482
|
* awaited step resolves) — NOT dispose(), which never settles and would
|
|
479
483
|
* leave the engine's `await` hanging forever. */
|
|
480
484
|
cancel(runId) {
|
|
485
|
+
const frozen = (0, loop_runs_store_1.readDefinitionRun)(this.db, runId);
|
|
486
|
+
if (this.executors.cancelDefinition && frozen?.metadata.contextPath) {
|
|
487
|
+
void this.cancelDefinition(runId).catch(error => {
|
|
488
|
+
console.error(`[loop-run] durable cancellation failed for ${runId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
489
|
+
});
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
this.cancelResident(runId, false);
|
|
493
|
+
}
|
|
494
|
+
_definitionCancellations = new Map();
|
|
495
|
+
isDefinitionCancellationPending(runId) { return this._definitionCancellations.has(runId); }
|
|
496
|
+
/** Launch-time engine check, callable before a caller allocates worktrees. */
|
|
497
|
+
async assertEngineSupport(graph) {
|
|
498
|
+
if ((0, loop_graph_1.isDefinitionGraph)(graph)) {
|
|
499
|
+
if (!this.executors.runDefinition)
|
|
500
|
+
throw new Error('engine_unsupported: Core workflow execution is unavailable');
|
|
501
|
+
await this.executors.assertDefinitionSupport?.();
|
|
502
|
+
}
|
|
503
|
+
else
|
|
504
|
+
await this.executors.assertLegacyEngineSupport?.();
|
|
505
|
+
}
|
|
506
|
+
definitionForkOwnsRun(runId) {
|
|
507
|
+
return !!(0, loop_runs_store_1.readDefinitionForkTarget)(this.db, runId) || (0, loop_runs_store_1.readDefinitionExecutionClaim)(this.db, runId)?.owner.startsWith('fork:') === true;
|
|
508
|
+
}
|
|
509
|
+
/** Persist intent in the retained Core inbox before settling a resident pause.
|
|
510
|
+
* A rejected control leaves the execution available for an explicit retry. */
|
|
511
|
+
cancelDefinition(runId, requestId = `desktop-cancel:${runId}`) {
|
|
512
|
+
if (this.definitionForkOwnsRun(runId))
|
|
513
|
+
return Promise.reject(new Error('runtime_fork_owns_worktree: Continue the forked run'));
|
|
514
|
+
const pending = this._definitionCancellations.get(runId);
|
|
515
|
+
if (pending)
|
|
516
|
+
return pending;
|
|
517
|
+
const frozen = (0, loop_runs_store_1.readDefinitionRun)(this.db, runId);
|
|
518
|
+
const contextPath = frozen?.metadata.contextPath;
|
|
519
|
+
if (!contextPath || !this.executors.cancelDefinition)
|
|
520
|
+
return Promise.reject(new Error('runtime_control_unavailable: Frozen workflow cancellation is unavailable'));
|
|
521
|
+
const task = this.executors.cancelDefinition({ runId, contextPath, requestId }).then(() => {
|
|
522
|
+
this.cancelResident(runId, true);
|
|
523
|
+
}).finally(() => { this._definitionCancellations.delete(runId); });
|
|
524
|
+
this._definitionCancellations.set(runId, task);
|
|
525
|
+
return task;
|
|
526
|
+
}
|
|
527
|
+
cancelResident(runId, graceful) {
|
|
481
528
|
this._cancelled.add(runId);
|
|
482
529
|
const paused = this._pausedHumanDecisions.get(runId);
|
|
483
530
|
if (paused) {
|
|
@@ -491,9 +538,21 @@ class LoopRunManager {
|
|
|
491
538
|
const child = this._activeChild.get(runId);
|
|
492
539
|
if (child?.pid) {
|
|
493
540
|
try {
|
|
494
|
-
(0, win_spawn_1.treeKillSafe)(child.pid, 'SIGKILL', () => { });
|
|
541
|
+
(0, win_spawn_1.treeKillSafe)(child.pid, graceful ? 'SIGTERM' : 'SIGKILL', () => { });
|
|
495
542
|
}
|
|
496
543
|
catch { /* already gone */ }
|
|
544
|
+
if (graceful) {
|
|
545
|
+
const timer = setTimeout(() => {
|
|
546
|
+
if (this._activeChild.get(runId) === child && child.pid) {
|
|
547
|
+
try {
|
|
548
|
+
(0, win_spawn_1.treeKillSafe)(child.pid, 'SIGKILL', () => { });
|
|
549
|
+
}
|
|
550
|
+
catch { /* already gone */ }
|
|
551
|
+
}
|
|
552
|
+
}, 1500);
|
|
553
|
+
timer.unref?.();
|
|
554
|
+
child.once('close', () => clearTimeout(timer));
|
|
555
|
+
}
|
|
497
556
|
}
|
|
498
557
|
}
|
|
499
558
|
// ─── Interactive step routing (manager-agnostic /jobs/:id/messages) ─────────
|
|
@@ -511,11 +570,21 @@ class LoopRunManager {
|
|
|
511
570
|
/** Feed one more user prompt to the ACTIVE step session owning this job row
|
|
512
571
|
* (queued behind the active turn — steering; the loop tends to continue its
|
|
513
572
|
* plan). Returns false when no interactive step is live for the id. */
|
|
514
|
-
|
|
573
|
+
pendingInterrupts(jobId) {
|
|
574
|
+
return structuredClone(this._pausedHumanDecisions.get(jobId)?.pending ?? []);
|
|
575
|
+
}
|
|
576
|
+
sendInteractiveTurn(jobId, text, control) {
|
|
577
|
+
if (this.definitionForkOwnsRun(jobId))
|
|
578
|
+
return false;
|
|
515
579
|
const paused = this._pausedHumanDecisions.get(jobId);
|
|
516
580
|
if (paused) {
|
|
581
|
+
if (paused.pending?.length) {
|
|
582
|
+
const selected = control?.interruptId ? paused.pending.find(item => item.id === control.interruptId) : paused.pending.length === 1 ? paused.pending[0] : undefined;
|
|
583
|
+
if (!selected || (selected.kind !== 'question' && control?.approve !== true))
|
|
584
|
+
return false;
|
|
585
|
+
}
|
|
517
586
|
this._pausedHumanDecisions.delete(jobId);
|
|
518
|
-
paused.resolve({ action: 'resume', text });
|
|
587
|
+
paused.resolve({ action: 'resume', text, ...control });
|
|
519
588
|
return true;
|
|
520
589
|
}
|
|
521
590
|
const session = this._interactiveSteps.get(jobId);
|
|
@@ -614,7 +683,76 @@ class LoopRunManager {
|
|
|
614
683
|
}
|
|
615
684
|
this._pausedHumanDecisions.clear();
|
|
616
685
|
}
|
|
617
|
-
|
|
686
|
+
isDisposed() { return this._disposed; }
|
|
687
|
+
isDefinitionRunActive(runId) { return this._definitionTasks.has(runId); }
|
|
688
|
+
_definitionClaims = new Map();
|
|
689
|
+
claimDefinition(req) {
|
|
690
|
+
if (this._definitionClaims.has(req.runId))
|
|
691
|
+
return;
|
|
692
|
+
const claim = (0, loop_runs_store_1.claimDefinitionExecution)(this.db, req.runId, { owner: (0, ids_1.newId)(), repositoryMounts: (0, loop_runs_store_1.definitionRepositoryMounts)(req) });
|
|
693
|
+
if (!claim.ok)
|
|
694
|
+
throw new Error(`runtime_run_active: ${claim.reason} (${claim.conflictingRunId})`);
|
|
695
|
+
this._definitionClaims.set(req.runId, claim.release);
|
|
696
|
+
}
|
|
697
|
+
releaseDefinition(runId) {
|
|
698
|
+
this._definitionClaims.get(runId)?.();
|
|
699
|
+
this._definitionClaims.delete(runId);
|
|
700
|
+
}
|
|
701
|
+
run(req) {
|
|
702
|
+
if (!(0, loop_graph_1.isDefinitionGraph)(req.graph))
|
|
703
|
+
return this._run(req);
|
|
704
|
+
const runId = req.runId ?? (0, ids_1.newId)();
|
|
705
|
+
if (this._definitionTasks.has(runId))
|
|
706
|
+
return Promise.reject(new Error('runtime_run_active: Workflow is already running'));
|
|
707
|
+
try {
|
|
708
|
+
this.claimDefinition({ ...req, runId });
|
|
709
|
+
}
|
|
710
|
+
catch (error) {
|
|
711
|
+
return Promise.reject(error);
|
|
712
|
+
}
|
|
713
|
+
const task = this._run({ ...req, runId }).finally(() => { this.releaseDefinition(runId); this._definitionTasks.delete(runId); });
|
|
714
|
+
this._definitionTasks.set(runId, task);
|
|
715
|
+
return task;
|
|
716
|
+
}
|
|
717
|
+
resumeDefinition(runId, input = {}) {
|
|
718
|
+
try {
|
|
719
|
+
return this.beginDefinitionResume(runId, input);
|
|
720
|
+
}
|
|
721
|
+
catch (error) {
|
|
722
|
+
return Promise.reject(error);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
/** Synchronous admission lets HTTP reject competing writers before acknowledging a resume. */
|
|
726
|
+
beginDefinitionResume(runId, input = {}) {
|
|
727
|
+
if (this._disposed)
|
|
728
|
+
throw new Error('runtime_shutting_down: LoopRunManager is shut down');
|
|
729
|
+
const active = this._definitionTasks.get(runId);
|
|
730
|
+
if (active) {
|
|
731
|
+
const interruptId = input.interruptId ?? input.approve?.[0];
|
|
732
|
+
if (!this.isPaused(runId))
|
|
733
|
+
throw new Error('runtime_run_active: Select a pending question or approval');
|
|
734
|
+
const request = (0, loop_runs_store_1.readDefinitionRun)(this.db, runId)?.request;
|
|
735
|
+
if (!request)
|
|
736
|
+
throw new Error('runtime_run_not_found: Frozen workflow is unavailable');
|
|
737
|
+
this.claimDefinition({ ...request, runId });
|
|
738
|
+
if (!this.sendInteractiveTurn(runId, input.answer ?? '', { interruptId, approve: Boolean(input.approve?.length) })) {
|
|
739
|
+
this.releaseDefinition(runId);
|
|
740
|
+
throw new Error('runtime_run_active: Select a pending question or approval');
|
|
741
|
+
}
|
|
742
|
+
return active;
|
|
743
|
+
}
|
|
744
|
+
const frozen = (0, loop_runs_store_1.readDefinitionRun)(this.db, runId);
|
|
745
|
+
if (!frozen)
|
|
746
|
+
throw new Error('runtime_run_not_found: Frozen workflow is unavailable');
|
|
747
|
+
if (frozen.row.status === 'completed')
|
|
748
|
+
throw new Error('runtime_run_completed: Fork a completed workflow to continue');
|
|
749
|
+
this._cancelled.delete(runId);
|
|
750
|
+
this.claimDefinition({ ...frozen.request, runId });
|
|
751
|
+
const task = this._run(frozen.request, { resume: true, ...input }).finally(() => { this.releaseDefinition(runId); this._definitionTasks.delete(runId); });
|
|
752
|
+
this._definitionTasks.set(runId, task);
|
|
753
|
+
return task;
|
|
754
|
+
}
|
|
755
|
+
async _run(req, continuation) {
|
|
618
756
|
// Later fresh steps must verify the admitted spec, even if its caller or
|
|
619
757
|
// backlog changes while the implementation is running.
|
|
620
758
|
req = { ...req, runtimeProviderOverride: (0, agent_runtime_settings_1.validateRuntimeProviderOverride)(req.runtimeProviderOverride), graph: structuredClone(req.graph) };
|
|
@@ -640,6 +778,12 @@ class LoopRunManager {
|
|
|
640
778
|
}
|
|
641
779
|
}
|
|
642
780
|
}
|
|
781
|
+
const definitionEngine = (0, loop_graph_1.isDefinitionGraph)(req.graph);
|
|
782
|
+
if (definitionEngine && !this.executors.runDefinition)
|
|
783
|
+
throw new Error('engine_unsupported: Core workflow execution is unavailable');
|
|
784
|
+
// Saved runs resume with their retained package whatever the active Core lists.
|
|
785
|
+
if (!continuation)
|
|
786
|
+
await this.assertEngineSupport(req.graph);
|
|
643
787
|
if (this._disposed)
|
|
644
788
|
throw new Error('LoopRunManager is shut down');
|
|
645
789
|
const adapter = (0, providers_1.getAdapter)(req.provider);
|
|
@@ -708,6 +852,8 @@ class LoopRunManager {
|
|
|
708
852
|
iterationLimit: maxIterations,
|
|
709
853
|
startedAt: launchStartedAt,
|
|
710
854
|
});
|
|
855
|
+
if (definitionEngine)
|
|
856
|
+
(0, loop_runs_store_1.saveDefinitionRun)(this.db, runId, { request: req, source: 'definition' });
|
|
711
857
|
if (req.executionManifest)
|
|
712
858
|
this.db.prepare('UPDATE loop_runs SET execution_manifest = ? WHERE id = ?').run(JSON.stringify(req.executionManifest), runId);
|
|
713
859
|
(0, db_1.createJob)(this.db, {
|
|
@@ -718,8 +864,15 @@ class LoopRunManager {
|
|
|
718
864
|
owner: 'loop',
|
|
719
865
|
causal_ownership: true,
|
|
720
866
|
});
|
|
867
|
+
if (!definitionEngine)
|
|
868
|
+
(0, legacy_launch_telemetry_1.recordLegacyLaunch)(this.db, { kind: 'legacy_loop_traversal', projectId: req.projectId, runId, at: launchStartedAt });
|
|
721
869
|
});
|
|
722
|
-
|
|
870
|
+
if (continuation) {
|
|
871
|
+
(0, loop_runs_store_1.resumeLoopRun)(this.db, runId);
|
|
872
|
+
this.db.prepare("UPDATE jobs SET status='running',finished_at=NULL,exit_code=NULL WHERE id=? AND owner='loop'").run(runId);
|
|
873
|
+
}
|
|
874
|
+
else
|
|
875
|
+
persistLaunch();
|
|
723
876
|
this._emit({
|
|
724
877
|
type: 'loop.run_started',
|
|
725
878
|
projectId: req.projectId,
|
|
@@ -729,7 +882,7 @@ class LoopRunManager {
|
|
|
729
882
|
});
|
|
730
883
|
// Surface the run as a JOB so the full session streams live in the Jobs list
|
|
731
884
|
// + JobDetail. Both identities committed together above, before any spawn.
|
|
732
|
-
let seq = 0;
|
|
885
|
+
let seq = continuation ? Number(this.db.prepare('SELECT COALESCE(MAX(seq),-1)+1 AS next FROM events WHERE job_id=?').get(runId).next) : 0;
|
|
733
886
|
// Monotonic event-seq allocator for THIS run's job row. Shared with an
|
|
734
887
|
// interactive step session (which persists its own provider events/logs on
|
|
735
888
|
// the same job id) so replay ordering (getJobEvents ORDER BY seq) stays
|
|
@@ -840,7 +993,7 @@ class LoopRunManager {
|
|
|
840
993
|
logLine(`▶ Loop "${req.loopName ?? req.loopId}" started${req.spec?.title ? ` — spec: ${req.spec.title}` : ''}`);
|
|
841
994
|
if (req.isolation)
|
|
842
995
|
logLine(`⎇ Isolated worktree: ${req.isolation.worktreePath} (branch ${req.isolation.branch})`);
|
|
843
|
-
if (!usageTelemetryAvailable) {
|
|
996
|
+
if (!definitionEngine && !usageTelemetryAvailable) {
|
|
844
997
|
logLine(`⚠️ ${adapter.displayName} does not report token/cost usage in headless mode; usage totals will remain unavailable.` +
|
|
845
998
|
(configuredMaxCostUsd !== undefined
|
|
846
999
|
? ' The configured maxCostUsd guard is disabled because it cannot be verified.'
|
|
@@ -856,7 +1009,8 @@ class LoopRunManager {
|
|
|
856
1009
|
model: req.model,
|
|
857
1010
|
iterationLimit: maxIterations,
|
|
858
1011
|
};
|
|
859
|
-
|
|
1012
|
+
if (!continuation)
|
|
1013
|
+
emitRunEvent('loop_graph', graphPayload);
|
|
860
1014
|
console.log(`[loop] start run=${runId} loop=${req.loopId} provider=${req.provider} model=${req.model} nodes=${req.graph.nodes.length} cwd=${req.cwd}`);
|
|
861
1015
|
const byId = (0, loop_graph_1.nodesById)(req.graph);
|
|
862
1016
|
const start = (0, loop_graph_1.findStartNode)(req.graph);
|
|
@@ -1046,9 +1200,9 @@ class LoopRunManager {
|
|
|
1046
1200
|
// that loop-back so each iteration starts FRESH (re-reading the current code),
|
|
1047
1201
|
// keeping context bounded regardless of pass count. Within an iteration the
|
|
1048
1202
|
// steps still resume, so RED→GREEN→REFACTOR share context.
|
|
1049
|
-
const awaitHumanDecision = async (reason) => {
|
|
1203
|
+
const awaitHumanDecision = async (reason, pending) => {
|
|
1050
1204
|
const decisionPromise = new Promise((resolve) => {
|
|
1051
|
-
this._pausedHumanDecisions.set(runId, { reason, resolve });
|
|
1205
|
+
this._pausedHumanDecisions.set(runId, { reason, pending, resolve });
|
|
1052
1206
|
});
|
|
1053
1207
|
logLine(`\n■ Loop paused — needs a human decision: ${reason}`, 'stderr');
|
|
1054
1208
|
try {
|
|
@@ -1075,6 +1229,7 @@ class LoopRunManager {
|
|
|
1075
1229
|
projectId: req.projectId,
|
|
1076
1230
|
jobId: runId,
|
|
1077
1231
|
acceptingTurns: true,
|
|
1232
|
+
pendingInterrupts: pending,
|
|
1078
1233
|
settleMode: 'auto',
|
|
1079
1234
|
timestamp: pausedAt,
|
|
1080
1235
|
});
|
|
@@ -1102,6 +1257,7 @@ class LoopRunManager {
|
|
|
1102
1257
|
projectId: req.projectId,
|
|
1103
1258
|
jobId: runId,
|
|
1104
1259
|
acceptingTurns: false,
|
|
1260
|
+
pendingInterrupts: [],
|
|
1105
1261
|
settleMode: 'auto',
|
|
1106
1262
|
timestamp: resumedAt,
|
|
1107
1263
|
});
|
|
@@ -1128,12 +1284,41 @@ class LoopRunManager {
|
|
|
1128
1284
|
phaseRecovery = undefined;
|
|
1129
1285
|
return failedId === nodeId ? successor : failedId;
|
|
1130
1286
|
};
|
|
1287
|
+
let definitionCompletion;
|
|
1131
1288
|
const firstStepId = start ? req.graph.edges.find((e) => e.source === start.id)?.target : undefined;
|
|
1132
1289
|
try {
|
|
1133
1290
|
let nodeId = start?.id;
|
|
1134
1291
|
let settled = !start; // no start node → fall through to settle as failed
|
|
1135
1292
|
if (!start)
|
|
1136
1293
|
outcome = 'failed';
|
|
1294
|
+
if (definitionEngine) {
|
|
1295
|
+
settled = true;
|
|
1296
|
+
const projectEvent = (0, loop_definition_events_1.createDefinitionEventProjection)({ db: this.db, runId, projectId: req.projectId, ticketIds: exactTicketIds, nextSequence: takeSeq,
|
|
1297
|
+
broadcast: event => this._emit({ type: 'event', jobId: runId, event_type: event.eventType, source: 'stdout', payload: event.payload, seq: event.seq, timestamp: event.timestamp }),
|
|
1298
|
+
onProgress: (count, usage) => { stepNum = count; totalCost = usage.cost; totalTokens = usage.tokensIn + usage.tokensOut; totalDuration = usage.duration; costUncertain = usage.costUnknown; usageTelemetryAvailable = usage.present; },
|
|
1299
|
+
});
|
|
1300
|
+
let activeDurationMs = continuation ? (0, loop_runs_store_1.getLoopRun)(this.db, runId)?.total_duration_ms ?? 0 : 0;
|
|
1301
|
+
const result = await (0, loop_definition_run_1.runDefinitionLoop)(req, runId, { continuation, contextPath: () => (0, loop_runs_store_1.readDefinitionRun)(this.db, runId)?.metadata.contextPath,
|
|
1302
|
+
onPrepared: metadata => { (0, loop_runs_store_1.saveDefinitionRun)(this.db, runId, metadata); },
|
|
1303
|
+
invoke: input => { this.claimDefinition({ ...req, runId }); return this.executors.runDefinition(input); }, isCancelled: () => this._cancelled.has(runId),
|
|
1304
|
+
remainingMs: () => req.graph.config.timeoutMinutes > 0 ? Math.max(1, req.graph.config.timeoutMinutes * 60_000 - activeDurationMs) : undefined,
|
|
1305
|
+
onLine: logLine, onRuntimeEvent: projectEvent, onSpawn: child => {
|
|
1306
|
+
this._activeChild.set(runId, child);
|
|
1307
|
+
if (this._cancelled.has(runId))
|
|
1308
|
+
this.cancelResident(runId, false);
|
|
1309
|
+
},
|
|
1310
|
+
onInvocationEnd: result => { this._activeChild.delete(runId); if (result.runtimeStatus === 'paused')
|
|
1311
|
+
this.releaseDefinition(runId); if (result.durationMs !== undefined) {
|
|
1312
|
+
activeDurationMs = result.durationMs;
|
|
1313
|
+
totalDuration = result.durationMs;
|
|
1314
|
+
} }, awaitHumanDecision, });
|
|
1315
|
+
definitionCompletion = result.completion;
|
|
1316
|
+
if (result.durationMs !== undefined)
|
|
1317
|
+
totalDuration = result.durationMs;
|
|
1318
|
+
if (result.errorText)
|
|
1319
|
+
logLine(result.errorText, 'stderr');
|
|
1320
|
+
outcome = result.runtimeStatus === 'succeeded' ? 'success' : result.runtimeStatus === 'cancelled' ? 'stopped' : result.runtimeStatus === 'blocked' ? 'blocked' : 'failed';
|
|
1321
|
+
}
|
|
1137
1322
|
while (nodeId && !settled) {
|
|
1138
1323
|
if (this._cancelled.has(runId)) {
|
|
1139
1324
|
outcome = 'stopped';
|
|
@@ -1771,7 +1956,7 @@ class LoopRunManager {
|
|
|
1771
1956
|
try {
|
|
1772
1957
|
const recoveredSteps = recoverOrphanLoopStepAccounting(this.db, new Date(this.now()).toISOString(), runId);
|
|
1773
1958
|
this._activeStepRecovery.delete(runId);
|
|
1774
|
-
runtimeUsage = programmaticUsageAvailability(this.db, runId);
|
|
1959
|
+
runtimeUsage = definitionEngine ? (0, loop_definition_events_1.readDefinitionUsage)(this.db, runId) : programmaticUsageAvailability(this.db, runId);
|
|
1775
1960
|
usageTelemetryAvailable ||= runtimeUsage.present;
|
|
1776
1961
|
const aggregate = this.db.prepare(`
|
|
1777
1962
|
SELECT COALESCE(SUM(total_cost_usd), 0) AS cost,
|
|
@@ -1819,10 +2004,18 @@ class LoopRunManager {
|
|
|
1819
2004
|
// terminal snapshot alongside counters so history does not depend on prose.
|
|
1820
2005
|
let coreCompletion = null;
|
|
1821
2006
|
try {
|
|
1822
|
-
|
|
2007
|
+
if (!definitionEngine)
|
|
2008
|
+
coreCompletion = await this.executors.readCoreCompletion?.(runId) ?? null;
|
|
1823
2009
|
}
|
|
1824
2010
|
catch { /* old/unavailable runtime */ }
|
|
2011
|
+
if (definitionEngine) {
|
|
2012
|
+
const usage = (0, loop_definition_events_1.readDefinitionUsage)(this.db, runId);
|
|
2013
|
+
usageTelemetryAvailable = usage.present;
|
|
2014
|
+
finalJobUsage = { tokensIn: usage.present && !usage.tokensInUnknown ? usage.tokensIn : null, tokensOut: usage.present && !usage.tokensOutUnknown ? usage.tokensOut : null, tokensCacheRead: usage.present && !usage.cacheReadUnknown ? usage.cacheRead : null, tokensCacheCreate: usage.present && !usage.cacheCreateUnknown ? usage.cacheCreate : null, numTurns: usage.present && !usage.turnsUnknown ? usage.turns : null };
|
|
2015
|
+
}
|
|
1825
2016
|
const executionOutcome = outcome;
|
|
2017
|
+
if (definitionEngine && outcome === 'success' && !definitionCompletion?.ok)
|
|
2018
|
+
outcome = 'blocked';
|
|
1826
2019
|
if (outcome === 'success' && coreCompletion && (coreCompletion.completion.implementation !== 'complete' || !['verified', 'with-exceptions'].includes(coreCompletion.completion.validation)))
|
|
1827
2020
|
outcome = 'blocked';
|
|
1828
2021
|
const costAvailable = usageTelemetryAvailable && !runtimeUsage.costUnknown;
|
|
@@ -1831,7 +2024,7 @@ class LoopRunManager {
|
|
|
1831
2024
|
emitRunEvent('loop_completion', {
|
|
1832
2025
|
version: 1, execution: executionOutcome, steps: stepNum, deciderEvaluations: iteration,
|
|
1833
2026
|
turns: finalJobUsage.numTurns, costUsd: usageTelemetryAvailable ? totalCost : null,
|
|
1834
|
-
costUncertain, core: coreCompletion,
|
|
2027
|
+
costUncertain, core: coreCompletion, ...(definitionEngine ? { engineVersion: 2, completion: definitionCompletion } : {}),
|
|
1835
2028
|
});
|
|
1836
2029
|
// Settle the backing job so the Jobs list + JobDetail reflect the final
|
|
1837
2030
|
// status, and emit job.finalized so an open JobDetail re-fetches + stops the
|