specrails-desktop 2.55.0 → 2.55.1
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/cli/dist/args.js +80 -0
- package/cli/dist/desktop-client.js +125 -0
- package/cli/dist/desktop-control.js +339 -0
- package/cli/dist/format.js +45 -0
- package/cli/dist/help.js +68 -0
- package/cli/dist/output.js +47 -0
- package/cli/dist/run-command.js +340 -0
- package/cli/dist/specrails-desktop.js +41 -1107
- package/cli/dist/status.js +111 -0
- package/client/dist/assets/{ActivityFeedPage-ILXMZXcb.js → ActivityFeedPage-DmJcQpNe.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-UcsupCy7.js → AgentBrowserCapture-NxBHrU-V.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-CQuxYh8B.js → AgentModeAnalyticsPane-CGAKTJfU.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-zPWbW7ei.js → AgentModeCodePane-DNSs5_oe.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-CInByIdl.js → AgentModeJobsPane-DLoVYDnG.js} +1 -1
- package/client/dist/assets/{AgentsPage-BWvgxaBv.js → AgentsPage-CAzMn9Gg.js} +1 -1
- package/client/dist/assets/{AnalyticsPage-DP3jakv-.js → AnalyticsPage-C06KT4Y0.js} +1 -1
- package/client/dist/assets/{CodePage-BKXiwE5a.js → CodePage-aX1mxGyT.js} +1 -1
- package/client/dist/assets/{DesktopAnalyticsPage-DryJOaMz.js → DesktopAnalyticsPage-BtscfiQD.js} +1 -1
- package/client/dist/assets/{DocsDialog-BsCG9ksG.js → DocsDialog-CNOcXhp-.js} +1 -1
- package/client/dist/assets/{DocsPage-Cc-GeKYl.js → DocsPage-C2BugxaI.js} +1 -1
- package/client/dist/assets/{ExportDropdown-ClahJdDn.js → ExportDropdown-BVGKEgkd.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-DfLF6N0f.js → InteractiveJobComposer-CCncBqNu.js} +1 -1
- package/client/dist/assets/{JobDetailModal-DHeur9YK.js → JobDetailModal-Cn_k3-RM.js} +1 -1
- package/client/dist/assets/{JobDetailPage-CraDKzeG.js → JobDetailPage-BogJFBsk.js} +1 -1
- package/client/dist/assets/{JobsPage-CcbuSwj7.js → JobsPage-DL4E8ZyU.js} +1 -1
- package/client/dist/assets/{LoopBuilderPage-BKtNp494.js → LoopBuilderPage-9L6URQLY.js} +1 -1
- package/client/dist/assets/{LoopPreviewModal-DbZd9isy.js → LoopPreviewModal-CAPqTIgL.js} +1 -1
- package/client/dist/assets/{LoopsPage-DEg6sIkG.js → LoopsPage-aU8dYw7L.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-BGtEjWsc.js → MinimizedChatsContext-D3QzgV0B.js} +1 -1
- package/client/dist/assets/{PluginsPage-BVqSsPzL.js → PluginsPage-D_tsW9B5.js} +1 -1
- package/client/dist/assets/{ProjectSettingsDialog-CAjLgJAZ.js → ProjectSettingsDialog-_ZbNuspP.js} +1 -1
- package/client/dist/assets/{RepositoryDeliveries-DrcrxLe0.js → RepositoryDeliveries-Du2UCf1a.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-CAGY3xW6.js → RepositoryScopeSelector-hPGZNRBm.js} +1 -1
- package/client/dist/assets/ReviewPacketPage-CG-Dv0El.js +4 -0
- package/client/dist/assets/{TemplatePreviewModal-Bqs-9fhn.js → TemplatePreviewModal-C19H2b2o.js} +1 -1
- package/client/dist/assets/{TicketDetailModalContext-C0jQ5yOk.js → TicketDetailModalContext-DAK-NoK6.js} +1 -1
- package/client/dist/assets/{Trans-DtWlCJN9.js → Trans-DEbgkuAY.js} +1 -1
- package/client/dist/assets/{dashboard-CTfEtkqX.js → dashboard-B9uWNGO2.js} +1 -1
- package/client/dist/assets/{dashboard-DMklepmz.js → dashboard-BIwmO9wc.js} +1 -1
- package/client/dist/assets/{dashboard-DBAP2_SQ.js → dashboard-BV4vOZkR.js} +1 -1
- package/client/dist/assets/{dashboard-D40HP2ks.js → dashboard-Bf6MPVsM.js} +1 -1
- package/client/dist/assets/{dashboard-Csf1yGSN.js → dashboard-C8klWVvZ.js} +1 -1
- package/client/dist/assets/{dashboard-C29Qwa-L.js → dashboard-D1ORhPF0.js} +1 -1
- package/client/dist/assets/{dashboard-Cr4D8oMn.js → dashboard-DSubvs9x.js} +1 -1
- package/client/dist/assets/{dashboard-CSJzf5OT.js → dashboard-px_vlRx_.js} +1 -1
- package/client/dist/assets/{formatDistanceToNow-DYmvOA3R.js → formatDistanceToNow-Cc2u5FwQ.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-BAhW5E6V.js → getTimezoneOffsetInMilliseconds-BHm2U-w1.js} +1 -1
- package/client/dist/assets/{index-BfAZg5DG.js → index-BcligJ3-.js} +29 -29
- package/client/dist/assets/index-C51x61Bz.css +2 -0
- package/client/dist/assets/{jira-api-B27Za5FP.js → jira-api-DrGxiD9p.js} +1 -1
- package/client/dist/assets/packet-8nn9RsU7.js +1 -0
- package/client/dist/assets/packet-B0H15elv.js +1 -0
- package/client/dist/assets/packet-BQvBgrwh.js +1 -0
- package/client/dist/assets/packet-BR7mO0-a.js +1 -0
- package/client/dist/assets/packet-BgcQ6q_K.js +1 -0
- package/client/dist/assets/packet-D2s92Jnn.js +1 -0
- package/client/dist/assets/packet-YbtcD1HS.js +1 -0
- package/client/dist/assets/packet-c0Qj_9eX.js +1 -0
- package/client/dist/assets/{project-repositories-DixIZHTA.js → project-repositories-9Wzs0coQ.js} +1 -1
- package/client/dist/assets/{spending-BGmZBX5B.js → spending-T5GM7wpn.js} +1 -1
- package/client/dist/assets/{useDesktop-CPB4cnwI.js → useDesktop-QogiN0zR.js} +1 -1
- package/client/dist/assets/{useRuntimeRuns-DEQ9HdAM.js → useRuntimeRuns-Dqmz9fS9.js} +1 -1
- package/client/dist/assets/{useSharedWebSocket-DcPRKR8R.js → useSharedWebSocket-Dz-HI6De.js} +2 -2
- package/client/dist/index.html +17 -17
- package/docs/codex.md +5 -5
- package/docs/customizing.md +1 -1
- package/docs/gemini-cli-provider-study.md +14 -14
- package/docs/gemini-core-support-evaluation.md +1 -1
- package/docs/gemini.md +5 -5
- package/docs/internals/README.md +6 -2
- package/docs/internals/adding-a-provider.md +15 -15
- package/docs/internals/agent-runtime-framework-evaluation.md +8 -8
- package/docs/internals/api-reference.md +2 -2
- package/docs/internals/architecture.md +9 -9
- package/docs/internals/browser-capture-performance.md +3 -3
- package/docs/internals/code-explorer-story.md +2 -2
- package/docs/internals/companion-rails-as-loops-contract.md +2 -2
- package/docs/internals/embedded-browser-native-webview-evaluation.md +5 -5
- package/docs/internals/gemini-mcp-registration.md +2 -2
- package/docs/internals/global-artifacts-alignment-contract.md +1 -1
- package/docs/internals/global-artifacts-relocation-evaluation.md +1 -1
- package/docs/internals/interactive-jobs.md +8 -8
- package/docs/internals/legacy-implementation-notes.md +722 -0
- package/docs/internals/loop-step-log-explorer.md +8 -8
- package/docs/internals/mission-rail-cards.md +14 -14
- package/docs/internals/modular-architecture.md +107 -0
- package/docs/internals/profiles.md +1 -1
- package/docs/internals/project-builder.md +18 -18
- package/docs/internals/review-packet.md +8 -8
- package/docs/internals/safe-pr-review-flow.md +11 -11
- package/docs/internals/source-architecture.md +131 -0
- package/docs/internals/source-map.md +1354 -0
- package/docs/internals/spec-addenda.md +65 -9
- package/docs/internals/switch-to-agent-mode-design.md +11 -11
- package/docs/tracking-cost.md +1 -1
- package/package.json +5 -2
- package/server/dist/agent-mcp-config.js +1 -1
- package/server/dist/attachment-manager.js +1 -1
- package/server/dist/build-dirs.js +2 -2
- package/server/dist/config.js +0 -3
- package/server/dist/core-completion.js +1 -1
- package/server/dist/core-execution.js +1 -1
- package/server/dist/db/activity.js +39 -0
- package/server/dist/db/connection.js +41 -0
- package/server/dist/db/conversations.js +48 -0
- package/server/dist/db/jobs.js +251 -0
- package/server/dist/db/migrations.js +1521 -0
- package/server/dist/db/proposals.js +50 -0
- package/server/dist/db/settings.js +15 -0
- package/server/dist/db/stats.js +61 -0
- package/server/dist/db/telemetry.js +56 -0
- package/server/dist/db/templates.js +37 -0
- package/server/dist/db/types.js +2 -0
- package/server/dist/db.js +66 -2224
- package/server/dist/desktop-db.js +3 -3
- package/server/dist/desktop-router.js +8 -8
- package/server/dist/git-diagnostics.js +1 -1
- package/server/dist/index.js +11 -11
- package/server/dist/integration-branch.js +3 -14
- package/server/dist/jira/jira-issue-fields.js +0 -1
- package/server/dist/jira/jira-materializer.js +1 -1
- package/server/dist/jira/jira-sync-manager.js +1 -1
- package/server/dist/mcp/mcp-admin-router.js +1 -1
- package/server/dist/mcp/mcp-server.js +1 -1
- package/server/dist/mcp/tools/jobs.js +1 -1
- package/server/dist/mcp/tools/rails.js +2 -2
- package/server/dist/mcp/tools/specs.js +2 -2
- package/server/dist/mcp/tools/types.js +3 -3
- package/server/dist/mobile/mobile-gateway.js +1 -1
- package/server/dist/mobile/mobile-missions.js +1 -1
- package/server/dist/{desktop-analytics.js → modules/accounting/runtime/desktop-analytics.js} +2 -2
- package/server/dist/{pricing.js → modules/accounting/runtime/pricing.js} +1 -1
- package/server/dist/{result-event.js → modules/accounting/runtime/result-event.js} +3 -3
- package/server/dist/{spending.js → modules/accounting/runtime/spending.js} +0 -3
- package/server/dist/{telemetry-compactor.js → modules/accounting/runtime/telemetry-compactor.js} +1 -1
- package/server/dist/{telemetry-receiver.js → modules/accounting/runtime/telemetry-receiver.js} +2 -2
- package/server/dist/{agent-runtime-bridge.js → modules/agent-runtime/runtime/agent-runtime-bridge.js} +2 -2
- package/server/dist/{agent-runtime-controls.js → modules/agent-runtime/runtime/agent-runtime-controls.js} +7 -7
- package/server/dist/{agent-runtime-effective-config.js → modules/agent-runtime/runtime/agent-runtime-effective-config.js} +1 -1
- package/server/dist/{agent-runtime-loader.js → modules/agent-runtime/runtime/agent-runtime-loader.js} +3 -3
- package/server/dist/{agent-runtime-paths.js → modules/agent-runtime/runtime/agent-runtime-paths.js} +1 -1
- package/server/dist/{agent-runtime-settings-router.js → modules/agent-runtime/runtime/agent-runtime-settings-router.js} +2 -2
- package/server/dist/{agent-runtime-settings.js → modules/agent-runtime/runtime/agent-runtime-settings.js} +3 -3
- package/server/dist/{agent-runtime-settlement.js → modules/agent-runtime/runtime/agent-runtime-settlement.js} +6 -6
- package/server/dist/{agent-defaults.js → modules/agents/runtime/agent-defaults.js} +3 -3
- package/server/dist/{agent-generator.js → modules/agents/runtime/agent-generator.js} +7 -7
- package/server/dist/{agent-refine-manager.js → modules/agents/runtime/agent-refine-manager.js} +5 -5
- package/server/dist/{agent-store.js → modules/agents/runtime/agent-store.js} +1 -1
- package/server/dist/{profile-manager.js → modules/agents/runtime/profile-manager.js} +2 -2
- package/server/dist/{profiles-router.js → modules/agents/runtime/profiles-router.js} +5 -5
- package/server/dist/{browser-capture-manager.js → modules/browser/runtime/browser-capture-manager.js} +2 -4
- package/server/dist/{browser-playwright.js → modules/browser/runtime/browser-playwright.js} +1 -1
- package/server/dist/{blueprint-chat-manager.js → modules/builder/runtime/blueprint-chat-manager.js} +7 -7
- package/server/dist/{blueprint-commit.js → modules/builder/runtime/blueprint-commit.js} +8 -8
- package/server/dist/{blueprint-draft-parser.js → modules/builder/runtime/blueprint-draft-parser.js} +1 -1
- package/server/dist/{blueprint-generation.js → modules/builder/runtime/blueprint-generation.js} +1 -1
- package/server/dist/{blueprint-operator-prompt.js → modules/builder/runtime/blueprint-operator-prompt.js} +1 -1
- package/server/dist/{blueprint-router.js → modules/builder/runtime/blueprint-router.js} +3 -3
- package/server/dist/{blueprint-spec-quality.js → modules/builder/runtime/blueprint-spec-quality.js} +1 -1
- package/server/dist/{milestone-chain.js → modules/builder/runtime/milestone-chain.js} +1 -1
- package/server/dist/{milestone-progress.js → modules/builder/runtime/milestone-progress.js} +6 -6
- package/server/dist/{code-activity.js → modules/code/runtime/code-activity.js} +1 -1
- package/server/dist/{code-explorer-router.js → modules/code/runtime/code-explorer-router.js} +5 -5
- package/server/dist/{file-provenance.js → modules/code/runtime/file-provenance.js} +1 -1
- package/server/dist/{file-story-manager.js → modules/code/runtime/file-story-manager.js} +2 -2
- package/server/dist/{file-story.js → modules/code/runtime/file-story.js} +2 -2
- package/server/dist/{file-summary-generator.js → modules/code/runtime/file-summary-generator.js} +3 -3
- package/server/dist/{file-summary-manager.js → modules/code/runtime/file-summary-manager.js} +3 -3
- package/server/dist/{project-code-discovery.js → modules/code/runtime/project-code-discovery.js} +2 -2
- package/server/dist/modules/conversations/domain/draft-stream.js +91 -0
- package/server/dist/modules/conversations/domain/recovery-context.js +101 -0
- package/server/dist/modules/conversations/index.js +10 -0
- package/server/dist/{chat-manager.js → modules/conversations/runtime/chat-manager.js} +32 -216
- package/server/dist/{context-budget.js → modules/conversations/runtime/context-budget.js} +1 -1
- package/server/dist/{explore-cwd-manager.js → modules/conversations/runtime/explore-cwd-manager.js} +1 -1
- package/server/dist/{explore-smash.js → modules/conversations/runtime/explore-smash.js} +1 -1
- package/server/dist/{explore-stdin-session.js → modules/conversations/runtime/explore-stdin-session.js} +1 -1
- package/server/dist/modules/delivery/adapters/decisions/chains.js +138 -0
- package/server/dist/modules/delivery/adapters/decisions/contracts.js +2 -0
- package/server/dist/modules/delivery/adapters/decisions/create.js +234 -0
- package/server/dist/modules/delivery/adapters/decisions/discard.js +251 -0
- package/server/dist/modules/delivery/adapters/decisions/dispatch.js +107 -0
- package/server/dist/modules/delivery/adapters/decisions/evidence.js +205 -0
- package/server/dist/modules/delivery/adapters/decisions/merge-local.js +338 -0
- package/server/dist/modules/delivery/adapters/decisions/metadata.js +109 -0
- package/server/dist/modules/delivery/adapters/decisions/observations.js +260 -0
- package/server/dist/modules/delivery/adapters/decisions/ownership.js +83 -0
- package/server/dist/modules/delivery/adapters/decisions/publish.js +242 -0
- package/server/dist/modules/delivery/adapters/decisions/recovery.js +425 -0
- package/server/dist/modules/delivery/adapters/decisions/retry.js +112 -0
- package/server/dist/modules/delivery/adapters/decisions/transitions.js +94 -0
- package/server/dist/modules/delivery/domain/decision-policy.js +50 -0
- package/server/dist/modules/delivery/domain/state.js +2 -0
- package/server/dist/modules/delivery/index.js +7 -0
- package/server/dist/{active-pr-continuation.js → modules/delivery/runtime/active-pr-continuation.js} +2 -2
- package/server/dist/{delivery-evidence.js → modules/delivery/runtime/delivery-evidence.js} +3 -3
- package/server/dist/{multi-repo-bases.js → modules/delivery/runtime/multi-repo-bases.js} +1 -1
- package/server/dist/{multi-repo-checkout.js → modules/delivery/runtime/multi-repo-checkout.js} +4 -4
- package/server/dist/{multi-repo-delivery.js → modules/delivery/runtime/multi-repo-delivery.js} +4 -4
- package/server/dist/{multi-repo-execution.js → modules/delivery/runtime/multi-repo-execution.js} +8 -8
- package/server/dist/{pr-body.js → modules/delivery/runtime/pr-body.js} +1 -1
- package/server/dist/{pr-follow-up-scope.js → modules/delivery/runtime/pr-follow-up-scope.js} +2 -2
- package/server/dist/{pr-follow-up.js → modules/delivery/runtime/pr-follow-up.js} +1 -1
- package/server/dist/{pr-naming.js → modules/delivery/runtime/pr-naming.js} +1 -1
- package/server/dist/{pr-publisher.js → modules/delivery/runtime/pr-publisher.js} +2 -2
- package/server/dist/{rail-isolated-launch.js → modules/delivery/runtime/rail-isolated-launch.js} +29 -27
- package/server/dist/{rail-launch-parser.js → modules/delivery/runtime/rail-launch-parser.js} +2 -2
- package/server/dist/{rail-merge-orchestrator.js → modules/delivery/runtime/rail-merge-orchestrator.js} +5 -5
- package/server/dist/modules/delivery/runtime/rail-pr-decision.js +12 -0
- package/server/dist/{rail-pr-delivery.js → modules/delivery/runtime/rail-pr-delivery.js} +1 -1
- package/server/dist/{rail-pr-store.js → modules/delivery/runtime/rail-pr-store.js} +2 -2
- package/server/dist/{rail-pr-ticket-effects.js → modules/delivery/runtime/rail-pr-ticket-effects.js} +3 -3
- package/server/dist/{rail-worktree-release.js → modules/delivery/runtime/rail-worktree-release.js} +4 -4
- package/server/dist/{rails-router.js → modules/delivery/runtime/rails-router.js} +66 -67
- package/server/dist/{review-packet.js → modules/delivery/runtime/review-packet.js} +3 -3
- package/server/dist/modules/execution/adapters/budget-storage.js +21 -0
- package/server/dist/modules/execution/adapters/usage-reader.js +38 -0
- package/server/dist/modules/execution/application/enforce-budget.js +14 -0
- package/server/dist/modules/execution/application/record-job-invocations.js +64 -0
- package/server/dist/modules/execution/application/recover-job-usage.js +200 -0
- package/server/dist/modules/execution/domain/job-accounting.js +2 -0
- package/server/dist/modules/execution/domain/scheduling.js +24 -0
- package/server/dist/modules/execution/domain/usage.js +21 -0
- package/server/dist/modules/execution/index.js +14 -0
- package/server/dist/modules/execution/ports.js +2 -0
- package/server/dist/{accept-ladder.js → modules/execution/runtime/accept-ladder.js} +1 -1
- package/server/dist/{interactive-job-session.js → modules/execution/runtime/interactive-job-session.js} +11 -11
- package/server/dist/{job-phase-breakdown.js → modules/execution/runtime/job-phase-breakdown.js} +1 -1
- package/server/dist/{queue-manager.js → modules/execution/runtime/queue-manager.js} +74 -491
- package/server/dist/{revision-seed.js → modules/execution/runtime/revision-seed.js} +1 -1
- package/server/dist/{spawn-lifecycle.js → modules/execution/runtime/spawn-lifecycle.js} +3 -3
- package/server/dist/{stuck-run-detector.js → modules/execution/runtime/stuck-run-detector.js} +1 -1
- package/server/dist/{loop-command-catalog.js → modules/loops/runtime/loop-command-catalog.js} +1 -1
- package/server/dist/{loop-executors.js → modules/loops/runtime/loop-executors.js} +17 -17
- package/server/dist/{loop-factory.js → modules/loops/runtime/loop-factory.js} +2 -21
- package/server/dist/{loop-graph.js → modules/loops/runtime/loop-graph.js} +25 -0
- package/server/dist/{loop-role-engines.js → modules/loops/runtime/loop-role-engines.js} +4 -4
- package/server/dist/{loop-run-manager.js → modules/loops/runtime/loop-run-manager.js} +101 -26
- package/server/dist/{loop-runs-store.js → modules/loops/runtime/loop-runs-store.js} +1 -1
- package/server/dist/{loop-shell-invocation.js → modules/loops/runtime/loop-shell-invocation.js} +2 -2
- package/server/dist/{loop-step-idle.js → modules/loops/runtime/loop-step-idle.js} +1 -1
- package/server/dist/{loop-templates.js → modules/loops/runtime/loop-templates.js} +24 -29
- package/server/dist/{loops-router.js → modules/loops/runtime/loops-router.js} +2 -2
- package/server/dist/{agent-chat-manager.js → modules/missions/runtime/agent-chat-manager.js} +19 -19
- package/server/dist/{agent-chat-router.js → modules/missions/runtime/agent-chat-router.js} +6 -6
- package/server/dist/{agent-context-resolver.js → modules/missions/runtime/agent-context-resolver.js} +8 -8
- package/server/dist/{agent-fence-promotion.js → modules/missions/runtime/agent-fence-promotion.js} +1 -1
- package/server/dist/{agent-input-store.js → modules/missions/runtime/agent-input-store.js} +1 -1
- package/server/dist/{agent-operator-prompt.js → modules/missions/runtime/agent-operator-prompt.js} +17 -7
- package/server/dist/{agent-spec-framing.js → modules/missions/runtime/agent-spec-framing.js} +4 -4
- package/server/dist/{agent-steering.js → modules/missions/runtime/agent-steering.js} +1 -1
- package/server/dist/{mission-run-notify.js → modules/missions/runtime/mission-run-notify.js} +1 -1
- package/server/dist/modules/project-settings/adapters/http.js +24 -0
- package/server/dist/modules/project-settings/adapters/sqlite.js +120 -0
- package/server/dist/modules/project-settings/application.js +11 -0
- package/server/dist/modules/project-settings/domain.js +95 -0
- package/server/dist/modules/project-settings/index.js +11 -0
- package/server/dist/modules/project-settings/ports.js +2 -0
- package/server/dist/{contract-refine-runner.js → modules/specs/runtime/contract-refine-runner.js} +12 -12
- package/server/dist/{proposal-manager.js → modules/specs/runtime/proposal-manager.js} +8 -8
- package/server/dist/{smash-runner.js → modules/specs/runtime/smash-runner.js} +26 -58
- package/server/dist/{spec-addenda-core.js → modules/specs/runtime/spec-addenda-core.js} +2 -2
- package/server/dist/{spec-addenda.js → modules/specs/runtime/spec-addenda.js} +3 -3
- package/server/dist/{spec-launcher-manager.js → modules/specs/runtime/spec-launcher-manager.js} +8 -8
- package/server/dist/{spec-models.js → modules/specs/runtime/spec-models.js} +1 -1
- package/server/dist/{ticket-watcher.js → modules/specs/runtime/ticket-watcher.js} +1 -1
- package/server/dist/{background-process-control.js → modules/terminals/runtime/background-process-control.js} +1 -1
- package/server/dist/{background-process-service.js → modules/terminals/runtime/background-process-service.js} +3 -3
- package/server/dist/{background-process-store.js → modules/terminals/runtime/background-process-store.js} +1 -1
- package/server/dist/{background-windows-bootstrap.js → modules/terminals/runtime/background-windows-bootstrap.js} +3 -3
- package/server/dist/{terminal-manager.js → modules/terminals/runtime/terminal-manager.js} +3 -3
- package/server/dist/project-git.js +1 -1
- package/server/dist/project-profile-support.js +32 -0
- package/server/dist/project-registry.js +34 -40
- package/server/dist/project-router-background-processes.js +1 -1
- package/server/dist/project-router-chat.js +6 -6
- package/server/dist/project-router-git.js +1 -1
- package/server/dist/project-router-helpers.js +2 -2
- package/server/dist/project-router-jobs.js +14 -12
- package/server/dist/project-router-loop-runs.js +12 -12
- package/server/dist/project-router-settings.js +15 -75
- package/server/dist/project-router-setup.js +2 -2
- package/server/dist/project-router-spending.js +4 -4
- package/server/dist/project-router-terminals.js +4 -4
- package/server/dist/project-router-tickets.js +14 -14
- package/server/dist/project-router.js +13 -13
- package/server/dist/providers/codex-adapter.js +3 -3
- package/server/dist/providers/gemini-adapter.js +1 -1
- package/server/dist/providers/telemetry-env.js +55 -0
- package/server/dist/runtime-role-prompts-router.js +2 -2
- package/server/dist/setup-manager.js +2 -48
- package/server/dist/shared/git-branch-name.js +16 -0
- package/server/dist/transient-children.js +3 -3
- package/server/dist/util/distribute-int.js +33 -0
- package/client/dist/assets/ReviewPacketPage-D-UjTef3.js +0 -4
- package/client/dist/assets/index-BAtqmAZR.css +0 -2
- package/client/dist/assets/packet-CjS_478C.js +0 -1
- package/client/dist/assets/packet-D69dKsHN.js +0 -1
- package/client/dist/assets/packet-D9rU6Oxo.js +0 -1
- package/client/dist/assets/packet-DMDFoamg.js +0 -1
- package/client/dist/assets/packet-Dd2RMs1h.js +0 -1
- package/client/dist/assets/packet-DjC9OibC.js +0 -1
- package/client/dist/assets/packet-DwPtJoDz.js +0 -1
- package/client/dist/assets/packet-ceahDg8_.js +0 -1
- package/server/dist/rail-pr-decision.js +0 -2377
- package/server/dist/ticket-broadcast.js +0 -47
- /package/server/dist/{ai-invocations.js → modules/accounting/runtime/ai-invocations.js} +0 -0
- /package/server/dist/{codex-otel-bridge.js → modules/accounting/runtime/codex-otel-bridge.js} +0 -0
- /package/server/dist/{metrics.js → modules/accounting/runtime/metrics.js} +0 -0
- /package/server/dist/{telemetry-export.js → modules/accounting/runtime/telemetry-export.js} +0 -0
- /package/server/dist/{agent-runtime-accounting.js → modules/agent-runtime/runtime/agent-runtime-accounting.js} +0 -0
- /package/server/dist/{agent-runtime-controls-router.js → modules/agent-runtime/runtime/agent-runtime-controls-router.js} +0 -0
- /package/server/dist/{agent-runtime-events.js → modules/agent-runtime/runtime/agent-runtime-events.js} +0 -0
- /package/server/dist/{agent-runtime-history.js → modules/agent-runtime/runtime/agent-runtime-history.js} +0 -0
- /package/server/dist/{agent-runtime-metrics.js → modules/agent-runtime/runtime/agent-runtime-metrics.js} +0 -0
- /package/server/dist/{agent-runtime-package.js → modules/agent-runtime/runtime/agent-runtime-package.js} +0 -0
- /package/server/dist/{agent-runtime-repositories.js → modules/agent-runtime/runtime/agent-runtime-repositories.js} +0 -0
- /package/server/dist/{agent-runtime-verification-suggestions.js → modules/agent-runtime/runtime/agent-runtime-verification-suggestions.js} +0 -0
- /package/server/dist/{agent-refine-db.js → modules/agents/runtime/agent-refine-db.js} +0 -0
- /package/server/dist/{browser-capture-types.js → modules/browser/runtime/browser-capture-types.js} +0 -0
- /package/server/dist/{browser-context-pool.js → modules/browser/runtime/browser-context-pool.js} +0 -0
- /package/server/dist/{browser-network.js → modules/browser/runtime/browser-network.js} +0 -0
- /package/server/dist/{browser-viewport.js → modules/browser/runtime/browser-viewport.js} +0 -0
- /package/server/dist/{blueprint-render.js → modules/builder/runtime/blueprint-render.js} +0 -0
- /package/server/dist/{blueprint-spec-fixtures.js → modules/builder/runtime/blueprint-spec-fixtures.js} +0 -0
- /package/server/dist/{blueprint-store.js → modules/builder/runtime/blueprint-store.js} +0 -0
- /package/server/dist/{blueprint-types.js → modules/builder/runtime/blueprint-types.js} +0 -0
- /package/server/dist/{builder-cwd-manager.js → modules/builder/runtime/builder-cwd-manager.js} +0 -0
- /package/server/dist/{milestone-chain-store.js → modules/builder/runtime/milestone-chain-store.js} +0 -0
- /package/server/dist/{changes-reader.js → modules/code/runtime/changes-reader.js} +0 -0
- /package/server/dist/{context-scope.js → modules/conversations/runtime/context-scope.js} +0 -0
- /package/server/dist/{explore-contract-refine.js → modules/conversations/runtime/explore-contract-refine.js} +0 -0
- /package/server/dist/{explore-draft-title.js → modules/conversations/runtime/explore-draft-title.js} +0 -0
- /package/server/dist/{merge-manager.js → modules/delivery/runtime/merge-manager.js} +0 -0
- /package/server/dist/{multi-repo-execution-store.js → modules/delivery/runtime/multi-repo-execution-store.js} +0 -0
- /package/server/dist/{pr-lifecycle.js → modules/delivery/runtime/pr-lifecycle.js} +0 -0
- /package/server/dist/{rail-isolation.js → modules/delivery/runtime/rail-isolation.js} +0 -0
- /package/server/dist/{rail-pr-recovery-git.js → modules/delivery/runtime/rail-pr-recovery-git.js} +0 -0
- /package/server/dist/{rail-worktrees-store.js → modules/delivery/runtime/rail-worktrees-store.js} +0 -0
- /package/server/dist/{rails-store.js → modules/delivery/runtime/rails-store.js} +0 -0
- /package/server/dist/{job-listing.js → modules/execution/runtime/job-listing.js} +0 -0
- /package/server/dist/{job-spawn-idempotency.js → modules/execution/runtime/job-spawn-idempotency.js} +0 -0
- /package/server/dist/{run-duration-stats.js → modules/execution/runtime/run-duration-stats.js} +0 -0
- /package/server/dist/{verification-sentinel.js → modules/execution/runtime/verification-sentinel.js} +0 -0
- /package/server/dist/{loop-constants.js → modules/loops/runtime/loop-constants.js} +0 -0
- /package/server/dist/{loop-decider.js → modules/loops/runtime/loop-decider.js} +0 -0
- /package/server/dist/{loop-effect.js → modules/loops/runtime/loop-effect.js} +0 -0
- /package/server/dist/{loop-preview.js → modules/loops/runtime/loop-preview.js} +0 -0
- /package/server/dist/{loop-templates-ported.js → modules/loops/runtime/loop-templates-ported.js} +0 -0
- /package/server/dist/{loops-store.js → modules/loops/runtime/loops-store.js} +0 -0
- /package/server/dist/{agent-chat-registry.js → modules/missions/runtime/agent-chat-registry.js} +0 -0
- /package/server/dist/{agent-cwd-manager.js → modules/missions/runtime/agent-cwd-manager.js} +0 -0
- /package/server/dist/{agent-failure-briefing.js → modules/missions/runtime/agent-failure-briefing.js} +0 -0
- /package/server/dist/{agent-tier.js → modules/missions/runtime/agent-tier.js} +0 -0
- /package/server/dist/{spec-contract-prompt.js → modules/specs/runtime/spec-contract-prompt.js} +0 -0
- /package/server/dist/{spec-draft-parser.js → modules/specs/runtime/spec-draft-parser.js} +0 -0
- /package/server/dist/{ticket-store.js → modules/specs/runtime/ticket-store.js} +0 -0
- /package/server/dist/{terminal-marks-store.js → modules/terminals/runtime/terminal-marks-store.js} +0 -0
- /package/server/dist/{terminal-osc-parser.js → modules/terminals/runtime/terminal-osc-parser.js} +0 -0
- /package/server/dist/{terminal-settings.js → modules/terminals/runtime/terminal-settings.js} +0 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runCreatePr = runCreatePr;
|
|
4
|
+
const pr_publisher_1 = require("../../runtime/pr-publisher");
|
|
5
|
+
const rail_pr_delivery_1 = require("../../runtime/rail-pr-delivery");
|
|
6
|
+
const rail_worktree_release_1 = require("../../runtime/rail-worktree-release");
|
|
7
|
+
const pr_naming_1 = require("../../runtime/pr-naming");
|
|
8
|
+
const pr_body_1 = require("../../runtime/pr-body");
|
|
9
|
+
const ai_invocations_1 = require("../../../accounting/runtime/ai-invocations");
|
|
10
|
+
const rail_pr_store_1 = require("../../runtime/rail-pr-store");
|
|
11
|
+
const retry_1 = require("./retry");
|
|
12
|
+
const evidence_1 = require("./evidence");
|
|
13
|
+
const transitions_1 = require("./transitions");
|
|
14
|
+
const metadata_1 = require("./metadata");
|
|
15
|
+
const ownership_1 = require("./ownership");
|
|
16
|
+
async function runCreatePr(deps, row) {
|
|
17
|
+
if (row.decision === 'pr_failed' && row.pr_url && row.branch) {
|
|
18
|
+
return (0, retry_1.retryExistingPrFollowupPush)(deps, row);
|
|
19
|
+
}
|
|
20
|
+
const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
|
|
21
|
+
// Resolve every deliverable unit to an immutable object. New rows carry the
|
|
22
|
+
// verified final SHA from settlement; legacy rows may capture their recorded
|
|
23
|
+
// ref once. Never substitute another historical branch merely because it
|
|
24
|
+
// belongs to the same ticket.
|
|
25
|
+
let effectiveBranches = snap.branches;
|
|
26
|
+
let branchEvidenceCaptured = false;
|
|
27
|
+
const singleDeliverable = snap.branches.filter((unit) => unit.succeeded).length === 1;
|
|
28
|
+
const frozenSingleSha = singleDeliverable && row.delivery_sha && evidence_1.COMMIT_SHA_RE.test(row.delivery_sha) &&
|
|
29
|
+
await (0, evidence_1.commitObjectExists)(deps, row.delivery_sha)
|
|
30
|
+
? row.delivery_sha
|
|
31
|
+
: null;
|
|
32
|
+
for (let index = 0; index < snap.branches.length; index++) {
|
|
33
|
+
const unit = snap.branches[index];
|
|
34
|
+
if (!unit.succeeded)
|
|
35
|
+
continue;
|
|
36
|
+
// A detached/stale single-unit delivery already has authoritative immutable
|
|
37
|
+
// evidence. Prefer it over both legacy unit gaps and a branch ref that may
|
|
38
|
+
// have advanced while the card waited for the user's decision.
|
|
39
|
+
let sourceSha = frozenSingleSha ?? (unit.finalSha && evidence_1.COMMIT_SHA_RE.test(unit.finalSha) ? unit.finalSha : null);
|
|
40
|
+
if (sourceSha) {
|
|
41
|
+
if (!(await (0, evidence_1.commitObjectExists)(deps, sourceSha)))
|
|
42
|
+
sourceSha = null;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
sourceSha = await (0, evidence_1.captureBranchSha)(deps, unit.branch);
|
|
46
|
+
if (sourceSha && !(await (0, evidence_1.commitObjectExists)(deps, sourceSha)))
|
|
47
|
+
sourceSha = null;
|
|
48
|
+
}
|
|
49
|
+
if (!sourceSha) {
|
|
50
|
+
const detail = `the verified commit for branch '${unit.branch}' (ticket #${unit.ticketId}) is unavailable; refusing to deliver a mutable or unrelated ref`;
|
|
51
|
+
const conflict = (0, transitions_1.casTransition)(deps, row, 'pr_failed', {
|
|
52
|
+
deliveryOutcome: 'blocked', statusCode: 'branch_verification_failed', statusDetail: detail,
|
|
53
|
+
});
|
|
54
|
+
if (conflict)
|
|
55
|
+
return conflict;
|
|
56
|
+
(0, transitions_1.finalizeTransition)(deps, row.id);
|
|
57
|
+
return { status: 200, body: { ok: true, decision: 'pr_failed', detail } };
|
|
58
|
+
}
|
|
59
|
+
if (unit.finalSha !== sourceSha)
|
|
60
|
+
branchEvidenceCaptured = true;
|
|
61
|
+
effectiveBranches = effectiveBranches.map((branch, branchIndex) => branchIndex === index
|
|
62
|
+
? { ...branch, finalSha: sourceSha }
|
|
63
|
+
: branch);
|
|
64
|
+
}
|
|
65
|
+
// Succeeded COVERED tickets for the PR title/body: a single unit covers every
|
|
66
|
+
// launch ticket (scope='all'), per-ticket units cover exactly their own.
|
|
67
|
+
const succeededUnits = effectiveBranches.filter((b) => b.succeeded);
|
|
68
|
+
const succeededTicketIds = effectiveBranches.length === 1 && succeededUnits.length === 1
|
|
69
|
+
? snap.ticketIds
|
|
70
|
+
: succeededUnits.map((b) => b.ticketId);
|
|
71
|
+
const ticketData = (0, metadata_1.loadPrTicketData)(deps, succeededTicketIds);
|
|
72
|
+
// The batch name is derived ONLY for multi-unit deliveries — the single-ticket
|
|
73
|
+
// path delivers straight from its unit branch and must never even compute one.
|
|
74
|
+
const batchPreferred = succeededUnits.length > 1 ? (0, pr_naming_1.batchBranchNameFor)(ticketData) : null;
|
|
75
|
+
const unitBranches = new Set(effectiveBranches.map((b) => b.branch));
|
|
76
|
+
// Per-ticket covering branch for the body's honest Tests digest: per-ticket
|
|
77
|
+
// units map 1:1; a single 'all'-scope unit covers every launch ticket.
|
|
78
|
+
const branchFor = (ticketId) => {
|
|
79
|
+
const unit = succeededUnits.find((b) => b.ticketId === ticketId);
|
|
80
|
+
if (unit)
|
|
81
|
+
return unit.branch;
|
|
82
|
+
return succeededUnits.length === 1 ? succeededUnits[0].branch : null;
|
|
83
|
+
};
|
|
84
|
+
// Diffstats are best-effort: a git failure degrades the body (section
|
|
85
|
+
// omitted / "diff unavailable" note), never blocks the PR.
|
|
86
|
+
let changes = null;
|
|
87
|
+
try {
|
|
88
|
+
changes = await (0, pr_body_1.collectBranchChanges)(deps.git, deps.project.path, row.base_branch, succeededUnits.map((b) => b.branch));
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
changes = null;
|
|
92
|
+
}
|
|
93
|
+
// Cost footer is best-effort: a lookup failure omits the line, never blocks.
|
|
94
|
+
let costUsd = null;
|
|
95
|
+
try {
|
|
96
|
+
costUsd = (0, ai_invocations_1.sumInvocationCostForRuns)(deps.db, snap.runIds);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
costUsd = null;
|
|
100
|
+
}
|
|
101
|
+
const title = (0, pr_naming_1.buildPrTitle)(ticketData, { loopName: row.loop_name });
|
|
102
|
+
const body = (0, pr_body_1.buildCanonicalPrBody)({
|
|
103
|
+
loopName: row.loop_name,
|
|
104
|
+
baseBranch: row.base_branch,
|
|
105
|
+
tickets: ticketData.map((t) => ({ ...t, branch: branchFor(t.ticketId) })),
|
|
106
|
+
changes,
|
|
107
|
+
costUsd,
|
|
108
|
+
});
|
|
109
|
+
let next;
|
|
110
|
+
// Underlying git/gh failure detail for a degraded or failed delivery —
|
|
111
|
+
// relayed on the response and persisted as bounded secondary diagnostics.
|
|
112
|
+
let detail = null;
|
|
113
|
+
const patch = {};
|
|
114
|
+
if (branchEvidenceCaptured)
|
|
115
|
+
patch.branches = effectiveBranches;
|
|
116
|
+
try {
|
|
117
|
+
// A degraded multi-unit attempt already owns an assembled batch branch.
|
|
118
|
+
// Retry that exact head so exact head/base PR discovery remains idempotent;
|
|
119
|
+
// never `branch -D` a merely name-matching ref, which could destroy a user's
|
|
120
|
+
// unrelated or subsequently edited local branch.
|
|
121
|
+
let degradedBatchSha = null;
|
|
122
|
+
if (batchPreferred && row.branch && row.pr_url === null &&
|
|
123
|
+
(row.pr_state === 'pushed' || row.pr_state === 'local-only') &&
|
|
124
|
+
row.branch !== row.base_branch && !unitBranches.has(row.branch)) {
|
|
125
|
+
if (row.delivery_sha && await (0, evidence_1.commitObjectExists)(deps, row.delivery_sha)) {
|
|
126
|
+
degradedBatchSha = row.delivery_sha;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
degradedBatchSha = await (0, evidence_1.captureBranchSha)(deps, row.branch);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const result = degradedBatchSha
|
|
133
|
+
? {
|
|
134
|
+
state: 'delivered',
|
|
135
|
+
branch: row.branch,
|
|
136
|
+
pr: await (0, pr_publisher_1.publishDraftPr)(deps.exec, {
|
|
137
|
+
repoDir: deps.project.path,
|
|
138
|
+
branch: row.branch,
|
|
139
|
+
baseBranch: row.base_branch,
|
|
140
|
+
title,
|
|
141
|
+
body,
|
|
142
|
+
sourceSha: degradedBatchSha,
|
|
143
|
+
}),
|
|
144
|
+
ticketIds: succeededTicketIds,
|
|
145
|
+
}
|
|
146
|
+
: await (0, rail_pr_delivery_1.deliverRailAsPr)(deps.git, deps.exec, {
|
|
147
|
+
baseRepo: deps.project.path,
|
|
148
|
+
integrationBranch: row.base_branch,
|
|
149
|
+
railKey: row.rail_key,
|
|
150
|
+
batchBranch: batchPreferred ?? undefined,
|
|
151
|
+
batchWorktreeRoot: (0, metadata_1.batchWorktreeRoot)(deps.project.slug),
|
|
152
|
+
branches: effectiveBranches.map((unit) => ({
|
|
153
|
+
...unit,
|
|
154
|
+
sourceSha: unit.finalSha ?? undefined,
|
|
155
|
+
})),
|
|
156
|
+
title,
|
|
157
|
+
body,
|
|
158
|
+
});
|
|
159
|
+
if (result.state === 'delivered') {
|
|
160
|
+
next = result.pr.state === 'pr-created' && result.pr.isDraft === false ? 'pr_ready' : 'pr_draft';
|
|
161
|
+
patch.branch = result.branch;
|
|
162
|
+
patch.prState = result.pr.state;
|
|
163
|
+
const resultSha = degradedBatchSha
|
|
164
|
+
?? (succeededUnits.length === 1 ? succeededUnits[0].finalSha ?? null : await (0, evidence_1.captureBranchSha)(deps, result.branch));
|
|
165
|
+
if (resultSha && await (0, evidence_1.commitObjectExists)(deps, resultSha))
|
|
166
|
+
patch.deliverySha = resultSha;
|
|
167
|
+
if (result.pr.state === 'pr-created' && result.pr.prUrl) {
|
|
168
|
+
patch.prUrl = result.pr.prUrl;
|
|
169
|
+
patch.prNumber = (0, metadata_1.parsePrNumber)(result.pr.prUrl);
|
|
170
|
+
patch.deliveryOutcome = 'delivered';
|
|
171
|
+
patch.statusCode = next === 'pr_ready' ? 'pr_ready' : 'pr_draft_ready';
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// Degraded (pushed / local-only): no PR exists — only retry or discard.
|
|
175
|
+
patch.prUrl = null;
|
|
176
|
+
patch.prNumber = null;
|
|
177
|
+
detail = result.pr.reason ?? null;
|
|
178
|
+
patch.deliveryOutcome = 'retryable_failure';
|
|
179
|
+
patch.statusCode = result.pr.state === 'local-only' ? 'push_failed' : 'delivery_failed';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// 'assembly-failed' (or an unexpected 'no-op' — settle guarantees ≥1
|
|
184
|
+
// succeeded unit, but a wedged row must not 500) → retryable failure.
|
|
185
|
+
next = 'pr_failed';
|
|
186
|
+
detail = result.reason;
|
|
187
|
+
const retryable = !result.reason.startsWith('merge-conflict:') &&
|
|
188
|
+
!result.reason.startsWith('batch-branch-collision:') &&
|
|
189
|
+
result.reason !== 'missing-batch-branch' && result.state === 'assembly-failed';
|
|
190
|
+
patch.deliveryOutcome = retryable ? 'retryable_failure' : 'blocked';
|
|
191
|
+
patch.statusCode = 'delivery_failed';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
// publishDraftPr can propagate GitGuardrailError — a guardrail violation is
|
|
196
|
+
// a retryable delivery failure, never a crash.
|
|
197
|
+
console.error('[rail-pr-decision] create-pr delivery failed:', err);
|
|
198
|
+
next = 'pr_failed';
|
|
199
|
+
detail = err instanceof Error ? err.message : String(err);
|
|
200
|
+
patch.deliveryOutcome = 'blocked';
|
|
201
|
+
patch.statusCode = 'delivery_failed';
|
|
202
|
+
}
|
|
203
|
+
if (detail)
|
|
204
|
+
patch.statusDetail = detail;
|
|
205
|
+
if ((next === 'pr_draft' || next === 'pr_ready') && patch.prUrl) {
|
|
206
|
+
patch.cleanupWarnings = await (0, rail_worktree_release_1.releaseRailWorktrees)({
|
|
207
|
+
db: deps.db, git: deps.git, repoDir: deps.project.path, worktreeIds: (0, ownership_1.releasableWorktreeIds)(deps, snap),
|
|
208
|
+
expectedHeadByBranch: (0, rail_worktree_release_1.durableBranchHeads)(effectiveBranches),
|
|
209
|
+
overlayEvidenceByBranch: (0, rail_worktree_release_1.durableOverlayCleanupEvidence)(effectiveBranches),
|
|
210
|
+
settlementIgnoredByBranch: (0, rail_worktree_release_1.durableSettlementIgnoredPaths)(effectiveBranches),
|
|
211
|
+
onSafetyArchive: (0, transitions_1.safetyArchiveRecorder)(deps, row),
|
|
212
|
+
});
|
|
213
|
+
if (patch.cleanupWarnings.length > 0)
|
|
214
|
+
patch.statusCode = 'cleanup_incomplete';
|
|
215
|
+
}
|
|
216
|
+
const conflict = (0, transitions_1.casTransition)(deps, row, next, patch);
|
|
217
|
+
if (conflict)
|
|
218
|
+
return conflict;
|
|
219
|
+
if ((next === 'pr_draft' || next === 'pr_ready') && patch.prUrl) {
|
|
220
|
+
await (0, evidence_1.releaseDeliveredRecoveryLineage)(deps, row, patch.deliverySha ?? row.delivery_sha);
|
|
221
|
+
}
|
|
222
|
+
const after = (0, transitions_1.finalizeTransition)(deps, row.id);
|
|
223
|
+
// Tickets stay on_review — a draft PR is still awaiting the engineer's merge.
|
|
224
|
+
return {
|
|
225
|
+
status: 200,
|
|
226
|
+
body: {
|
|
227
|
+
ok: true,
|
|
228
|
+
decision: next,
|
|
229
|
+
prUrl: after?.prUrl ?? null,
|
|
230
|
+
prState: after?.prState ?? row.pr_state,
|
|
231
|
+
...(detail ? { detail } : {}),
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runDiscard = runDiscard;
|
|
37
|
+
exports.runDismiss = runDismiss;
|
|
38
|
+
exports.runAcknowledgeNoChanges = runAcknowledgeNoChanges;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const rail_worktree_release_1 = require("../../runtime/rail-worktree-release");
|
|
41
|
+
const rail_pr_store_1 = require("../../runtime/rail-pr-store");
|
|
42
|
+
const rail_worktrees_store_1 = require("../../runtime/rail-worktrees-store");
|
|
43
|
+
const rail_pr_recovery_git_1 = require("../../runtime/rail-pr-recovery-git");
|
|
44
|
+
const transitions_1 = require("./transitions");
|
|
45
|
+
const ownership_1 = require("./ownership");
|
|
46
|
+
const evidence_1 = require("./evidence");
|
|
47
|
+
const chains_1 = require("./chains");
|
|
48
|
+
async function runDiscard(deps, row, opts = { removeNeedsReview: true }) {
|
|
49
|
+
const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
|
|
50
|
+
const implementationFailed = row.decision === 'implementation_failed';
|
|
51
|
+
// PR lifecycle ownership and head-ref ownership are separate. Startup repairs
|
|
52
|
+
// historical continuation rows before admission opens; only that durable bit
|
|
53
|
+
// borrows the PR/ticket lifecycle. Per-unit ownership below independently
|
|
54
|
+
// prevents deletion of borrowed/pre-existing head refs for fresh replacements.
|
|
55
|
+
const preserveExternalReview = row.is_continuation === 1;
|
|
56
|
+
// A preparation failure never ran: no worktree, no branch, no commit, no PR.
|
|
57
|
+
// Discarding it only closes the attempt and frees the rail — the spec keeps
|
|
58
|
+
// the status it had (typically on_review from a still-open earlier PR), the
|
|
59
|
+
// backlog/Jira are not told about a delivery that never existed, and no
|
|
60
|
+
// resource cleanup can be owed. Distinct from implementation_failed, which
|
|
61
|
+
// did run and did move the ticket.
|
|
62
|
+
const preparationFailure = row.decision === 'pr_failed' &&
|
|
63
|
+
row.implementation_outcome === 'failed' &&
|
|
64
|
+
!row.pr_url && !row.delivery_sha && !preserveExternalReview &&
|
|
65
|
+
snap.branches.length === 0 && snap.worktreeIds.length === 0;
|
|
66
|
+
const cleanupWarnings = [];
|
|
67
|
+
// A continuation borrows an existing PR/head. Discarding its local iteration
|
|
68
|
+
// may remove Specrails' worktree, but never closes or deletes borrowed review
|
|
69
|
+
// state. A fresh PR is closed without GitHub's unleased --delete-branch: its
|
|
70
|
+
// remote head may have advanced since the card was rendered.
|
|
71
|
+
if (row.pr_url && !implementationFailed && !preserveExternalReview) {
|
|
72
|
+
try {
|
|
73
|
+
const r = await deps.exec.run('gh', ['pr', 'close', row.pr_url], deps.project.path);
|
|
74
|
+
if (r.code !== 0) {
|
|
75
|
+
const detail = (r.stderr.trim() || r.stdout.trim()).split('\n')[0] || `exit ${r.code}`;
|
|
76
|
+
cleanupWarnings.push(`PR close ${row.pr_url}: ${detail}`);
|
|
77
|
+
console.warn(`[rail-pr-decision] gh pr close failed (continuing discard): ${detail}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
cleanupWarnings.push(`PR close ${row.pr_url}: ${err instanceof Error ? err.message : String(err)}`);
|
|
82
|
+
console.warn('[rail-pr-decision] gh pr close threw (continuing discard):', err);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// 2. Release only worktrees whose live tracked/untracked/ignored state and
|
|
86
|
+
// exact HEAD/ref still match durable settlement evidence. Explicit
|
|
87
|
+
// discard is not permission to contradict the confirmation copy by
|
|
88
|
+
// force-removing subsequently changed local work. Authenticated overlays
|
|
89
|
+
// take the same lossless quarantine path as automatic settlement.
|
|
90
|
+
const deleteOwnedBranches = !implementationFailed && !preserveExternalReview;
|
|
91
|
+
const skippedNeedsReview = opts.removeNeedsReview === true
|
|
92
|
+
? []
|
|
93
|
+
: snap.worktreeIds
|
|
94
|
+
.map((wtId) => (0, rail_worktrees_store_1.getRailWorktree)(deps.db, wtId))
|
|
95
|
+
.filter((wt) => wt?.merge_state === 'needs-review');
|
|
96
|
+
for (const worktree of skippedNeedsReview) {
|
|
97
|
+
cleanupWarnings.push(`worktree ${worktree.worktree_path}: preserved for inspection because it already requires review`);
|
|
98
|
+
}
|
|
99
|
+
const skippedIds = new Set(skippedNeedsReview.map((wt) => wt.id));
|
|
100
|
+
const worktreeIds = snap.worktreeIds.filter((wtId) => !skippedIds.has(wtId));
|
|
101
|
+
cleanupWarnings.push(...await (0, rail_worktree_release_1.releaseRailWorktrees)({
|
|
102
|
+
db: deps.db,
|
|
103
|
+
git: deps.git,
|
|
104
|
+
repoDir: deps.project.path,
|
|
105
|
+
worktreeIds,
|
|
106
|
+
state: 'failed',
|
|
107
|
+
expectedHeadByBranch: (0, rail_worktree_release_1.durableBranchHeads)(snap.branches),
|
|
108
|
+
overlayEvidenceByBranch: (0, rail_worktree_release_1.durableOverlayCleanupEvidence)(snap.branches),
|
|
109
|
+
settlementIgnoredByBranch: (0, rail_worktree_release_1.durableSettlementIgnoredPaths)(snap.branches),
|
|
110
|
+
onSafetyArchive: (0, transitions_1.safetyArchiveRecorder)(deps, row),
|
|
111
|
+
}));
|
|
112
|
+
const retainedWorktreeBranches = new Set(snap.worktreeIds
|
|
113
|
+
.map((wtId) => (0, rail_worktrees_store_1.getRailWorktree)(deps.db, wtId))
|
|
114
|
+
.filter((wt) => Boolean(wt && (wt.merge_state === 'needs-review' || fs.existsSync(wt.worktree_path))))
|
|
115
|
+
.map((wt) => wt.branch));
|
|
116
|
+
// 3. Delete only branches this delivery durably records as created, and only
|
|
117
|
+
// while their live tips still equal the immutable delivered commits.
|
|
118
|
+
// Later user/collaborator commits are retained with a cleanup warning.
|
|
119
|
+
if (deleteOwnedBranches) {
|
|
120
|
+
await (0, ownership_1.deleteOwnedBranchesIfUnchanged)(deps, row, snap, cleanupWarnings, retainedWorktreeBranches);
|
|
121
|
+
}
|
|
122
|
+
// Explicit Discard local result is also the only authority (besides proven
|
|
123
|
+
// delivery) to release a pinned orphan. A crash can occur after the atomic
|
|
124
|
+
// ref creation but before delivery_sha is written, so recover that ownership
|
|
125
|
+
// only from this delivery's exact durable final SHA or run-marker evidence.
|
|
126
|
+
if (opts.removeNeedsReview === true) {
|
|
127
|
+
let recoverySha = row.delivery_sha && evidence_1.COMMIT_SHA_RE.test(row.delivery_sha)
|
|
128
|
+
? row.delivery_sha.toLowerCase()
|
|
129
|
+
: null;
|
|
130
|
+
if (!recoverySha && row.is_continuation === 1 &&
|
|
131
|
+
(row.status_code === 'settlement_interrupted' || row.status_code === 'recovery_unavailable')) {
|
|
132
|
+
const protection = await (0, rail_pr_recovery_git_1.inspectRecoveryCommitProtection)(deps.git, deps.project.path, row.id);
|
|
133
|
+
if (protection.kind === 'present') {
|
|
134
|
+
const durableFinalShas = [...new Set(snap.branches
|
|
135
|
+
.map((unit) => unit.finalSha)
|
|
136
|
+
.filter((sha) => typeof sha === 'string' && evidence_1.COMMIT_SHA_RE.test(sha))
|
|
137
|
+
.map((sha) => sha.toLowerCase()))];
|
|
138
|
+
const runIds = [...new Set(snap.runIds.filter(Boolean))];
|
|
139
|
+
const exactDurableFinal = durableFinalShas.length === 1 && durableFinalShas[0] === protection.sha;
|
|
140
|
+
const exactRunMarker = runIds.length === 1 && await (0, rail_pr_recovery_git_1.commitCarriesRunMarker)(deps.git, deps.project.path, protection.sha, runIds[0]);
|
|
141
|
+
if (exactDurableFinal || exactRunMarker) {
|
|
142
|
+
recoverySha = protection.sha;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
cleanupWarnings.push(`recovery ref ${protection.ref}: preserved because its commit could not be proven to belong to this delivery`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if (protection.kind === 'unreadable') {
|
|
149
|
+
cleanupWarnings.push(`recovery ref ${protection.ref}: preserved because its exact commit could not be read safely`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (recoverySha && !await (0, rail_pr_recovery_git_1.releaseRecoveryCommit)(deps.git, deps.project.path, row.id, recoverySha)) {
|
|
153
|
+
cleanupWarnings.push('the delivery recovery ref changed or could not be removed; it was preserved for inspection');
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const terminalPatch = {
|
|
157
|
+
deliveryOutcome: 'not_started',
|
|
158
|
+
statusCode: cleanupWarnings.length > 0 ? 'cleanup_incomplete' : 'discarded',
|
|
159
|
+
cleanupWarnings,
|
|
160
|
+
};
|
|
161
|
+
const conflict = preserveExternalReview || preparationFailure
|
|
162
|
+
? (0, transitions_1.casTransition)(deps, row, 'discarded', terminalPatch)
|
|
163
|
+
: (0, transitions_1.casTransitionWithTicketEffect)(deps, row, 'discarded', terminalPatch, {
|
|
164
|
+
deliveryId: row.id,
|
|
165
|
+
ticketIds: snap.ticketIds,
|
|
166
|
+
targetStatus: 'todo',
|
|
167
|
+
// The dashboard labels discard-from-no_changes as Refine. Jira must
|
|
168
|
+
// mirror that truthful backlog return and never apply discardStatus.
|
|
169
|
+
jiraAction: row.decision === 'no_changes' ? 'refine' : 'discard',
|
|
170
|
+
prUrl: null,
|
|
171
|
+
});
|
|
172
|
+
if (conflict)
|
|
173
|
+
return conflict;
|
|
174
|
+
(0, chains_1.pauseChainsOnDiscard)(deps, row);
|
|
175
|
+
if (!preserveExternalReview && !preparationFailure)
|
|
176
|
+
(0, transitions_1.applyTerminalTicketEffect)(deps, row, 'discarded', cleanupWarnings);
|
|
177
|
+
(0, transitions_1.finalizeTransition)(deps, row.id);
|
|
178
|
+
return {
|
|
179
|
+
status: 200,
|
|
180
|
+
body: {
|
|
181
|
+
ok: true,
|
|
182
|
+
decision: 'discarded',
|
|
183
|
+
...(cleanupWarnings.length > 0 ? { cleanupWarnings } : {}),
|
|
184
|
+
...(preparationFailure ? { preparationFailure: true } : {}),
|
|
185
|
+
...(preserveExternalReview ? { preservedBorrowedReview: true, preservedExternalReview: true } : {}),
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
async function runDismiss(deps, row) {
|
|
190
|
+
// Legality restricts dismiss to a clean/retryable continuation. Reuse the
|
|
191
|
+
// ownership-safe discard path; its external PR, head and tickets are borrowed.
|
|
192
|
+
return runDiscard(deps, row, { removeNeedsReview: false });
|
|
193
|
+
}
|
|
194
|
+
async function runAcknowledgeNoChanges(deps, row) {
|
|
195
|
+
const snap = (0, rail_pr_store_1.toPrDeliverySnapshot)(row);
|
|
196
|
+
const cleanupWarnings = await (0, rail_worktree_release_1.releaseRailWorktrees)({
|
|
197
|
+
db: deps.db,
|
|
198
|
+
git: deps.git,
|
|
199
|
+
repoDir: deps.project.path,
|
|
200
|
+
worktreeIds: snap.worktreeIds,
|
|
201
|
+
expectedHeadByBranch: (0, rail_worktree_release_1.durableBranchHeads)(snap.branches),
|
|
202
|
+
overlayEvidenceByBranch: (0, rail_worktree_release_1.durableOverlayCleanupEvidence)(snap.branches),
|
|
203
|
+
settlementIgnoredByBranch: (0, rail_worktree_release_1.durableSettlementIgnoredPaths)(snap.branches),
|
|
204
|
+
onSafetyArchive: (0, transitions_1.safetyArchiveRecorder)(deps, row),
|
|
205
|
+
});
|
|
206
|
+
// A fresh no-change branch is disposable only while Git still proves that it
|
|
207
|
+
// has no commits ahead of the integration base. If the user added work after
|
|
208
|
+
// settlement, preserve it and disclose the incomplete cleanup.
|
|
209
|
+
for (const branch of (0, ownership_1.ownedDeliveryBranches)(row, snap, cleanupWarnings)) {
|
|
210
|
+
if (!branch || branch === row.base_branch)
|
|
211
|
+
continue;
|
|
212
|
+
try {
|
|
213
|
+
const ahead = await deps.git.run(['rev-list', '--count', `${row.base_branch}..${branch}`], deps.project.path);
|
|
214
|
+
if (ahead.code !== 0 || Number.parseInt(ahead.stdout.trim(), 10) !== 0) {
|
|
215
|
+
cleanupWarnings.push(`branch ${branch}: retained because no-change cleanup could not prove it has zero commits ahead of ${row.base_branch}`);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
const deleted = await deps.git.run(['branch', '-d', branch], deps.project.path);
|
|
219
|
+
if (deleted.code !== 0) {
|
|
220
|
+
cleanupWarnings.push(`branch ${branch}: ${(deleted.stderr.trim() || deleted.stdout.trim()).split('\n')[0] || `exit ${deleted.code}`}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
cleanupWarnings.push(`branch ${branch}: ${err instanceof Error ? err.message : String(err)}`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const conflict = (0, transitions_1.casTransitionWithTicketEffect)(deps, row, 'completed', {
|
|
228
|
+
deliveryOutcome: 'no_changes',
|
|
229
|
+
statusCode: cleanupWarnings.length > 0 ? 'cleanup_incomplete' : 'no_changes',
|
|
230
|
+
cleanupWarnings,
|
|
231
|
+
}, {
|
|
232
|
+
deliveryId: row.id,
|
|
233
|
+
ticketIds: snap.ticketIds,
|
|
234
|
+
targetStatus: 'done',
|
|
235
|
+
jiraAction: 'completed',
|
|
236
|
+
prUrl: null,
|
|
237
|
+
});
|
|
238
|
+
if (conflict)
|
|
239
|
+
return conflict;
|
|
240
|
+
(0, transitions_1.applyTerminalTicketEffect)(deps, row, 'completed', cleanupWarnings);
|
|
241
|
+
(0, transitions_1.finalizeTransition)(deps, row.id);
|
|
242
|
+
return {
|
|
243
|
+
status: 200,
|
|
244
|
+
body: {
|
|
245
|
+
ok: true,
|
|
246
|
+
decision: 'completed',
|
|
247
|
+
noChanges: true,
|
|
248
|
+
...(cleanupWarnings.length > 0 ? { cleanupWarnings } : {}),
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.executePrDecision = executePrDecision;
|
|
37
|
+
const __1 = require("../..");
|
|
38
|
+
const rail_pr_store_1 = require("../../runtime/rail-pr-store");
|
|
39
|
+
const ids_1 = require("../../../../ids");
|
|
40
|
+
const transitions_1 = require("./transitions");
|
|
41
|
+
const create_1 = require("./create");
|
|
42
|
+
const publish_1 = require("./publish");
|
|
43
|
+
const discard_1 = require("./discard");
|
|
44
|
+
const merge_local_1 = require("./merge-local");
|
|
45
|
+
const recovery_1 = require("./recovery");
|
|
46
|
+
async function executePrDecision(deps, input) {
|
|
47
|
+
const row = (0, rail_pr_store_1.getPrDelivery)(deps.db, input.prDeliveryId);
|
|
48
|
+
if (!row)
|
|
49
|
+
return { status: 404, body: { error: 'Unknown prDeliveryId' } };
|
|
50
|
+
if (row.parent_delivery_id && deps.repositoryChildOf !== row.parent_delivery_id)
|
|
51
|
+
return { status: 409, body: { error: 'repository_delivery_requires_parent', parentDeliveryId: row.parent_delivery_id } };
|
|
52
|
+
// A manifest alone does not make a repository GROUP: a launch that failed
|
|
53
|
+
// before allocating a single repository delivery persists the parent with
|
|
54
|
+
// its manifest and zero children (observed: `git worktree add` refused
|
|
55
|
+
// because the PR branch was checked out in the main clone). Routing that
|
|
56
|
+
// parent into the group path 404'd on "no repositories" — which the UI read
|
|
57
|
+
// as "already resolved" — and left the rail pinned at pending_decision.
|
|
58
|
+
if (!row.parent_delivery_id && row.execution_manifest && (0, rail_pr_store_1.hasRepositoryDeliveries)(deps.db, row.id)) {
|
|
59
|
+
const { executeRepositoryGroupDecision } = await Promise.resolve().then(() => __importStar(require('../../runtime/multi-repo-delivery')));
|
|
60
|
+
return executeRepositoryGroupDecision(deps, input);
|
|
61
|
+
}
|
|
62
|
+
// Compare-and-set pre-check: the caller decided against a snapshot — if the
|
|
63
|
+
// row moved on (the other surface answered first), it must reconcile, not act.
|
|
64
|
+
if (row.decision !== input.expectedDecision)
|
|
65
|
+
return (0, transitions_1.staleDecision)(row.decision);
|
|
66
|
+
if (!(0, __1.actionAllowed)(input.action, row))
|
|
67
|
+
return (0, transitions_1.illegalAction)(row.decision);
|
|
68
|
+
// Claim before any git/GitHub/cleanup/ticket effect. The visible decision is
|
|
69
|
+
// unchanged while the winner works, but a second surface cannot start.
|
|
70
|
+
const operationToken = (0, ids_1.newId)();
|
|
71
|
+
if (!(0, rail_pr_store_1.claimPrDeliveryOperation)(deps.db, row.id, row.decision, input.action, operationToken)) {
|
|
72
|
+
const current = (0, rail_pr_store_1.getPrDelivery)(deps.db, row.id);
|
|
73
|
+
if (!current || current.decision !== input.expectedDecision) {
|
|
74
|
+
return (0, transitions_1.staleDecision)(current?.decision ?? row.decision);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
status: 409,
|
|
78
|
+
body: { error: 'operation_in_progress', current: current.decision, operation: current.operation },
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const claimedRow = (0, rail_pr_store_1.getPrDelivery)(deps.db, row.id);
|
|
82
|
+
if (!claimedRow || claimedRow.operation_token !== operationToken) {
|
|
83
|
+
return { status: 409, body: { error: 'operation_in_progress', current: claimedRow?.decision ?? row.decision } };
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
switch (input.action) {
|
|
87
|
+
case 'create-pr': return await (0, create_1.runCreatePr)(deps, claimedRow);
|
|
88
|
+
case 'publish': return await (0, publish_1.runPublish)(deps, claimedRow);
|
|
89
|
+
case 'discard': return await (0, discard_1.runDiscard)(deps, claimedRow);
|
|
90
|
+
case 'dismiss': return await (0, discard_1.runDismiss)(deps, claimedRow);
|
|
91
|
+
case 'poll-merge': return await (0, publish_1.runPollMerge)(deps, claimedRow);
|
|
92
|
+
case 'reopen': return await (0, publish_1.runReopen)(deps, claimedRow);
|
|
93
|
+
case 'merge-local': return await (0, merge_local_1.runMergeLocal)(deps, claimedRow);
|
|
94
|
+
case 'acknowledge-no-changes': return await (0, discard_1.runAcknowledgeNoChanges)(deps, claimedRow);
|
|
95
|
+
case 'recover-and-retry': return await (0, recovery_1.runRecoverAndRetry)(deps, claimedRow);
|
|
96
|
+
}
|
|
97
|
+
return (0, transitions_1.illegalAction)(row.decision);
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
try {
|
|
101
|
+
(0, rail_pr_store_1.releasePrDeliveryOperation)(deps.db, row.id, operationToken);
|
|
102
|
+
}
|
|
103
|
+
catch { /* durable state remains authoritative */ }
|
|
104
|
+
if (transitions_1.deferredFinalizations.delete(row.id))
|
|
105
|
+
(0, transitions_1.finalizeTransition)(deps, row.id);
|
|
106
|
+
}
|
|
107
|
+
}
|