@straiffi/archon 1.8.20 → 1.8.22
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/dist/client/assets/{ActivityView-DDE3U1zB.js → ActivityView-CdEPjmqD.js} +1 -1
- package/dist/client/assets/GitHubActionsDialog-CA189pr2.js +1 -0
- package/dist/client/assets/VerificationDialog-BPVkhKRj.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-oPUmRpZr.js → architectureDiagram-3BPJPVTR-BrZ08mqq.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-0sq1jkkp.js → blockDiagram-GPEHLZMM-b93XwJ6Z.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BeDxMy7J.js → c4Diagram-AAUBKEIU-BKOdbZ_v.js} +1 -1
- package/dist/client/assets/channel-D0zqzBT_.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-D8VGsje2.js → chunk-2J33WTMH-D7Vxn_1m.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-DuTUTeBe.js → chunk-3OPIFGDE-B1zo2UZq.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-BzX5dPNW.js → chunk-5ZQYHXKU-BajvkDdQ.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-DS9putxN.js → chunk-727SXJPM-CSH7cVpV.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CWzFZRBv.js → chunk-AQP2D5EJ-DE-wgUNP.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-DXZ-ADYW.js → chunk-CSCIHK7Q-Ba7JgCEf.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-BD7mL3KK.js → chunk-KSCS5N6A-0o3YWkHM.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-DmYQi9AP.js → chunk-L5ZTLDWV-DihWczP8.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-CZyFYHvS.js → chunk-LZXEDZCA-Bxnu-hme.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-BxdjvT9I.js → chunk-ND2GUHAM-CoaR5kmP.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-BwuZcZ_9.js → chunk-NZK2D7GU-By92Rd3d.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-CC-TZXr3.js → chunk-O5CBEL6O-D83Pkgfu.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-CJZJkca2.js → chunk-WU5MYG2G-v8OVf5Lz.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-ChhyvHH2.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Cl02kurK.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-D2L5RvPF.js → dagre-BM42HDAG-Dq1ALF7Z.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DBJzxSqZ.js → diagram-2AECGRRQ-1t1_TKtu.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-J_1M-Wou.js → diagram-5GNKFQAL-DtvYRL6f.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-CmT1Vbmc.js → diagram-KO2AKTUF-PRNrSX5F.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DfPoJyQI.js → diagram-LMA3HP47-DaTX0DhT.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-D4uEb6vo.js → diagram-OG6HWLK6-C2p9p-92.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-l7yIFj0e.js → erDiagram-TEJ5UH35-DKzLtnp-.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-B3caTMes.js → flowDiagram-I6XJVG4X-GdL8lm6e.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-9Am36v9m.js → ganttDiagram-6RSMTGT7-Ok-4XYwT.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-B7OjYsv_.js → gitGraphDiagram-PVQCEYII-DSMrOCK7.js} +1 -1
- package/dist/client/assets/index-Bs8KsdV9.js +276 -0
- package/dist/client/assets/index-DdwM8Wgt.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-ZAcNejkW.js → infoDiagram-5YYISTIA-Dl4hRXis.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BaaJwuN0.js → ishikawaDiagram-YF4QCWOH-C1Dc1fTT.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DjzTU3kM.js → journeyDiagram-JHISSGLW-CUscmJze.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-DYRchzub.js → kanban-definition-UN3LZRKU-C0nwYjQV.js} +1 -1
- package/dist/client/assets/{line-X0j9gj61.js → line-ByiuEIg_.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-DCKG87Vl.js → mermaid-parser.core-B-XdAyDR.js} +1 -1
- package/dist/client/assets/{mermaid.core-BxI5T2gs.js → mermaid.core-D_bIfuZD.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BE7MZzQO.js → mindmap-definition-RKZ34NQL-BGNiPJDK.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-D3fTYovg.js → pieDiagram-4H26LBE5-CP6FpAoO.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-B35nXRdQ.js → quadrantDiagram-W4KKPZXB-dsAWBAQn.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-CLBcHvP0.js → requirementDiagram-4Y6WPE33-DJH-zHqF.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DdBCxGHF.js → sankeyDiagram-5OEKKPKP-BJMnZrqH.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-KcLt0X1K.js → sequenceDiagram-3UESZ5HK-CzNjUSlM.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-Bq23ObLK.js → stateDiagram-AJRCARHV-jppMhOwh.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-CLR1WgdV.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-SK3oVUD9.js → timeline-definition-PNZ67QCA-BX2CI5H_.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-COVtAlEC.js → vennDiagram-CIIHVFJN-Bd1KZaXh.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BvfOOwga.js → wardleyDiagram-YWT4CUSO-D-0BNz49.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DFnAD9k4.js → xychartDiagram-2RQKCTM6-DbYa0ZWK.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +780 -16
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +198 -20
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +8 -4
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/agentProvider.js +8 -1
- package/dist/server/lib/agentProvider.js.map +1 -1
- package/dist/server/lib/approvalReconciliation.js +101 -0
- package/dist/server/lib/approvalReconciliation.js.map +1 -0
- package/dist/server/lib/approvalRequests.js +587 -0
- package/dist/server/lib/approvalRequests.js.map +1 -0
- package/dist/server/lib/approvalRoutes.js +143 -0
- package/dist/server/lib/approvalRoutes.js.map +1 -0
- package/dist/server/lib/automationProgression.js +44 -14
- package/dist/server/lib/automationProgression.js.map +1 -1
- package/dist/server/lib/buildCompletionContinuation.js +14 -3
- package/dist/server/lib/buildCompletionContinuation.js.map +1 -1
- package/dist/server/lib/buildExecutionEnvironment.js +350 -66
- package/dist/server/lib/buildExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/buildOpenQuestionOperations.js +47 -3
- package/dist/server/lib/buildOpenQuestionOperations.js.map +1 -1
- package/dist/server/lib/buildSequences.js +267 -18
- package/dist/server/lib/buildSequences.js.map +1 -1
- package/dist/server/lib/buildSetupAuthority.js +138 -0
- package/dist/server/lib/buildSetupAuthority.js.map +1 -0
- package/dist/server/lib/bundleReviewOperations.js +15 -4
- package/dist/server/lib/bundleReviewOperations.js.map +1 -1
- package/dist/server/lib/checkDefinitions.js +29 -1
- package/dist/server/lib/checkDefinitions.js.map +1 -1
- package/dist/server/lib/checkRunner.js +306 -27
- package/dist/server/lib/checkRunner.js.map +1 -1
- package/dist/server/lib/checkRuns.js +4 -2
- package/dist/server/lib/checkRuns.js.map +1 -1
- package/dist/server/lib/consequentialActionAuthority.js +142 -0
- package/dist/server/lib/consequentialActionAuthority.js.map +1 -0
- package/dist/server/lib/consequentialActions.js +231 -0
- package/dist/server/lib/consequentialActions.js.map +1 -0
- package/dist/server/lib/dockerSandboxCredentials.js +64 -10
- package/dist/server/lib/dockerSandboxCredentials.js.map +1 -1
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js +119 -0
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js +174 -11
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionProvider.js +12 -3
- package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -1
- package/dist/server/lib/dockerSandboxNetworkPolicy.js +222 -0
- package/dist/server/lib/dockerSandboxNetworkPolicy.js.map +1 -0
- package/dist/server/lib/executionCredentialCapabilities.js +106 -0
- package/dist/server/lib/executionCredentialCapabilities.js.map +1 -0
- package/dist/server/lib/executionEnvironment.js.map +1 -1
- package/dist/server/lib/executionEnvironmentContexts.js +59 -3
- package/dist/server/lib/executionEnvironmentContexts.js.map +1 -1
- package/dist/server/lib/executionEnvironmentLifecycle.js +34 -0
- package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -1
- package/dist/server/lib/executionEnvironmentRoutes.js +127 -9
- package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidation.js +169 -45
- package/dist/server/lib/executionEnvironmentValidation.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidationOperations.js +203 -19
- package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -1
- package/dist/server/lib/executionEnvironments.js +103 -14
- package/dist/server/lib/executionEnvironments.js.map +1 -1
- package/dist/server/lib/executionProfileRoutes.js +67 -0
- package/dist/server/lib/executionProfileRoutes.js.map +1 -0
- package/dist/server/lib/executionProfileStore.js +117 -0
- package/dist/server/lib/executionProfileStore.js.map +1 -0
- package/dist/server/lib/executionProfiles.js +324 -0
- package/dist/server/lib/executionProfiles.js.map +1 -0
- package/dist/server/lib/executionReconciliation.js +345 -197
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRetry.js +24 -5
- package/dist/server/lib/executionRetry.js.map +1 -1
- package/dist/server/lib/executionRunAuthority.js +467 -0
- package/dist/server/lib/executionRunAuthority.js.map +1 -0
- package/dist/server/lib/executionRuns.js +30 -4
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/executionTimeline.js +2 -1
- package/dist/server/lib/executionTimeline.js.map +1 -1
- package/dist/server/lib/git.js +77 -10
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/gitPushApprovals.js +367 -0
- package/dist/server/lib/gitPushApprovals.js.map +1 -0
- package/dist/server/lib/hostExecutionEnvironment.js +7 -1
- package/dist/server/lib/hostExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/mobileAccess.js +115 -1
- package/dist/server/lib/mobileAccess.js.map +1 -1
- package/dist/server/lib/productionCheckApprovals.js +106 -0
- package/dist/server/lib/productionCheckApprovals.js.map +1 -0
- package/dist/server/lib/projects.js +1 -0
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/run.js +58 -2
- package/dist/server/lib/run.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +32 -6
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/transcriptRuns.js +3 -0
- package/dist/server/lib/transcriptRuns.js.map +1 -1
- package/dist/server/lib/types.js +40 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/lib/workspaceProcessEnvironment.js +72 -1
- package/dist/server/lib/workspaceProcessEnvironment.js.map +1 -1
- package/dist/server/workers/build.js +214 -46
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/followUp.js +74 -1
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/review.js +30 -13
- package/dist/server/workers/review.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/GitHubActionsDialog-CM1z-amZ.js +0 -1
- package/dist/client/assets/VerificationDialog-oHjNllh6.js +0 -4
- package/dist/client/assets/channel-CF8hkOdu.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-D6FiG9_B.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Bim05ijr.js +0 -1
- package/dist/client/assets/index-CsZfTdMO.css +0 -2
- package/dist/client/assets/index-DDefs3iM.js +0 -275
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BLzZdVo0.js +0 -1
package/dist/server/index.js
CHANGED
|
@@ -11,6 +11,10 @@ import db from './db.js';
|
|
|
11
11
|
import { pruneAllRepositoryGraphScans } from './lib/repositoryGraphRetention.js';
|
|
12
12
|
import { registerRepositoryGraphRoutes } from './lib/repositoryGraphRoutes.js';
|
|
13
13
|
import { registerExecutionEnvironmentRoutes } from './lib/executionEnvironmentRoutes.js';
|
|
14
|
+
import { registerExecutionProfileRoutes } from './lib/executionProfileRoutes.js';
|
|
15
|
+
import { registerApprovalRoutes } from './lib/approvalRoutes.js';
|
|
16
|
+
import { admitForcePush, finalizeGitPushApproval, resumeGitPushApproval } from './lib/gitPushApprovals.js';
|
|
17
|
+
import { reconcileApprovalRequests } from './lib/approvalReconciliation.js';
|
|
14
18
|
import { dockerSandboxAdapter, dockerSandboxRunner, dockerSandboxRuntimeController, } from './lib/dockerSandboxEnvironmentOperations.js';
|
|
15
19
|
import { deleteChatSession, getChatSession, listChatSessions } from './lib/chats.js';
|
|
16
20
|
import { deleteSpecSession, getCreatedTicketIdsForSnapshot, getSpecSession, getSpecSnapshot, listSpecSessions } from './lib/specs.js';
|
|
@@ -26,7 +30,7 @@ import { resolveSessionTargetForExecution } from './lib/sessionTargets.js';
|
|
|
26
30
|
import { createChatMessage, getChatMessage, updateChatMessageContent } from './lib/chatMessages.js';
|
|
27
31
|
import { attachChatTicketProposalsToMessageContent } from './lib/chatTicketProposals.js';
|
|
28
32
|
import { createCorsOriginResolver, parseCorsOrigins } from './lib/cors.js';
|
|
29
|
-
import { abortGitOperation, branchExistsLocally, commitGitChanges, createWorktreeAsync, deleteWorktree, getBundleReviewDiffForCwd, getGitDiffDataAsync, getGitDiffFiles, getGitStatus, getGitStatusAsync, getGitUnifiedDiff, getGitUnifiedDiffAsync, getLocalProjectBranch, getProjectBranch, getProjectBranchSuggestions, getSelectedGitUnifiedDiff, getUnpushedCommitDiffForCwd, getUnpushedCommitSummaryForCwd, getUnpushedCommitSummaryForCwdAsync, hasKnownBranchRef, listUnpushedCommitsForCwd, pullGitBranch, pushCurrentBranch, rebaseGitBranchOntoBase, resolveExistingWorktreePath, resolveWorktreePath, squashUnpushedCommitsForCwd, summarizeTicketDiffFiles, switchProjectBranch, syncWorktreeFilesAsync, undoLatestUnpushedCommitForCwd, UnpushedCommitDiffSelectionError } from './lib/git.js';
|
|
33
|
+
import { abortGitOperation, branchExistsLocally, commitGitChanges, createWorktreeAsync, deleteLocalBranch, deleteWorktree, getBundleReviewDiffForCwd, getGitDiffDataAsync, getGitDiffFiles, getGitStatus, getGitStatusAsync, getGitUnifiedDiff, getGitUnifiedDiffAsync, getLocalProjectBranch, getProjectBranch, getProjectBranchSuggestions, getSelectedGitUnifiedDiff, getUnpushedCommitDiffForCwd, getUnpushedCommitSummaryForCwd, getUnpushedCommitSummaryForCwdAsync, hasKnownBranchRef, listUnpushedCommitsForCwd, pullGitBranch, pushCurrentBranch, rebaseGitBranchOntoBase, resolveExistingWorktreePath, resolveWorktreePath, squashUnpushedCommitsForCwd, summarizeTicketDiffFiles, switchProjectBranch, syncWorktreeFilesAsync, undoLatestUnpushedCommitForCwd, UnpushedCommitDiffSelectionError } from './lib/git.js';
|
|
30
34
|
import config from './lib/config.js';
|
|
31
35
|
import { autoConfigProject, ProjectAutoConfigError } from './lib/projectAutoConfig.js';
|
|
32
36
|
import { analyzeRepoPath, createInitialCommit, ensureInitialCommitForWorktrees, initializeGitRepo, isInitialCommitRequiredError, } from './lib/projectRepos.js';
|
|
@@ -37,7 +41,8 @@ import { validateDesktopMobileAccessRequest } from './lib/mobileAccessSecurity.j
|
|
|
37
41
|
import { refreshChatSessionUsageSnapshot, refreshSpecSessionUsageSnapshot, stopAllBuildAgents, stopAllReviewAgents, stopBuildAgent, stopReviewAgent } from './lib/agent.js';
|
|
38
42
|
import { runLightweightPrompt } from './lib/lightweightPrompt.js';
|
|
39
43
|
import { advanceBuildChain, startBuildChain, stopBuildChain } from './lib/buildChains.js';
|
|
40
|
-
import { activateQueuedBuildSequenceTicket, compensateBuildSequenceAcceptance, enqueueBundledBuild, getDependencyOrderedBundleTicketIds, getBuildSequenceIdForTicket, hasActiveSequenceForBundle, removeTicketFromBuildSequence, stopBuildSequence, } from './lib/buildSequences.js';
|
|
44
|
+
import { activateQueuedBuildSequenceTicket, bindBuildSequenceTicketExecutionRun, compensateBuildSequenceAcceptance, enqueueBundledBuild, getDependencyOrderedBundleTicketIds, getBuildSequenceIdForTicket, getBuildSequenceTicketExecutionProfileSelection, hasActiveSequenceForBundle, releaseQueuedBuildSequenceTicketExecutionRunForRetry, removeTicketFromBuildSequence, stopBuildSequence, } from './lib/buildSequences.js';
|
|
45
|
+
import { createExecutionProfileSelection, executionProfileSelectionMetadata, validateExecutionProfileSelection } from './lib/executionRunAuthority.js';
|
|
41
46
|
import { prepareTicketForBuild } from './lib/buildFlow.js';
|
|
42
47
|
import { getActiveBundleRepairBlocker, getBundlePlanMutationBlockerById, shouldBlockPlanForBundleMutationById, } from './lib/bundleActivity.js';
|
|
43
48
|
import { getDiscoveredModels, normalizeModelId, normalizeTicketModelId } from './lib/models.js';
|
|
@@ -92,15 +97,16 @@ import { refreshIfNeeded as refreshAssignedIssues, clearCachedAssignedIssues } f
|
|
|
92
97
|
import { buildCommitMessagePrompt, normalizeGeneratedCommitMessage } from './lib/commitMessage.js';
|
|
93
98
|
import { BUNDLE_PULL_REQUEST_SYNC_TTL_MS, getBundlePullRequestRecord, hasOpenBundlePullRequest, serializeBundlePullRequest, shouldSyncBundlePullRequest, syncTrackedBundlePullRequestIfNeeded, upsertBundlePullRequest, upsertBundlePullRequestFromGitHub, } from './lib/bundlePullRequests.js';
|
|
94
99
|
import { countInboundProjectLinks, getEffectiveProject, getProjectCheckDefinitions, getProjectById, getProjectTestCommands, getProjectTicketStats, hasProjectRunIde, listInterruptedProjectDeletions, listProjects, releaseInterruptedProjectDeletionClaims, replaceProjectLinks, serializeProject, updateProjectActiveTarget, validateProjectRequiredCheckPolicyReferences, validateProjectPayload, } from './lib/projects.js';
|
|
95
|
-
import { getActiveRunStatus, getActiveRunStatusForProject, getPreviewStatusForProject, hasRunConfig, isRunning, openIde, openTicketIdeInWorkspace, resolveProjectRunContextKey,
|
|
100
|
+
import { getActiveRunStatus, getActiveRunStatusForProject, getPreviewStatusForProject, hasRunConfig, isRunning, openIde, openTicketIdeInWorkspace, resolveProjectRunContextKey, runTicketInWorkspace, stopAllTickets, stopTicket } from './lib/run.js';
|
|
96
101
|
import { clearAllTestSessions, createTestSession, deleteTestSession, discoverTestsForSession, doesTestFileExistForSession, getTestSession, isTestSelectionSupported, startTestSessionRun, stopTestSessionRun } from './lib/testSessions.js';
|
|
97
|
-
import { closeCheckRunnerAdmissions, getCheckBatchAttempts, openCheckRunnerAdmissions, rerunCheckBatchAndSchedule, shutdownCheckRunner, startCheckBatch, stopCheckBatch } from './lib/checkRunner.js';
|
|
102
|
+
import { closeCheckRunnerAdmissions, finalizeProductionCheckApproval, getCheckBatchAttempts, openCheckRunnerAdmissions, rerunCheckBatchAndSchedule, resumeProductionCheckApproval, shutdownCheckRunner, startCheckBatch, stopCheckBatch } from './lib/checkRunner.js';
|
|
98
103
|
import { CheckRepairError, getCheckRepairCandidateState, getCheckRepairDetails, getLatestCheckRepairForBatch, retryCheckRepair, startCheckRepair, stopCheckRepair } from './lib/checkRepair.js';
|
|
99
104
|
import { getCheckAutoFixDetails, stopCheckAutoFix } from './lib/checkAutoFix.js';
|
|
100
105
|
import { findActiveCheckAutoFixForTarget, findActiveCheckBatchForTarget, getCheckAttemptDetails, getCheckBatchDetails, getLatestCheckBatchRunIdForTarget, hasActiveProjectCheckBatch, isCheckAttemptCurrent, resolveCheckBatchRerunEligibility } from './lib/checkRuns.js';
|
|
101
106
|
import { getCheckAttemptDiagnosticResponse, getCheckBatchDiagnosticResponse } from './lib/checkDiagnostics.js';
|
|
102
107
|
import { getCheckDefinitionFingerprint } from './lib/checkDefinitions.js';
|
|
103
108
|
import { getCheckGateEvaluation, hydrateCheckGatePresentApplicability } from './lib/checkGateEvaluations.js';
|
|
109
|
+
import { getBuildSetupEvidenceForRun } from './lib/buildSetupAuthority.js';
|
|
104
110
|
import { captureCheckWorkspaceIdentity } from './lib/checkWorkspaceIdentity.js';
|
|
105
111
|
import { hasActiveBundleRepositoryGraphScan, hasActiveProjectRepositoryGraphScan } from './lib/repositoryGraphStore.js';
|
|
106
112
|
import { resolveEffectiveRequiredCheckPolicyMembership, resolveRequiredCheckPolicy } from './lib/requiredCheckPolicy.js';
|
|
@@ -231,6 +237,7 @@ const parseMultiValueQuery = (value, allowedValues, fieldName) => {
|
|
|
231
237
|
};
|
|
232
238
|
};
|
|
233
239
|
const EXECUTION_RUN_STATUSES = ['queued', 'running', 'waiting', 'completed', 'failed', 'cancelled', 'interrupted'];
|
|
240
|
+
const EXECUTION_RUN_DOMAIN_STATUS_FILTERS = ['approval_required'];
|
|
234
241
|
const parseLifecycleListQuery = (query) => {
|
|
235
242
|
const kind = parseMultiValueQuery(query.kind, EXECUTION_RUN_KINDS, 'kind');
|
|
236
243
|
if ('error' in kind) {
|
|
@@ -243,6 +250,13 @@ const parseLifecycleListQuery = (query) => {
|
|
|
243
250
|
if ('error' in status) {
|
|
244
251
|
return status;
|
|
245
252
|
}
|
|
253
|
+
const domainStatus = parseMultiValueQuery(query.domain_status, EXECUTION_RUN_DOMAIN_STATUS_FILTERS, 'domain_status');
|
|
254
|
+
if ('error' in domainStatus) {
|
|
255
|
+
return domainStatus;
|
|
256
|
+
}
|
|
257
|
+
if (domainStatus.values.length > 1) {
|
|
258
|
+
return { error: 'domain_status must include at most one value' };
|
|
259
|
+
}
|
|
246
260
|
if (query.cursor != null && typeof query.cursor !== 'string') {
|
|
247
261
|
return { error: 'cursor must be a string' };
|
|
248
262
|
}
|
|
@@ -253,6 +267,7 @@ const parseLifecycleListQuery = (query) => {
|
|
|
253
267
|
return {
|
|
254
268
|
kind: kind.values[0],
|
|
255
269
|
statuses: status.values,
|
|
270
|
+
domainStatus: domainStatus.values[0],
|
|
256
271
|
cursor: typeof query.cursor === 'string' && query.cursor !== '' ? query.cursor : null,
|
|
257
272
|
limit,
|
|
258
273
|
};
|
|
@@ -446,9 +461,16 @@ const buildExecutionRunDetailResponse = async (project, run) => {
|
|
|
446
461
|
}
|
|
447
462
|
: run.kind === 'github_actions'
|
|
448
463
|
? { ...serializeGitHubActionsExecutionDetail(getGitHubActionsExecutionDetails(project.id, run.id)), retry_eligibility: retryEligibility }
|
|
449
|
-
:
|
|
450
|
-
? {
|
|
451
|
-
|
|
464
|
+
: run.kind === 'build'
|
|
465
|
+
? {
|
|
466
|
+
kind: 'build',
|
|
467
|
+
available: true,
|
|
468
|
+
setup_authority: getBuildSetupEvidenceForRun(project.id, run.id),
|
|
469
|
+
retry_eligibility: retryEligibility,
|
|
470
|
+
}
|
|
471
|
+
: ['automation_commit', 'automation_push', 'automation_pull_request'].includes(run.kind)
|
|
472
|
+
? { kind: run.kind, available: true, automation_stage: getAutomationStageDetails(project.id, run.id), retry_eligibility: retryEligibility }
|
|
473
|
+
: { kind: run.kind, available: true, retry_eligibility: retryEligibility };
|
|
452
474
|
const artifacts = loadExecutionArtifactSummariesForRuns(project.id, [run.id], MAX_ARTIFACTS_PER_RUN).get(run.id)
|
|
453
475
|
?? { artifacts: [], artifact_count: 0 };
|
|
454
476
|
return {
|
|
@@ -467,17 +489,16 @@ const formatWorktreeDeleteError = (target, branch, error) => {
|
|
|
467
489
|
const prepareBundleWorkspace = async (bundle, project, options = {}) => {
|
|
468
490
|
const branch = bundle.branch;
|
|
469
491
|
const workspacePath = resolveWorktreePath(branch, project);
|
|
470
|
-
let
|
|
492
|
+
let workspacePrepared = false;
|
|
471
493
|
try {
|
|
472
494
|
ensureInitialCommitForWorktrees(project.repo_path);
|
|
473
495
|
await createWorktreeAsync(branch, project, { baseBranch: options.baseBranch ?? null });
|
|
474
496
|
await syncWorktreeFilesAsync(branch, project);
|
|
475
|
-
|
|
476
|
-
setupCompleted = true;
|
|
497
|
+
workspacePrepared = true;
|
|
477
498
|
return workspacePath;
|
|
478
499
|
}
|
|
479
500
|
finally {
|
|
480
|
-
if (!
|
|
501
|
+
if (!workspacePrepared) {
|
|
481
502
|
deleteWorktree(branch, project);
|
|
482
503
|
}
|
|
483
504
|
}
|
|
@@ -512,6 +533,18 @@ const getBundlePlanBlockerError = () => {
|
|
|
512
533
|
const hasActiveBundleCheckWork = (projectId, bundleId) => Boolean(getActiveBundleRepairBlocker(bundleId)
|
|
513
534
|
|| findActiveCheckBatchForTarget(projectId, 'bundle', bundleId)
|
|
514
535
|
|| findActiveCheckAutoFixForTarget(projectId, 'bundle', bundleId));
|
|
536
|
+
const buildBranchCleanupWarning = (branch, result) => {
|
|
537
|
+
if (result === 'unmerged') {
|
|
538
|
+
return `Git branch "${branch}" was kept because it contains commits that are not merged into its base branch.`;
|
|
539
|
+
}
|
|
540
|
+
if (result === 'checked-out') {
|
|
541
|
+
return `Git branch "${branch}" was kept because it is still checked out in another worktree.`;
|
|
542
|
+
}
|
|
543
|
+
if (result === 'failed') {
|
|
544
|
+
return `Git branch "${branch}" could not be deleted automatically.`;
|
|
545
|
+
}
|
|
546
|
+
return null;
|
|
547
|
+
};
|
|
515
548
|
const cleanupWorktreeExecutionTarget = async ({ project, targetKind, targetKey, targetLabel, worktreeTarget, branch, }) => {
|
|
516
549
|
try {
|
|
517
550
|
await cleanupExecutionEnvironmentsForTarget({
|
|
@@ -530,6 +563,7 @@ const cleanupWorktreeExecutionTarget = async ({ project, targetKind, targetKey,
|
|
|
530
563
|
catch (error) {
|
|
531
564
|
throw new HttpError(500, formatWorktreeDeleteError(worktreeTarget, branch, error));
|
|
532
565
|
}
|
|
566
|
+
return { branchWarning: buildBranchCleanupWarning(branch, deleteLocalBranch(branch, project)) };
|
|
533
567
|
};
|
|
534
568
|
const deleteTicketRecord = async (ticket) => {
|
|
535
569
|
if (ticket.project_id
|
|
@@ -1471,6 +1505,14 @@ const resolveBundleLatestBuiltTicket = (tickets) => {
|
|
|
1471
1505
|
return right.id.localeCompare(left.id);
|
|
1472
1506
|
})[0] ?? null;
|
|
1473
1507
|
};
|
|
1508
|
+
const resolveBundleNewestEligibleTicket = (tickets) => {
|
|
1509
|
+
const eligibleTickets = tickets.filter(ticket => ticket.state !== 'plan' && ticket.parked_at === null);
|
|
1510
|
+
const latestBuiltTicket = resolveBundleLatestBuiltTicket(eligibleTickets);
|
|
1511
|
+
if (latestBuiltTicket) {
|
|
1512
|
+
return latestBuiltTicket;
|
|
1513
|
+
}
|
|
1514
|
+
return sortBundleTicketsByExecutionOrder(eligibleTickets).at(-1) ?? null;
|
|
1515
|
+
};
|
|
1474
1516
|
const resolveBundleTargetTicket = (tickets, options = {}) => {
|
|
1475
1517
|
const explicitTargetTicket = options.targetTicketId
|
|
1476
1518
|
? tickets.find(ticket => ticket.id === options.targetTicketId) ?? null
|
|
@@ -1479,6 +1521,7 @@ const resolveBundleTargetTicket = (tickets, options = {}) => {
|
|
|
1479
1521
|
? tickets.find(ticket => ticket.id === options.reviewOwnerTicketId) ?? null
|
|
1480
1522
|
: null;
|
|
1481
1523
|
const runningTicket = tickets.find(ticket => ticket.agent_status === 'running') ?? null;
|
|
1524
|
+
const newestEligibleTicket = resolveBundleNewestEligibleTicket(tickets);
|
|
1482
1525
|
const latestBuiltTicket = resolveBundleLatestBuiltTicket(tickets);
|
|
1483
1526
|
const latestSessionTicket = options.latestSessionTicketId
|
|
1484
1527
|
? tickets.find(ticket => ticket.id === options.latestSessionTicketId && ticket.session_id) ?? null
|
|
@@ -1488,6 +1531,7 @@ const resolveBundleTargetTicket = (tickets, options = {}) => {
|
|
|
1488
1531
|
: null;
|
|
1489
1532
|
return explicitTargetTicket
|
|
1490
1533
|
?? reviewOwnerTicket
|
|
1534
|
+
?? newestEligibleTicket
|
|
1491
1535
|
?? runningTicket
|
|
1492
1536
|
?? latestBuiltTicket
|
|
1493
1537
|
?? latestSessionTicket
|
|
@@ -2556,6 +2600,8 @@ registerExecutionEnvironmentRoutes(app, {
|
|
|
2556
2600
|
adapter: dockerSandboxAdapter,
|
|
2557
2601
|
runtimeController: dockerSandboxRuntimeController,
|
|
2558
2602
|
});
|
|
2603
|
+
registerExecutionProfileRoutes(app);
|
|
2604
|
+
registerApprovalRoutes(app, { emitter: io });
|
|
2559
2605
|
const requireDesktopMobileAccessRequest = (req, res) => {
|
|
2560
2606
|
const rejectionReason = validateDesktopMobileAccessRequest(req);
|
|
2561
2607
|
if (!rejectionReason) {
|
|
@@ -3957,8 +4003,9 @@ app.delete('/bundles/:id', async (req, res) => {
|
|
|
3957
4003
|
const affectedSpecSessionIds = listSpecSessions(result.project.id)
|
|
3958
4004
|
.filter(specSession => specSession.target_bundle_id === bundle.id)
|
|
3959
4005
|
.map(specSession => specSession.id);
|
|
4006
|
+
let cleanupResult;
|
|
3960
4007
|
try {
|
|
3961
|
-
await cleanupWorktreeExecutionTarget({
|
|
4008
|
+
cleanupResult = await cleanupWorktreeExecutionTarget({
|
|
3962
4009
|
project: result.project,
|
|
3963
4010
|
targetKind: 'bundle-worktree',
|
|
3964
4011
|
targetKey: createExecutionTargetKey(result.project.id, {
|
|
@@ -3989,6 +4036,9 @@ app.delete('/bundles/:id', async (req, res) => {
|
|
|
3989
4036
|
io.emit('spec-session:updated', updatedSpecSession);
|
|
3990
4037
|
}
|
|
3991
4038
|
});
|
|
4039
|
+
if (cleanupResult.branchWarning) {
|
|
4040
|
+
return res.status(200).json({ warning: cleanupResult.branchWarning });
|
|
4041
|
+
}
|
|
3992
4042
|
res.status(204).end();
|
|
3993
4043
|
});
|
|
3994
4044
|
app.patch('/bundles/:id', (req, res) => {
|
|
@@ -7279,8 +7329,28 @@ app.post('/projects/:id/git-push', async (req, res) => {
|
|
|
7279
7329
|
return res.status(workspace.status).json({ error: workspace.error });
|
|
7280
7330
|
}
|
|
7281
7331
|
const forceWithLease = req.body?.force_with_lease === true;
|
|
7332
|
+
if (forceWithLease) {
|
|
7333
|
+
try {
|
|
7334
|
+
const admission = await admitForcePush({
|
|
7335
|
+
project: workspace.project,
|
|
7336
|
+
cwd: workspace.cwd,
|
|
7337
|
+
branch: workspace.branch,
|
|
7338
|
+
source: {
|
|
7339
|
+
kind: 'project',
|
|
7340
|
+
id: project.id,
|
|
7341
|
+
targetKind: workspace.target_kind,
|
|
7342
|
+
bundleId: workspace.target_bundle_id,
|
|
7343
|
+
},
|
|
7344
|
+
emitter: io,
|
|
7345
|
+
});
|
|
7346
|
+
return res.status(202).json(admission);
|
|
7347
|
+
}
|
|
7348
|
+
catch (error) {
|
|
7349
|
+
return res.status(409).json({ error: getErrorMessage(error) || 'Unable to request force-push approval right now.' });
|
|
7350
|
+
}
|
|
7351
|
+
}
|
|
7282
7352
|
try {
|
|
7283
|
-
await pushCurrentBranch(workspace.cwd, workspace.branch, { forceWithLease });
|
|
7353
|
+
await pushCurrentBranch(workspace.cwd, workspace.branch, { forceWithLease: false });
|
|
7284
7354
|
}
|
|
7285
7355
|
catch (error) {
|
|
7286
7356
|
return res.status(409).json({ error: getErrorMessage(error) || 'Unable to push the branch right now.' });
|
|
@@ -7345,6 +7415,12 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
7345
7415
|
if (!project) {
|
|
7346
7416
|
return res.status(404).json({ error: 'Not found' });
|
|
7347
7417
|
}
|
|
7418
|
+
if (Object.hasOwn(req.body ?? {}, 'build_execution_provider')) {
|
|
7419
|
+
return res.status(409).json({
|
|
7420
|
+
error: 'Build execution provider changes must use the execution profile endpoint',
|
|
7421
|
+
reason: 'execution_profile_required',
|
|
7422
|
+
});
|
|
7423
|
+
}
|
|
7348
7424
|
const validation = validateProjectPayload(asProjectPayload(req.body), { partial: true, currentProjectId: project.id });
|
|
7349
7425
|
if ('error' in validation) {
|
|
7350
7426
|
return res.status(400).json({ error: validation.error });
|
|
@@ -7357,7 +7433,7 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
7357
7433
|
});
|
|
7358
7434
|
}
|
|
7359
7435
|
}
|
|
7360
|
-
const { name, repo_path,
|
|
7436
|
+
const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, post_build_check_definition_ids, auto_fix_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, reviewer_model, reviewer_variant, commit_message_rules, commit_after_each_ticket, auto_park_stale_tickets, memory_enabled, scan_include_globs_json, scan_exclude_globs_json, worktree_sync, spec_aware_code_review_enabled, automation_depth, automation_review_fix_enabled, automation_pause_on_open_questions, automation_review_severity, automation_review_max_iterations, } = validation.values;
|
|
7361
7437
|
const updateProject = db.prepare(`
|
|
7362
7438
|
UPDATE projects SET
|
|
7363
7439
|
name = ?,
|
|
@@ -7424,7 +7500,7 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
7424
7500
|
if ('error' in policyReferences) {
|
|
7425
7501
|
return policyReferences;
|
|
7426
7502
|
}
|
|
7427
|
-
updateProject.run(name ?? project.name, repo_path ?? project.repo_path,
|
|
7503
|
+
updateProject.run(name ?? project.name, repo_path ?? project.repo_path, project.build_execution_provider, hasOwn(validation.values, 'run_setup') ? run_setup : project.run_setup, hasOwn(validation.values, 'run_services') ? run_services : project.run_services, nextCheckDefinitions, nextRequiredCheckDefinitionIds, nextPreReviewCheckDefinitionIds, nextPostBuildCheckDefinitionIds, nextAutoFixCheckDefinitionIds, hasOwn(validation.values, 'test_commands') ? test_commands : project.test_commands, hasOwn(validation.values, 'run_ide') ? run_ide : project.run_ide, hasOwn(validation.values, 'preview_service_name') ? preview_service_name : project.preview_service_name, hasOwn(validation.values, 'preview_path') ? preview_path : project.preview_path, hasOwn(validation.values, 'preview_capability_mode') ? preview_capability_mode : project.preview_capability_mode, hasOwn(validation.values, 'helper_model') ? helper_model : project.helper_model, hasOwn(validation.values, 'helper_variant') ? helper_variant : project.helper_variant, nextReviewerModel, nextReviewerVariant, hasOwn(validation.values, 'commit_message_rules') ? commit_message_rules : project.commit_message_rules, hasOwn(validation.values, 'commit_after_each_ticket') ? commit_after_each_ticket : project.commit_after_each_ticket, hasOwn(validation.values, 'auto_park_stale_tickets') ? auto_park_stale_tickets : project.auto_park_stale_tickets, hasOwn(validation.values, 'memory_enabled') ? memory_enabled : project.memory_enabled, hasOwn(validation.values, 'scan_include_globs_json') ? scan_include_globs_json : project.scan_include_globs_json, hasOwn(validation.values, 'scan_exclude_globs_json') ? scan_exclude_globs_json : project.scan_exclude_globs_json, hasOwn(validation.values, 'worktree_sync') ? worktree_sync : project.worktree_sync, hasOwn(validation.values, 'spec_aware_code_review_enabled') ? spec_aware_code_review_enabled : project.spec_aware_code_review_enabled, hasOwn(validation.values, 'automation_depth') ? automation_depth : project.automation_depth, hasOwn(validation.values, 'automation_review_fix_enabled') ? automation_review_fix_enabled : project.automation_review_fix_enabled, hasOwn(validation.values, 'automation_pause_on_open_questions') ? automation_pause_on_open_questions : project.automation_pause_on_open_questions, hasOwn(validation.values, 'automation_review_severity') ? automation_review_severity : project.automation_review_severity, hasOwn(validation.values, 'automation_review_max_iterations') ? automation_review_max_iterations : project.automation_review_max_iterations, req.params.id);
|
|
7428
7504
|
if (hasOwn(validation.values, 'linked_project_ids')) {
|
|
7429
7505
|
replaceProjectLinks(project.id, linked_project_ids ?? []);
|
|
7430
7506
|
}
|
|
@@ -7471,6 +7547,17 @@ const assertProjectDeletionEligible = (projectId, claimId) => {
|
|
|
7471
7547
|
if (!claimId && hasActiveProjectRepositoryGraphScan(projectId)) {
|
|
7472
7548
|
throw new ProjectDeletionError(409, 'Cannot delete a project while a repository graph scan is active');
|
|
7473
7549
|
}
|
|
7550
|
+
if (db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'approval_requests'").get() && db.prepare(`
|
|
7551
|
+
SELECT 1 FROM approval_requests request
|
|
7552
|
+
JOIN execution_runs run
|
|
7553
|
+
ON run.id = request.execution_run_id AND run.project_id = request.project_id
|
|
7554
|
+
WHERE request.project_id = ?
|
|
7555
|
+
AND request.status IN ('pending', 'approved', 'consumed')
|
|
7556
|
+
AND run.status IN ('queued', 'running', 'waiting')
|
|
7557
|
+
LIMIT 1
|
|
7558
|
+
`).get(projectId)) {
|
|
7559
|
+
throw new ProjectDeletionError(409, 'Cannot delete a project while consequential action approval is active');
|
|
7560
|
+
}
|
|
7474
7561
|
};
|
|
7475
7562
|
const completeClaimedProjectDeletion = async (projectId, claimId) => {
|
|
7476
7563
|
const marked = db.prepare(`
|
|
@@ -8025,7 +8112,7 @@ app.post('/tickets/:id/retry', (req, res) => {
|
|
|
8025
8112
|
LIMIT 1
|
|
8026
8113
|
`).get(ticket.project_id, ticket.id)
|
|
8027
8114
|
: undefined;
|
|
8028
|
-
const acceptRetry = () => {
|
|
8115
|
+
const acceptRetry = (selection) => {
|
|
8029
8116
|
db.prepare('UPDATE tickets SET agent_status = NULL, agent_log = NULL, agent_message_id = NULL, previous_agent_log = NULL, previous_agent_message_id = NULL, streaming_response = NULL, build_completed_at = NULL, auto_park_dismissed_at = NULL, updated_at = CURRENT_TIMESTAMP WHERE id = ?').run(req.params.id);
|
|
8030
8117
|
const updated = getTicket(req.params.id);
|
|
8031
8118
|
if (!updated) {
|
|
@@ -8038,6 +8125,7 @@ app.post('/tickets/:id/retry', (req, res) => {
|
|
|
8038
8125
|
projectId: updated.project_id,
|
|
8039
8126
|
worktreeBundleId: updated.worktree_bundle_id,
|
|
8040
8127
|
activate: shouldStartBundleBuildNow(updated),
|
|
8128
|
+
selection,
|
|
8041
8129
|
}).sequenceId;
|
|
8042
8130
|
}
|
|
8043
8131
|
return {
|
|
@@ -8049,7 +8137,19 @@ app.post('/tickets/:id/retry', (req, res) => {
|
|
|
8049
8137
|
if (ticket.project_id && ticket.worktree_bundle_id && hasActiveSequenceForBundle(ticket.project_id, ticket.worktree_bundle_id)) {
|
|
8050
8138
|
try {
|
|
8051
8139
|
withExecutionRunTransaction(transaction => {
|
|
8052
|
-
|
|
8140
|
+
releaseQueuedBuildSequenceTicketExecutionRunForRetry({
|
|
8141
|
+
projectId: ticket.project_id,
|
|
8142
|
+
worktreeBundleId: ticket.worktree_bundle_id,
|
|
8143
|
+
ticketId: ticket.id,
|
|
8144
|
+
cancelExecutionRun: runId => transaction.transitionExecutionRun({
|
|
8145
|
+
projectId: ticket.project_id,
|
|
8146
|
+
runId,
|
|
8147
|
+
status: 'cancelled',
|
|
8148
|
+
domainStatus: 'cancelled',
|
|
8149
|
+
eventType: 'retry_superseded',
|
|
8150
|
+
}),
|
|
8151
|
+
});
|
|
8152
|
+
const acceptance = acceptRetry(createExecutionProfileSelection(ticket.project_id));
|
|
8053
8153
|
if (!acceptance.sequenceId) {
|
|
8054
8154
|
throw new Error('Build sequence no longer exists');
|
|
8055
8155
|
}
|
|
@@ -8057,7 +8157,9 @@ app.post('/tickets/:id/retry', (req, res) => {
|
|
|
8057
8157
|
if (!project) {
|
|
8058
8158
|
throw new Error('Build project no longer exists');
|
|
8059
8159
|
}
|
|
8060
|
-
|
|
8160
|
+
const selection = getBuildSequenceTicketExecutionProfileSelection(acceptance.sequenceId, acceptance.ticket.id);
|
|
8161
|
+
const profileRevision = validateExecutionProfileSelection(ticket.project_id, selection);
|
|
8162
|
+
const executionRun = transaction.createExecutionRun({
|
|
8061
8163
|
projectId: ticket.project_id,
|
|
8062
8164
|
kind: 'build',
|
|
8063
8165
|
domainStatus: 'queued',
|
|
@@ -8067,12 +8169,14 @@ app.post('/tickets/:id/retry', (req, res) => {
|
|
|
8067
8169
|
{ entityType: 'build_sequence', entityId: acceptance.sequenceId, relationship: 'context' },
|
|
8068
8170
|
],
|
|
8069
8171
|
metadata: {
|
|
8070
|
-
build_execution_provider:
|
|
8172
|
+
build_execution_provider: profileRevision.profile.provider_preference,
|
|
8173
|
+
...executionProfileSelectionMetadata(selection),
|
|
8071
8174
|
},
|
|
8072
8175
|
initiatedBy: 'user',
|
|
8073
8176
|
retryOfRunId: retrySource?.id ?? null,
|
|
8074
8177
|
eventType: 'build_created',
|
|
8075
8178
|
});
|
|
8179
|
+
bindBuildSequenceTicketExecutionRun(acceptance.sequenceId, acceptance.ticket.id, executionRun.id);
|
|
8076
8180
|
}, io);
|
|
8077
8181
|
}
|
|
8078
8182
|
catch (error) {
|
|
@@ -8353,8 +8457,32 @@ app.post('/tickets/:id/git-push', async (req, res) => {
|
|
|
8353
8457
|
}
|
|
8354
8458
|
const previousTickets = listTicketsInRunContext(ticket);
|
|
8355
8459
|
const forceWithLease = req.body?.force_with_lease === true;
|
|
8460
|
+
if (forceWithLease) {
|
|
8461
|
+
try {
|
|
8462
|
+
const admission = await admitForcePush({
|
|
8463
|
+
project: workspace.project,
|
|
8464
|
+
cwd: workspace.cwd,
|
|
8465
|
+
branch: workspace.branch,
|
|
8466
|
+
source: {
|
|
8467
|
+
kind: 'ticket',
|
|
8468
|
+
id: ticket.id,
|
|
8469
|
+
targetKind: workspace.kind === 'project_root'
|
|
8470
|
+
? 'repo_root'
|
|
8471
|
+
: ticket.worktree_bundle_id
|
|
8472
|
+
? 'bundle'
|
|
8473
|
+
: 'ticket',
|
|
8474
|
+
bundleId: ticket.worktree_bundle_id ?? null,
|
|
8475
|
+
},
|
|
8476
|
+
emitter: io,
|
|
8477
|
+
});
|
|
8478
|
+
return res.status(202).json(admission);
|
|
8479
|
+
}
|
|
8480
|
+
catch (error) {
|
|
8481
|
+
return res.status(409).json({ error: getErrorMessage(error) || 'Unable to request force-push approval right now.' });
|
|
8482
|
+
}
|
|
8483
|
+
}
|
|
8356
8484
|
try {
|
|
8357
|
-
await pushCurrentBranch(workspace.cwd, workspace.branch, { forceWithLease });
|
|
8485
|
+
await pushCurrentBranch(workspace.cwd, workspace.branch, { forceWithLease: false });
|
|
8358
8486
|
}
|
|
8359
8487
|
catch (error) {
|
|
8360
8488
|
return res.status(409).json({ error: getErrorMessage(error) || 'Unable to push the branch right now.' });
|
|
@@ -8836,6 +8964,7 @@ app.get('/projects/:id/execution-runs', (req, res) => {
|
|
|
8836
8964
|
projectId: project.id,
|
|
8837
8965
|
kind: query.kind,
|
|
8838
8966
|
statuses: query.statuses,
|
|
8967
|
+
domainStatus: query.domainStatus,
|
|
8839
8968
|
cursor: query.cursor,
|
|
8840
8969
|
limit: query.limit,
|
|
8841
8970
|
}));
|
|
@@ -8905,6 +9034,7 @@ app.get('/projects/:id/execution-timeline', (req, res) => {
|
|
|
8905
9034
|
project,
|
|
8906
9035
|
kind: query.kind,
|
|
8907
9036
|
statuses: query.statuses,
|
|
9037
|
+
domainStatus: query.domainStatus,
|
|
8908
9038
|
cursor: query.cursor,
|
|
8909
9039
|
limit: query.limit,
|
|
8910
9040
|
scope: scope.scopeEntity,
|
|
@@ -9364,8 +9494,11 @@ io.on('connection', (socket) => {
|
|
|
9364
9494
|
registerTerminalSocketHandlers(io, socket);
|
|
9365
9495
|
});
|
|
9366
9496
|
const DEFAULT_PORT = 3001;
|
|
9497
|
+
const APPROVAL_RECONCILIATION_INTERVAL_MS = 30_000;
|
|
9367
9498
|
let executionEvidenceCleanupTimer = null;
|
|
9368
9499
|
let executionArtifactCleanupTimer = null;
|
|
9500
|
+
let approvalReconciliationTimer = null;
|
|
9501
|
+
let approvalReconciliationPromise = null;
|
|
9369
9502
|
let executionArtifactCleanupPromise = null;
|
|
9370
9503
|
let startServerPromise = null;
|
|
9371
9504
|
let shutdownServerPromise = null;
|
|
@@ -9441,6 +9574,45 @@ const startExecutionArtifactCleanupTimer = () => {
|
|
|
9441
9574
|
}, resolveArtifactCleanupIntervalMs());
|
|
9442
9575
|
executionArtifactCleanupTimer.unref();
|
|
9443
9576
|
};
|
|
9577
|
+
const runApprovalReconciliation = () => {
|
|
9578
|
+
if (approvalReconciliationPromise) {
|
|
9579
|
+
return approvalReconciliationPromise;
|
|
9580
|
+
}
|
|
9581
|
+
approvalReconciliationPromise = reconcileApprovalRequests({
|
|
9582
|
+
emitter: io,
|
|
9583
|
+
includeConsumed: false,
|
|
9584
|
+
resumeApproved: async (request) => {
|
|
9585
|
+
if (request.action_kind === 'git_push') {
|
|
9586
|
+
await resumeGitPushApproval(request.project_id, request.id, io);
|
|
9587
|
+
}
|
|
9588
|
+
else {
|
|
9589
|
+
await resumeProductionCheckApproval(request.project_id, request.id, io);
|
|
9590
|
+
}
|
|
9591
|
+
},
|
|
9592
|
+
resolveTerminal: async (request) => {
|
|
9593
|
+
if (request.action_kind === 'git_push') {
|
|
9594
|
+
await finalizeGitPushApproval(request.project_id, request.id, io);
|
|
9595
|
+
}
|
|
9596
|
+
else {
|
|
9597
|
+
finalizeProductionCheckApproval(request.project_id, request.id, io);
|
|
9598
|
+
}
|
|
9599
|
+
},
|
|
9600
|
+
}).then(() => undefined).catch(error => {
|
|
9601
|
+
console.error('Failed to reconcile approval requests', error);
|
|
9602
|
+
}).finally(() => {
|
|
9603
|
+
approvalReconciliationPromise = null;
|
|
9604
|
+
});
|
|
9605
|
+
return approvalReconciliationPromise;
|
|
9606
|
+
};
|
|
9607
|
+
const startApprovalReconciliationTimer = () => {
|
|
9608
|
+
if (approvalReconciliationTimer) {
|
|
9609
|
+
return;
|
|
9610
|
+
}
|
|
9611
|
+
approvalReconciliationTimer = setInterval(() => {
|
|
9612
|
+
void runApprovalReconciliation();
|
|
9613
|
+
}, APPROVAL_RECONCILIATION_INTERVAL_MS);
|
|
9614
|
+
approvalReconciliationTimer.unref();
|
|
9615
|
+
};
|
|
9444
9616
|
const resolveStartResult = (host) => {
|
|
9445
9617
|
const address = httpServer.address();
|
|
9446
9618
|
const { displayHost } = resolveDesktopServerHost(host);
|
|
@@ -9510,6 +9682,7 @@ export const startServer = ({ port = DEFAULT_PORT, host } = {}) => {
|
|
|
9510
9682
|
throwIfShutdownRequested();
|
|
9511
9683
|
startExecutionEvidenceCleanupTimer();
|
|
9512
9684
|
startExecutionArtifactCleanupTimer();
|
|
9685
|
+
startApprovalReconciliationTimer();
|
|
9513
9686
|
return resolveStartResult(host);
|
|
9514
9687
|
})().finally(() => {
|
|
9515
9688
|
startServerPromise = null;
|
|
@@ -9538,6 +9711,11 @@ export const shutdownServer = async (signal) => {
|
|
|
9538
9711
|
clearInterval(executionArtifactCleanupTimer);
|
|
9539
9712
|
executionArtifactCleanupTimer = null;
|
|
9540
9713
|
}
|
|
9714
|
+
if (approvalReconciliationTimer) {
|
|
9715
|
+
clearInterval(approvalReconciliationTimer);
|
|
9716
|
+
approvalReconciliationTimer = null;
|
|
9717
|
+
}
|
|
9718
|
+
await approvalReconciliationPromise;
|
|
9541
9719
|
await executionArtifactCleanupPromise;
|
|
9542
9720
|
await stopMobileAccess();
|
|
9543
9721
|
const repositoryGraphSchemaExists = db.prepare(`
|