@straiffi/archon 1.7.8 → 1.7.10
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-DwfDSF4q.js → ActivityView-IUWr92uj.js} +1 -1
- package/dist/client/assets/{GitHubActionsDialog-3dMCYCSZ.js → GitHubActionsDialog-0YtWvbFk.js} +1 -1
- package/dist/client/assets/VerificationDialog-B4Pyz1LV.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-Bdnc97XK.js → architectureDiagram-3BPJPVTR-LLMyOR-6.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-boxM3She.js → blockDiagram-GPEHLZMM-aa1HitBJ.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CJDdF7xd.js → c4Diagram-AAUBKEIU-BpSt5sdj.js} +1 -1
- package/dist/client/assets/channel-DWPRC-jg.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-ClpcO-Om.js → chunk-2J33WTMH-D8pf3RNr.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-CcuL_65J.js → chunk-3OPIFGDE-_yx1N2iT.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-CUGYZXkH.js → chunk-5ZQYHXKU-CYURGSbL.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-CApeLDyK.js → chunk-727SXJPM-Ci2Mu1zz.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-8FdSvF2D.js → chunk-AQP2D5EJ-CqVgrKze.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-CZoIOF3a.js → chunk-CSCIHK7Q-CT8aPk-o.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-BigFQI5y.js → chunk-KSCS5N6A-yM1i0J-p.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-DIi3SHaT.js → chunk-L5ZTLDWV-BKMGr31Z.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-B-Z0BcQy.js → chunk-LZXEDZCA-A7oUDETP.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-EBeba0mg.js → chunk-ND2GUHAM-Cagc-XAG.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-DJBI2y53.js → chunk-NZK2D7GU-pe8tKLWI.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-BqxdXhMd.js → chunk-O5CBEL6O-BahwghWW.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-Coe1_Cbb.js → chunk-WU5MYG2G-BfSAFufr.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DBZaZLLc.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B7HsVFoJ.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-tuTmeA0Y.js → dagre-BM42HDAG-DCma6-hS.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-ILGCpG2F.js → diagram-2AECGRRQ-DUeggZrO.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-C8qBZsgK.js → diagram-5GNKFQAL-CdjOKGtl.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BXlcm_Zo.js → diagram-KO2AKTUF-CYjXhgh_.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-B8V5EVbD.js → diagram-LMA3HP47-DYBCh4cm.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CWsdOqcP.js → diagram-OG6HWLK6-D3HPQt3z.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DW8pgly2.js → erDiagram-TEJ5UH35-mG8Yztg-.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Djn7fOVR.js → flowDiagram-I6XJVG4X-4FvjuoSZ.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DZ421MEy.js → ganttDiagram-6RSMTGT7-ByCQI8ft.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CCNzLPuP.js → gitGraphDiagram-PVQCEYII-CzEUA7nB.js} +1 -1
- package/dist/client/assets/index-D-miHTTb.js +273 -0
- package/dist/client/assets/index-TAQIlNdJ.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-Bd1gYgMp.js → infoDiagram-5YYISTIA-Q9CqnXO1.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-txyMoatJ.js → ishikawaDiagram-YF4QCWOH-CO8BToGf.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DhT3bmX6.js → journeyDiagram-JHISSGLW-DtOyWvDJ.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-BBHt2hfC.js → kanban-definition-UN3LZRKU-DIn9bYpk.js} +1 -1
- package/dist/client/assets/{line-KGRcT7Qz.js → line-H-k0M9_s.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-CDzt4_zR.js → mermaid-parser.core-CZOUS5zK.js} +1 -1
- package/dist/client/assets/{mermaid.core-DD_-k1aB.js → mermaid.core-Ck71Qr7h.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DoctVTDl.js → mindmap-definition-RKZ34NQL-BRFEcJw_.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DFlLEi70.js → pieDiagram-4H26LBE5-CwihXXcJ.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-3YHOQgl7.js → quadrantDiagram-W4KKPZXB-moiRw4Cm.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-X4fZVL9M.js → requirementDiagram-4Y6WPE33-tshvM_vV.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BUPnMXeG.js → sankeyDiagram-5OEKKPKP-rtKIuBEp.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-D6QU3M64.js → sequenceDiagram-3UESZ5HK-lkTCo4wE.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-c35bu4qZ.js → stateDiagram-AJRCARHV-CFQhVUSd.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-rrN4DgWp.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CX2y6e_b.js → timeline-definition-PNZ67QCA-BmlQ7Wiy.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BDaWltjF.js → vennDiagram-CIIHVFJN-CZyZepcT.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BpBRL2sb.js → wardleyDiagram-YWT4CUSO-C2b52gni.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-Bqw7X0UT.js → xychartDiagram-2RQKCTM6-FqnROUHq.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +23 -10
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +330 -25
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +5 -4
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/automationCheckGate.js +114 -20
- package/dist/server/lib/automationCheckGate.js.map +1 -1
- package/dist/server/lib/automationProgression.js +2 -1
- package/dist/server/lib/automationProgression.js.map +1 -1
- package/dist/server/lib/automationReconciliation.js +19 -0
- package/dist/server/lib/automationReconciliation.js.map +1 -1
- package/dist/server/lib/automationResumeDecision.js +82 -0
- package/dist/server/lib/automationResumeDecision.js.map +1 -1
- package/dist/server/lib/automationReviewGate.js +142 -0
- package/dist/server/lib/automationReviewGate.js.map +1 -0
- package/dist/server/lib/automationStageDetails.js +98 -5
- package/dist/server/lib/automationStageDetails.js.map +1 -1
- package/dist/server/lib/buildCompletionContinuation.js +109 -0
- package/dist/server/lib/buildCompletionContinuation.js.map +1 -0
- package/dist/server/lib/buildSequences.js +81 -0
- package/dist/server/lib/buildSequences.js.map +1 -1
- package/dist/server/lib/buildTicketCommit.js +219 -0
- package/dist/server/lib/buildTicketCommit.js.map +1 -0
- package/dist/server/lib/bundleAutomationReadiness.js +7 -0
- package/dist/server/lib/bundleAutomationReadiness.js.map +1 -0
- package/dist/server/lib/bundleReviewOperations.js +17 -5
- package/dist/server/lib/bundleReviewOperations.js.map +1 -1
- package/dist/server/lib/chatOperations.js +2 -2
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/checkDefinitions.js +11 -0
- package/dist/server/lib/checkDefinitions.js.map +1 -1
- package/dist/server/lib/checkGateEvaluations.js +4 -3
- package/dist/server/lib/checkGateEvaluations.js.map +1 -1
- package/dist/server/lib/checkRunner.js +27 -4
- package/dist/server/lib/checkRunner.js.map +1 -1
- package/dist/server/lib/checkRuns.js +38 -6
- package/dist/server/lib/checkRuns.js.map +1 -1
- package/dist/server/lib/git.js +5 -1
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/lightweightPrompt.js +2 -1
- package/dist/server/lib/lightweightPrompt.js.map +1 -1
- package/dist/server/lib/projectAutoConfig.js +2 -1
- package/dist/server/lib/projectAutoConfig.js.map +1 -1
- package/dist/server/lib/projects.js +95 -10
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/requiredCheckPolicy.js +150 -19
- package/dist/server/lib/requiredCheckPolicy.js.map +1 -1
- package/dist/server/lib/run.js +3 -2
- package/dist/server/lib/run.js.map +1 -1
- package/dist/server/lib/terminal.js +5 -7
- package/dist/server/lib/terminal.js.map +1 -1
- package/dist/server/lib/testSessions.js +2 -2
- package/dist/server/lib/testSessions.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +251 -160
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/tickets.js +45 -4
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/lib/workspaceProcessEnvironment.js +21 -0
- package/dist/server/lib/workspaceProcessEnvironment.js.map +1 -0
- package/dist/server/workers/build.js +57 -97
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +13 -6
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +92 -116
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/plan.js +4 -1
- package/dist/server/workers/plan.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/VerificationDialog-CoTfXMyb.js +0 -4
- package/dist/client/assets/channel-BGqdAcIT.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-D5VuKRcj.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B9GNqpRr.js +0 -1
- package/dist/client/assets/index-BRc02lbW.js +0 -273
- package/dist/client/assets/index-CZO9HL1Z.css +0 -2
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Ymy1_EHr.js +0 -1
package/dist/server/index.js
CHANGED
|
@@ -28,8 +28,8 @@ import { emitMobileRealtime, getMobileAccessStatus, regenerateMobilePairingChall
|
|
|
28
28
|
import { validateDesktopMobileAccessRequest } from './lib/mobileAccessSecurity.js';
|
|
29
29
|
import { refreshChatSessionUsageSnapshot, refreshSpecSessionUsageSnapshot, stopAllBuildAgents, stopAllReviewAgents, stopBuildAgent, stopReviewAgent } from './lib/agent.js';
|
|
30
30
|
import { runLightweightPrompt } from './lib/lightweightPrompt.js';
|
|
31
|
-
import { startBuildChain, stopBuildChain } from './lib/buildChains.js';
|
|
32
|
-
import { activateQueuedBuildSequenceTicket, compensateBuildSequenceAcceptance, enqueueBundledBuild, getDependencyOrderedBundleTicketIds, hasActiveSequenceForBundle, removeTicketFromBuildSequence, stopBuildSequence, } from './lib/buildSequences.js';
|
|
31
|
+
import { advanceBuildChain, startBuildChain, stopBuildChain } from './lib/buildChains.js';
|
|
32
|
+
import { activateQueuedBuildSequenceTicket, compensateBuildSequenceAcceptance, enqueueBundledBuild, getDependencyOrderedBundleTicketIds, getBuildSequenceIdForTicket, hasActiveSequenceForBundle, removeTicketFromBuildSequence, stopBuildSequence, } from './lib/buildSequences.js';
|
|
33
33
|
import { prepareTicketForBuild } from './lib/buildFlow.js';
|
|
34
34
|
import { getBundlePlanMutationBlockerById, shouldBlockPlanForBundleMutationById, } from './lib/bundleActivity.js';
|
|
35
35
|
import { getDiscoveredModels, normalizeModelId, normalizeTicketModelId } from './lib/models.js';
|
|
@@ -47,12 +47,15 @@ import { exportProjectMemoryArchive, importProjectMemoryArchive } from './lib/pr
|
|
|
47
47
|
import { buildReviewFindingsResponse, computeDiffSignature, getLatestReviewRunForContext, listReviewFindings } from './lib/reviewFindings.js';
|
|
48
48
|
import { formatBuildOpenQuestionAnswersPrompt, getLatestBuildOpenQuestionBatchStatus, hasActiveBuildOpenQuestionBatch, listBuildOpenQuestionsForBundle, loadBuildOpenQuestionsByBundleIds, } from './lib/buildOpenQuestions.js';
|
|
49
49
|
import { acceptBuildOpenQuestionResolution } from './lib/buildOpenQuestionOperations.js';
|
|
50
|
-
import { completeAutomationProgression, createAutomationReviewFix, finishAutomationReviewFix, getAutomationProgression, recoverLegacyAutomationProgression, recoverStoppedSideEffectProgression, runAutomationProgression, stopAutomationProgression, waitAutomationProgression } from './lib/automationProgression.js';
|
|
50
|
+
import { completeAutomationProgression, createAutomationReviewFix, ensureAutomationProgression, finishAutomationReviewFix, getAutomationProgression, recoverLegacyAutomationProgression, recoverStoppedSideEffectProgression, runAutomationProgression, stopAutomationProgression, waitAutomationProgression } from './lib/automationProgression.js';
|
|
51
51
|
import { reconcileAutomationStage } from './lib/automationReconciliation.js';
|
|
52
|
+
import { runAutomationReviewGateOrPause } from './lib/automationReviewGate.js';
|
|
52
53
|
import { pausedRunBelongsToProgression, resolveAutomationResumeDecision } from './lib/automationResumeDecision.js';
|
|
53
54
|
import { getAutomationStageDetails, } from './lib/automationStageDetails.js';
|
|
54
55
|
import { buildAutomationFixInstruction, clearAutomationPause, countBlockingFindings, depthAtLeast, getBundleAutomationState, isAutomationDepth, recordAutomationPause, resolveAutomationConfig, upsertBundleAutomationState, } from './lib/ticketAutomation.js';
|
|
55
|
-
import { resolveAutomationCheckGateResume, runAutomationCommitChain } from './lib/ticketAutomationCommit.js';
|
|
56
|
+
import { resolveAutomationCheckGateResume, runAutomationCommitChain, runAutomationCommitOperation } from './lib/ticketAutomationCommit.js';
|
|
57
|
+
import { canMutateBuildTicketCommitCheckpoint, resolveBuildTicketCommitCheckpointLineage } from './lib/buildTicketCommit.js';
|
|
58
|
+
import { advanceSuccessfulBuildTicketAfterCheckpoint, compensateBuildSequenceTicketActivation } from './lib/buildCompletionContinuation.js';
|
|
56
59
|
import { getDiscoveredSkills, normalizeSkillNames } from './lib/skills.js';
|
|
57
60
|
import { clearAllPreviewProxies } from './lib/previewProxy.js';
|
|
58
61
|
import { createExecutionRun, addExecutionRunLink, addExecutionRunLinks, getExecutionRun, hasActiveBuildExecutionRunForTicket, getGitHubActionsExecutionDetails, getTestExecutionDetails, GitHubActionsDispatchConflictError, listExecutionRunLinks, listExecutionRuns, listLifecycleEvents, listProjectLifecycleEvents, toCanonicalLifecycleEvent, transitionExecutionRun, withExecutionRunTransaction, } from './lib/executionRuns.js';
|
|
@@ -75,14 +78,15 @@ import { PlanningReferenceError, resolveExternalPlanningDescription } from './li
|
|
|
75
78
|
import { refreshIfNeeded as refreshAssignedIssues, clearCachedAssignedIssues } from './lib/integrations/assignedIssuesCache.js';
|
|
76
79
|
import { buildCommitMessagePrompt, normalizeGeneratedCommitMessage } from './lib/commitMessage.js';
|
|
77
80
|
import { BUNDLE_PULL_REQUEST_SYNC_TTL_MS, getBundlePullRequestRecord, hasOpenBundlePullRequest, serializeBundlePullRequest, shouldSyncBundlePullRequest, syncTrackedBundlePullRequestIfNeeded, upsertBundlePullRequest, upsertBundlePullRequestFromGitHub, } from './lib/bundlePullRequests.js';
|
|
78
|
-
import { countInboundProjectLinks, getEffectiveProject, getProjectCheckDefinitions, getProjectById, getProjectTestCommands, getProjectTicketStats, hasProjectRunIde, listInterruptedProjectDeletions, listProjects, releaseInterruptedProjectDeletionClaims, replaceProjectLinks, serializeProject, updateProjectActiveTarget, validateProjectPayload, } from './lib/projects.js';
|
|
81
|
+
import { countInboundProjectLinks, getEffectiveProject, getProjectCheckDefinitions, getProjectById, getProjectTestCommands, getProjectTicketStats, hasProjectRunIde, listInterruptedProjectDeletions, listProjects, releaseInterruptedProjectDeletionClaims, replaceProjectLinks, serializeProject, updateProjectActiveTarget, validateProjectRequiredCheckPolicyReferences, validateProjectPayload, } from './lib/projects.js';
|
|
79
82
|
import { getActiveRunStatus, getActiveRunStatusForProject, getPreviewStatusForProject, hasRunConfig, isRunning, openIde, openTicketIdeInWorkspace, resolveProjectRunContextKey, runSetupCommandsInWorkspace, runTicketInWorkspace, stopAllTickets, stopTicket } from './lib/run.js';
|
|
80
83
|
import { clearAllTestSessions, createTestSession, deleteTestSession, discoverTestsForSession, doesTestFileExistForSession, getTestSession, isTestSelectionSupported, startTestSessionRun, stopTestSessionRun } from './lib/testSessions.js';
|
|
81
84
|
import { closeCheckRunnerAdmissions, getCheckBatchAttempts, openCheckRunnerAdmissions, rerunCheckBatchAndSchedule, shutdownCheckRunner, startCheckBatch, stopCheckBatch } from './lib/checkRunner.js';
|
|
82
85
|
import { findActiveCheckBatchForTarget, getCheckAttemptDetails, getCheckBatchDetails, hasActiveProjectCheckBatch, isCheckAttemptCurrent, resolveCheckBatchRerunEligibility } from './lib/checkRuns.js';
|
|
83
|
-
import { getCheckDefinitionFingerprint } from './lib/checkDefinitions.js';
|
|
86
|
+
import { getCheckDefinitionFingerprint, validateRequiredCheckPolicySnapshotSize } from './lib/checkDefinitions.js';
|
|
84
87
|
import { getCheckGateEvaluation } from './lib/checkGateEvaluations.js';
|
|
85
88
|
import { captureCheckWorkspaceIdentity } from './lib/checkWorkspaceIdentity.js';
|
|
89
|
+
import { canonicalizeBundleRequiredCheckPolicyOverride, parseBundleRequiredCheckPolicyOverride, resolveEffectiveRequiredCheckPolicyMembership, } from './lib/requiredCheckPolicy.js';
|
|
86
90
|
import { getBundleBuildBlockerResponse, shouldStartBundleBuildNow, transitionTicketState, } from './lib/ticketWorkflowOperations.js';
|
|
87
91
|
import { submitPlanTicketFollowUp, submitTicketFollowUp, } from './lib/ticketFollowUpOperations.js';
|
|
88
92
|
import { closePendingTicketPlanQuestionSet, listPendingTicketPlanQuestionSetMessageIds, resolveTicketPlanQuestionSet, restoreClosedTicketPlanQuestionSets, } from './lib/planQuestionOperations.js';
|
|
@@ -1460,6 +1464,10 @@ const serializeBundleRow = (projectId, bundle, openQuestions = bundle ? loadBuil
|
|
|
1460
1464
|
const hasPreparedWorktree = bundle.kind === 'project_root'
|
|
1461
1465
|
? true
|
|
1462
1466
|
: Boolean(project && resolveExistingWorktreePath(bundle.branch, project));
|
|
1467
|
+
const parsedOverride = bundle.kind === 'project_root'
|
|
1468
|
+
? { value: null }
|
|
1469
|
+
: parseBundleRequiredCheckPolicyOverride(bundle.required_check_policy_override);
|
|
1470
|
+
const effectivePolicy = resolveEffectiveRequiredCheckPolicyMembership(project, bundle);
|
|
1463
1471
|
return {
|
|
1464
1472
|
...bundle,
|
|
1465
1473
|
has_prepared_worktree: hasPreparedWorktree,
|
|
@@ -1467,6 +1475,15 @@ const serializeBundleRow = (projectId, bundle, openQuestions = bundle ? loadBuil
|
|
|
1467
1475
|
? serializeBundlePullRequest(getBundlePullRequestRecord(bundle.id, projectId))
|
|
1468
1476
|
: null,
|
|
1469
1477
|
automation_config: resolveAutomationConfig(bundle, project),
|
|
1478
|
+
required_check_policy_override: 'error' in parsedOverride ? null : parsedOverride.value,
|
|
1479
|
+
required_check_policy: 'error' in effectivePolicy
|
|
1480
|
+
? undefined
|
|
1481
|
+
: {
|
|
1482
|
+
source: effectivePolicy.source,
|
|
1483
|
+
required_check_definition_ids: effectivePolicy.required_check_definition_ids,
|
|
1484
|
+
pre_review_check_definition_ids: effectivePolicy.pre_review_check_definition_ids,
|
|
1485
|
+
},
|
|
1486
|
+
required_check_policy_error: 'error' in parsedOverride ? parsedOverride.error : ('error' in effectivePolicy ? effectivePolicy.error : null),
|
|
1470
1487
|
open_questions: openQuestions,
|
|
1471
1488
|
build_open_question_batch_status: getLatestBuildOpenQuestionBatchStatus(projectId, bundle.id),
|
|
1472
1489
|
};
|
|
@@ -3741,11 +3758,14 @@ app.patch('/bundles/:id', (req, res) => {
|
|
|
3741
3758
|
return res.status(404).json({ error: 'Bundle not found' });
|
|
3742
3759
|
}
|
|
3743
3760
|
const hasNameUpdate = hasOwn(req.body, 'name');
|
|
3761
|
+
const hasRequiredCheckPolicyOverrideUpdate = hasOwn(req.body, 'required_check_policy_override');
|
|
3744
3762
|
if (isProjectRootBundle(bundle)) {
|
|
3745
3763
|
return res.status(409).json({
|
|
3746
3764
|
error: hasNameUpdate
|
|
3747
3765
|
? 'Project root bundles cannot be renamed'
|
|
3748
|
-
:
|
|
3766
|
+
: hasRequiredCheckPolicyOverrideUpdate
|
|
3767
|
+
? 'Project root bundles cannot override required-check policy'
|
|
3768
|
+
: 'Project root bundle automation cannot be overridden',
|
|
3749
3769
|
});
|
|
3750
3770
|
}
|
|
3751
3771
|
let nextName = bundle.name;
|
|
@@ -3818,6 +3838,39 @@ app.patch('/bundles/:id', (req, res) => {
|
|
|
3818
3838
|
return res.status(400).json({ error: 'automation_pause_on_open_questions must be a boolean' });
|
|
3819
3839
|
}
|
|
3820
3840
|
}
|
|
3841
|
+
let requiredCheckPolicyOverride;
|
|
3842
|
+
let requiredCheckPolicyOverrideValue;
|
|
3843
|
+
if (hasRequiredCheckPolicyOverrideUpdate) {
|
|
3844
|
+
const value = req.body.required_check_policy_override;
|
|
3845
|
+
if (value == null) {
|
|
3846
|
+
requiredCheckPolicyOverride = null;
|
|
3847
|
+
requiredCheckPolicyOverrideValue = null;
|
|
3848
|
+
}
|
|
3849
|
+
else {
|
|
3850
|
+
const result = canonicalizeBundleRequiredCheckPolicyOverride(value);
|
|
3851
|
+
if ('error' in result) {
|
|
3852
|
+
return res.status(400).json({ error: result.error });
|
|
3853
|
+
}
|
|
3854
|
+
requiredCheckPolicyOverrideValue = result.value;
|
|
3855
|
+
requiredCheckPolicyOverride = result.value ? JSON.stringify(result.value) : null;
|
|
3856
|
+
}
|
|
3857
|
+
}
|
|
3858
|
+
if (requiredCheckPolicyOverrideValue) {
|
|
3859
|
+
const definitions = getProjectCheckDefinitions(result.project);
|
|
3860
|
+
const definitionIds = new Set(definitions.map(definition => definition.id));
|
|
3861
|
+
const missingId = [
|
|
3862
|
+
...requiredCheckPolicyOverrideValue.required_check_definition_ids,
|
|
3863
|
+
...requiredCheckPolicyOverrideValue.pre_review_check_definition_ids,
|
|
3864
|
+
].find(id => !definitionIds.has(id));
|
|
3865
|
+
if (missingId) {
|
|
3866
|
+
return res.status(400).json({ error: `required_check_policy_override references missing check definition ${missingId}` });
|
|
3867
|
+
}
|
|
3868
|
+
const requiredDefinitions = definitions.filter(definition => requiredCheckPolicyOverrideValue.required_check_definition_ids.includes(definition.id));
|
|
3869
|
+
const policySnapshotSizeError = validateRequiredCheckPolicySnapshotSize(requiredCheckPolicyOverrideValue.required_check_definition_ids, requiredDefinitions);
|
|
3870
|
+
if (policySnapshotSizeError) {
|
|
3871
|
+
return res.status(400).json({ error: policySnapshotSizeError });
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3821
3874
|
let updated = null;
|
|
3822
3875
|
try {
|
|
3823
3876
|
updated = db.transaction(() => {
|
|
@@ -3835,6 +3888,7 @@ app.patch('/bundles/:id', (req, res) => {
|
|
|
3835
3888
|
automationDepth,
|
|
3836
3889
|
automationReviewFixEnabled,
|
|
3837
3890
|
automationPauseOnOpenQuestions,
|
|
3891
|
+
requiredCheckPolicyOverride,
|
|
3838
3892
|
});
|
|
3839
3893
|
})();
|
|
3840
3894
|
}
|
|
@@ -3938,6 +3992,18 @@ app.post('/bundles/:id/build-open-questions/resolve', (req, res) => {
|
|
|
3938
3992
|
io.emit('ticket:updated', ticket);
|
|
3939
3993
|
}
|
|
3940
3994
|
if (reviewResult && !reviewResult.ok) {
|
|
3995
|
+
if (reviewResult.code === 'bundle_build_incomplete') {
|
|
3996
|
+
completeAutomationProgression({
|
|
3997
|
+
projectId: result.project.id,
|
|
3998
|
+
bundleId: bundle.id,
|
|
3999
|
+
progressionRunId: accepted.progressionRunId,
|
|
4000
|
+
broadcaster: io,
|
|
4001
|
+
});
|
|
4002
|
+
for (const ticket of listDetailedBundleTickets(result.project.id, bundle.id)) {
|
|
4003
|
+
io.emit('ticket:updated', ticket);
|
|
4004
|
+
}
|
|
4005
|
+
return res.json(serializeBundleDetails(result.project, bundle));
|
|
4006
|
+
}
|
|
3941
4007
|
waitAutomationProgression({
|
|
3942
4008
|
projectId: result.project.id,
|
|
3943
4009
|
bundleId: bundle.id,
|
|
@@ -3951,8 +4017,8 @@ app.post('/bundles/:id/build-open-questions/resolve', (req, res) => {
|
|
|
3951
4017
|
return res.status(reviewResult.status).json({ error: reviewResult.error });
|
|
3952
4018
|
}
|
|
3953
4019
|
return res.json(serializeBundleDetails(result.project, bundle, {
|
|
3954
|
-
review_owner_ticket_id: reviewResult?.value?.id,
|
|
3955
|
-
target_ticket_id: reviewResult?.value?.id,
|
|
4020
|
+
review_owner_ticket_id: reviewResult?.ok ? reviewResult.value?.id : undefined,
|
|
4021
|
+
target_ticket_id: reviewResult?.ok ? reviewResult.value?.id : undefined,
|
|
3956
4022
|
}));
|
|
3957
4023
|
}
|
|
3958
4024
|
for (const ticket of listDetailedBundleTickets(result.project.id, bundle.id)) {
|
|
@@ -4135,6 +4201,183 @@ app.post('/bundles/:id/resume-automation', async (req, res) => {
|
|
|
4135
4201
|
if (!revalidateDecision()) {
|
|
4136
4202
|
return res.status(409).json({ error: 'Bundle automation state changed before Resume could start' });
|
|
4137
4203
|
}
|
|
4204
|
+
const checkpointLineage = resolveBuildTicketCommitCheckpointLineage({
|
|
4205
|
+
projectId: result.project.id,
|
|
4206
|
+
bundleId: bundle.id,
|
|
4207
|
+
progressionRunId,
|
|
4208
|
+
});
|
|
4209
|
+
if (checkpointLineage) {
|
|
4210
|
+
const owner = getTicket(decision.owner_ticket_id);
|
|
4211
|
+
if (!owner || owner.id !== checkpointLineage.ticket.id || owner.agent_status !== 'done') {
|
|
4212
|
+
return res.status(409).json({ error: 'Checkpoint progression owner is no longer the active Build ticket' });
|
|
4213
|
+
}
|
|
4214
|
+
let retryOfRunId;
|
|
4215
|
+
let commitAlreadyComplete = false;
|
|
4216
|
+
const stageRunId = bundleState.automation_paused_stage_run_id;
|
|
4217
|
+
if (stageRunId) {
|
|
4218
|
+
const stage = getExecutionRun(result.project.id, stageRunId);
|
|
4219
|
+
if (!stage
|
|
4220
|
+
|| !['automation_commit', 'check_batch'].includes(stage.kind)
|
|
4221
|
+
|| !pausedRunBelongsToProgression(result.project.id, bundle.id, progressionRunId, stageRunId)) {
|
|
4222
|
+
return res.status(409).json({ error: 'The paused checkpoint stage does not belong to the active progression' });
|
|
4223
|
+
}
|
|
4224
|
+
if (stage.kind === 'automation_commit') {
|
|
4225
|
+
let reconciled;
|
|
4226
|
+
try {
|
|
4227
|
+
reconciled = await reconcileAutomationStage({
|
|
4228
|
+
projectId: result.project.id,
|
|
4229
|
+
bundleId: bundle.id,
|
|
4230
|
+
progressionRunId,
|
|
4231
|
+
stageRunId,
|
|
4232
|
+
});
|
|
4233
|
+
}
|
|
4234
|
+
catch (error) {
|
|
4235
|
+
return res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
|
|
4236
|
+
}
|
|
4237
|
+
if (reconciled.domainStatus === 'ambiguous') {
|
|
4238
|
+
return res.status(409).json({ error: 'The paused checkpoint commit is ambiguous and cannot be resumed safely.' });
|
|
4239
|
+
}
|
|
4240
|
+
if (reconciled.status === 'completed' && reconciled.domainStatus === 'reconciled_completed') {
|
|
4241
|
+
commitAlreadyComplete = true;
|
|
4242
|
+
}
|
|
4243
|
+
else if (reconciled.status === 'interrupted' && reconciled.domainStatus === 'reconciled_absent') {
|
|
4244
|
+
retryOfRunId = stage.id;
|
|
4245
|
+
}
|
|
4246
|
+
else {
|
|
4247
|
+
return res.status(409).json({ error: 'The paused checkpoint commit has no safely resumable outcome.' });
|
|
4248
|
+
}
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
try {
|
|
4252
|
+
if (!revalidateDecision()) {
|
|
4253
|
+
return res.status(409).json({ error: 'Bundle automation state changed before Resume could start' });
|
|
4254
|
+
}
|
|
4255
|
+
runAutomationProgression({
|
|
4256
|
+
projectId: result.project.id,
|
|
4257
|
+
bundleId: bundle.id,
|
|
4258
|
+
progressionRunId,
|
|
4259
|
+
broadcaster: io,
|
|
4260
|
+
});
|
|
4261
|
+
if (commitAlreadyComplete) {
|
|
4262
|
+
completeAutomationProgression({
|
|
4263
|
+
projectId: result.project.id,
|
|
4264
|
+
bundleId: bundle.id,
|
|
4265
|
+
progressionRunId,
|
|
4266
|
+
broadcaster: io,
|
|
4267
|
+
});
|
|
4268
|
+
}
|
|
4269
|
+
else {
|
|
4270
|
+
await runAutomationCommitOperation({
|
|
4271
|
+
ticket: owner,
|
|
4272
|
+
io,
|
|
4273
|
+
progressionRunId,
|
|
4274
|
+
retryOfRunId,
|
|
4275
|
+
mutationLabel: 'checkpoint commit',
|
|
4276
|
+
canCommitLive: canMutateBuildTicketCommitCheckpoint,
|
|
4277
|
+
shouldCompleteProgression: () => true,
|
|
4278
|
+
failureMode: 'throw',
|
|
4279
|
+
requiredProgressionPurpose: 'build_ticket_checkpoint',
|
|
4280
|
+
});
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
catch (error) {
|
|
4284
|
+
return res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
|
|
4285
|
+
}
|
|
4286
|
+
const workflowContext = validateWorkflowContext(checkpointLineage.progression.metadata);
|
|
4287
|
+
const continuation = advanceSuccessfulBuildTicketAfterCheckpoint({
|
|
4288
|
+
ticket: owner,
|
|
4289
|
+
emitUpdatedTickets,
|
|
4290
|
+
});
|
|
4291
|
+
if (continuation.nextBuild) {
|
|
4292
|
+
const nextBuild = continuation.nextBuild;
|
|
4293
|
+
const nextSequenceId = continuation.nextSequenceId;
|
|
4294
|
+
const scheduling = startBuild(nextBuild, io, {
|
|
4295
|
+
initiation: {
|
|
4296
|
+
initiator: 'automation',
|
|
4297
|
+
causalParentRunId: checkpointLineage.parent.id,
|
|
4298
|
+
workflowContext,
|
|
4299
|
+
},
|
|
4300
|
+
sequenceId: nextSequenceId,
|
|
4301
|
+
accept: () => {
|
|
4302
|
+
const transition = prepareTicketForBuild(nextBuild.id, {
|
|
4303
|
+
ignoredBlockerTicketIds: continuation.ignoredBlockerTicketIds,
|
|
4304
|
+
});
|
|
4305
|
+
if (!transition.ok) {
|
|
4306
|
+
throw new Error(transition.error);
|
|
4307
|
+
}
|
|
4308
|
+
if (!nextSequenceId) {
|
|
4309
|
+
throw new Error('Build sequence no longer exists');
|
|
4310
|
+
}
|
|
4311
|
+
activateQueuedBuildSequenceTicket(nextSequenceId, transition.ticket.id);
|
|
4312
|
+
return {
|
|
4313
|
+
ticket: transition.ticket,
|
|
4314
|
+
sequenceId: nextSequenceId,
|
|
4315
|
+
compensate: () => compensateBuildSequenceTicketActivation(nextSequenceId, transition.ticket.id),
|
|
4316
|
+
};
|
|
4317
|
+
},
|
|
4318
|
+
});
|
|
4319
|
+
if (!scheduling.accepted) {
|
|
4320
|
+
const stoppedSequence = stopBuildSequence(nextBuild.id);
|
|
4321
|
+
emitUpdatedTickets(stoppedSequence.affectedTicketIds);
|
|
4322
|
+
}
|
|
4323
|
+
}
|
|
4324
|
+
else if (!continuation.nextTicketId && owner.project_id && owner.worktree_bundle_id) {
|
|
4325
|
+
const resumedOwnerForReview = getTicket(owner.id) ?? owner;
|
|
4326
|
+
const liveProject = getEffectiveProject(resumedOwnerForReview) ?? result.project;
|
|
4327
|
+
const automationConfig = resolveAutomationConfig(resumedOwnerForReview.bundle ?? null, liveProject);
|
|
4328
|
+
const autoReviewEnabled = depthAtLeast(automationConfig.depth, 'auto_review');
|
|
4329
|
+
const latestBundleState = getBundleAutomationState(owner.project_id, owner.worktree_bundle_id);
|
|
4330
|
+
const openQuestions = listBuildOpenQuestionsForBundle(owner.project_id, owner.worktree_bundle_id);
|
|
4331
|
+
const shouldPauseForOpenQuestions = autoReviewEnabled
|
|
4332
|
+
&& automationConfig.pauseOnOpenQuestions
|
|
4333
|
+
&& openQuestions.length > 0;
|
|
4334
|
+
if (shouldPauseForOpenQuestions) {
|
|
4335
|
+
const reviewProgression = ensureAutomationProgression({
|
|
4336
|
+
projectId: owner.project_id,
|
|
4337
|
+
bundleId: owner.worktree_bundle_id,
|
|
4338
|
+
ticketId: owner.id,
|
|
4339
|
+
ticketTitle: owner.title,
|
|
4340
|
+
parentRunId: checkpointLineage.parent.id,
|
|
4341
|
+
workflowContext,
|
|
4342
|
+
broadcaster: io,
|
|
4343
|
+
});
|
|
4344
|
+
waitAutomationProgression({
|
|
4345
|
+
projectId: owner.project_id,
|
|
4346
|
+
bundleId: owner.worktree_bundle_id,
|
|
4347
|
+
progressionRunId: reviewProgression.runId,
|
|
4348
|
+
pauseCode: 'open_questions',
|
|
4349
|
+
pauseReason: `${openQuestions.length} unresolved Build open question${openQuestions.length === 1 ? '' : 's'}`,
|
|
4350
|
+
reasonCode: 'precondition_failed',
|
|
4351
|
+
pausedStageRunId: checkpointLineage.parent.id,
|
|
4352
|
+
broadcaster: io,
|
|
4353
|
+
});
|
|
4354
|
+
}
|
|
4355
|
+
else if (autoReviewEnabled && (!latestBundleState?.automation_paused_reason || latestBundleState.automation_paused_code === 'open_questions')) {
|
|
4356
|
+
const reviewProgression = ensureAutomationProgression({
|
|
4357
|
+
projectId: owner.project_id,
|
|
4358
|
+
bundleId: owner.worktree_bundle_id,
|
|
4359
|
+
ticketId: owner.id,
|
|
4360
|
+
ticketTitle: owner.title,
|
|
4361
|
+
parentRunId: checkpointLineage.parent.id,
|
|
4362
|
+
workflowContext,
|
|
4363
|
+
broadcaster: io,
|
|
4364
|
+
});
|
|
4365
|
+
await runAutomationReviewGateOrPause({
|
|
4366
|
+
projectId: owner.project_id,
|
|
4367
|
+
bundleId: owner.worktree_bundle_id,
|
|
4368
|
+
progressionRunId: reviewProgression.runId,
|
|
4369
|
+
broadcaster: io,
|
|
4370
|
+
pausedStageRunId: checkpointLineage.parent.id,
|
|
4371
|
+
initiation: { workflowContext },
|
|
4372
|
+
});
|
|
4373
|
+
}
|
|
4374
|
+
}
|
|
4375
|
+
const resumedOwner = getTicket(owner.id);
|
|
4376
|
+
if (resumedOwner) {
|
|
4377
|
+
io.emit('ticket:updated', resumedOwner);
|
|
4378
|
+
}
|
|
4379
|
+
return res.json(serializeBundleDetails(result.project, bundle));
|
|
4380
|
+
}
|
|
4138
4381
|
let sideEffectResume = null;
|
|
4139
4382
|
if (bundleState.automation_paused_stage_run_id) {
|
|
4140
4383
|
const stageRunId = bundleState.automation_paused_stage_run_id;
|
|
@@ -4392,17 +4635,43 @@ app.post('/bundles/:id/resume-automation', async (req, res) => {
|
|
|
4392
4635
|
return res.status(409).json({ error: 'The selected Resume outcome no longer matches the bundle state' });
|
|
4393
4636
|
}
|
|
4394
4637
|
}
|
|
4395
|
-
else if (owner.state === 'build' && owner.agent_status === 'done' && decision.outcome === 'start_review') {
|
|
4638
|
+
else if (owner.state === 'build' && owner.agent_status === 'done' && (decision.outcome === 'start_review' || decision.outcome === 'rerun_review_checks')) {
|
|
4396
4639
|
if (!revalidateDecision()) {
|
|
4397
4640
|
return res.status(409).json({ error: 'Bundle automation state changed before Resume could start' });
|
|
4398
4641
|
}
|
|
4399
|
-
const
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4642
|
+
const progression = getAutomationProgression(result.project.id, bundle.id);
|
|
4643
|
+
if (!progression || progression.id !== progressionRunId) {
|
|
4644
|
+
return res.status(409).json({ error: 'Automation progression ownership is invalid' });
|
|
4645
|
+
}
|
|
4646
|
+
const workflowContext = validateWorkflowContext(progression.metadata);
|
|
4647
|
+
let reviewStartFailureStatus = null;
|
|
4648
|
+
let reviewStartFailureError = null;
|
|
4649
|
+
try {
|
|
4650
|
+
runAutomationProgression({
|
|
4651
|
+
projectId: result.project.id,
|
|
4652
|
+
bundleId: bundle.id,
|
|
4653
|
+
progressionRunId,
|
|
4654
|
+
broadcaster: io,
|
|
4655
|
+
});
|
|
4656
|
+
await runAutomationReviewGateOrPause({
|
|
4657
|
+
projectId: result.project.id,
|
|
4658
|
+
bundleId: bundle.id,
|
|
4659
|
+
progressionRunId,
|
|
4660
|
+
broadcaster: io,
|
|
4661
|
+
pausedStageRunId: bundleState.automation_paused_stage_run_id,
|
|
4662
|
+
initiation: { workflowContext },
|
|
4663
|
+
onReviewStartFailure: failure => {
|
|
4664
|
+
reviewStartFailureStatus = failure.status;
|
|
4665
|
+
reviewStartFailureError = failure.error;
|
|
4666
|
+
restoreWaitingProgression();
|
|
4667
|
+
},
|
|
4668
|
+
});
|
|
4669
|
+
}
|
|
4670
|
+
catch (error) {
|
|
4671
|
+
return res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
|
|
4672
|
+
}
|
|
4673
|
+
if (reviewStartFailureStatus !== null && reviewStartFailureError !== null) {
|
|
4674
|
+
return res.status(reviewStartFailureStatus).json({ error: reviewStartFailureError });
|
|
4406
4675
|
}
|
|
4407
4676
|
}
|
|
4408
4677
|
else {
|
|
@@ -4462,6 +4731,11 @@ app.post('/bundles/:id/dismiss-automation-pause', async (req, res) => {
|
|
|
4462
4731
|
catch (error) {
|
|
4463
4732
|
return res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
|
|
4464
4733
|
}
|
|
4734
|
+
const checkpointLineage = resolveBuildTicketCommitCheckpointLineage({
|
|
4735
|
+
projectId: result.project.id,
|
|
4736
|
+
bundleId: bundle.id,
|
|
4737
|
+
progressionRunId,
|
|
4738
|
+
});
|
|
4465
4739
|
if (bundleState.automation_paused_stage_run_id) {
|
|
4466
4740
|
const stage = getExecutionRun(result.project.id, bundleState.automation_paused_stage_run_id);
|
|
4467
4741
|
if (!stage
|
|
@@ -4497,6 +4771,10 @@ app.post('/bundles/:id/dismiss-automation-pause', async (req, res) => {
|
|
|
4497
4771
|
broadcaster: io,
|
|
4498
4772
|
stopLocalWorker: worker => (worker.kind === 'review' ? stopReviewAgent(worker.ticket_id) : stopBuildAgent(worker.ticket_id)),
|
|
4499
4773
|
});
|
|
4774
|
+
if (checkpointLineage) {
|
|
4775
|
+
const stoppedSequence = stopBuildSequence(checkpointLineage.ticket.id);
|
|
4776
|
+
emitUpdatedTickets(stoppedSequence.affectedTicketIds);
|
|
4777
|
+
}
|
|
4500
4778
|
for (const ticket of listDetailedBundleTickets(result.project.id, bundle.id)) {
|
|
4501
4779
|
io.emit('ticket:updated', ticket);
|
|
4502
4780
|
}
|
|
@@ -5581,7 +5859,7 @@ app.post('/projects', (req, res) => {
|
|
|
5581
5859
|
return res.status(400).json({ error: validation.error });
|
|
5582
5860
|
}
|
|
5583
5861
|
const projectCount = Number(db.prepare('SELECT COUNT(*) AS count FROM projects').get()?.count ?? 0);
|
|
5584
|
-
const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, commit_message_rules, 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;
|
|
5862
|
+
const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_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;
|
|
5585
5863
|
if (!repo_path) {
|
|
5586
5864
|
return res.status(400).json({ error: 'repo_path must be a non-empty string' });
|
|
5587
5865
|
}
|
|
@@ -5603,6 +5881,7 @@ app.post('/projects', (req, res) => {
|
|
|
5603
5881
|
run_services,
|
|
5604
5882
|
check_definitions,
|
|
5605
5883
|
required_check_definition_ids,
|
|
5884
|
+
pre_review_check_definition_ids,
|
|
5606
5885
|
test_commands,
|
|
5607
5886
|
run_ide,
|
|
5608
5887
|
preview_service_name,
|
|
@@ -5611,6 +5890,7 @@ app.post('/projects', (req, res) => {
|
|
|
5611
5890
|
helper_model,
|
|
5612
5891
|
helper_variant,
|
|
5613
5892
|
commit_message_rules,
|
|
5893
|
+
commit_after_each_ticket,
|
|
5614
5894
|
auto_park_stale_tickets,
|
|
5615
5895
|
memory_enabled,
|
|
5616
5896
|
scan_include_globs_json,
|
|
@@ -5623,8 +5903,8 @@ app.post('/projects', (req, res) => {
|
|
|
5623
5903
|
automation_review_severity,
|
|
5624
5904
|
automation_review_max_iterations
|
|
5625
5905
|
)
|
|
5626
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5627
|
-
`).run(id, name, normalizedRepoPath, run_setup, run_services, check_definitions, required_check_definition_ids ?? '[]', test_commands, run_ide ?? null, preview_service_name ?? null, preview_path ?? null, preview_capability_mode ?? null, helper_model ?? null, helper_variant ?? null, commit_message_rules ?? null, auto_park_stale_tickets ?? 0, memory_enabled ?? 0, scan_include_globs_json ?? null, scan_exclude_globs_json ?? null, worktree_sync ?? null, spec_aware_code_review_enabled ?? 0, automation_depth ?? 'manual', automation_review_fix_enabled ?? 0, automation_pause_on_open_questions ?? 0, automation_review_severity ?? 'medium', automation_review_max_iterations ?? 3);
|
|
5906
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5907
|
+
`).run(id, name, normalizedRepoPath, run_setup, run_services, check_definitions, required_check_definition_ids ?? '[]', pre_review_check_definition_ids ?? '[]', test_commands, run_ide ?? null, preview_service_name ?? null, preview_path ?? null, preview_capability_mode ?? null, helper_model ?? null, helper_variant ?? null, commit_message_rules ?? null, commit_after_each_ticket ?? 0, auto_park_stale_tickets ?? 0, memory_enabled ?? 0, scan_include_globs_json ?? null, scan_exclude_globs_json ?? null, worktree_sync ?? null, spec_aware_code_review_enabled ?? 0, automation_depth ?? 'manual', automation_review_fix_enabled ?? 0, automation_pause_on_open_questions ?? 0, automation_review_severity ?? 'medium', automation_review_max_iterations ?? 3);
|
|
5628
5908
|
replaceProjectLinks(id, linked_project_ids ?? []);
|
|
5629
5909
|
ensureProjectRootBundle(id);
|
|
5630
5910
|
if (projectCount === 0) {
|
|
@@ -6790,8 +7070,8 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
6790
7070
|
});
|
|
6791
7071
|
}
|
|
6792
7072
|
}
|
|
6793
|
-
const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_variant, commit_message_rules, 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;
|
|
6794
|
-
db.prepare(`
|
|
7073
|
+
const { name, repo_path, linked_project_ids, run_setup, run_services, check_definitions, required_check_definition_ids, pre_review_check_definition_ids, test_commands, run_ide, preview_service_name, preview_path, preview_capability_mode, helper_model, helper_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;
|
|
7074
|
+
const updateProject = db.prepare(`
|
|
6795
7075
|
UPDATE projects SET
|
|
6796
7076
|
name = ?,
|
|
6797
7077
|
repo_path = ?,
|
|
@@ -6799,6 +7079,7 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
6799
7079
|
run_services = ?,
|
|
6800
7080
|
check_definitions = ?,
|
|
6801
7081
|
required_check_definition_ids = ?,
|
|
7082
|
+
pre_review_check_definition_ids = ?,
|
|
6802
7083
|
test_commands = ?,
|
|
6803
7084
|
run_ide = ?,
|
|
6804
7085
|
preview_service_name = ?,
|
|
@@ -6807,6 +7088,7 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
6807
7088
|
helper_model = ?,
|
|
6808
7089
|
helper_variant = ?,
|
|
6809
7090
|
commit_message_rules = ?,
|
|
7091
|
+
commit_after_each_ticket = ?,
|
|
6810
7092
|
auto_park_stale_tickets = ?,
|
|
6811
7093
|
memory_enabled = ?,
|
|
6812
7094
|
scan_include_globs_json = ?,
|
|
@@ -6820,9 +7102,32 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
6820
7102
|
automation_review_max_iterations = ?,
|
|
6821
7103
|
updated_at = CURRENT_TIMESTAMP
|
|
6822
7104
|
WHERE id = ?
|
|
6823
|
-
`)
|
|
6824
|
-
|
|
6825
|
-
|
|
7105
|
+
`);
|
|
7106
|
+
const nextCheckDefinitions = hasOwn(validation.values, 'check_definitions') ? check_definitions ?? null : project.check_definitions;
|
|
7107
|
+
const nextRequiredCheckDefinitionIds = hasOwn(validation.values, 'required_check_definition_ids')
|
|
7108
|
+
? required_check_definition_ids ?? '[]'
|
|
7109
|
+
: project.required_check_definition_ids;
|
|
7110
|
+
const nextPreReviewCheckDefinitionIds = hasOwn(validation.values, 'pre_review_check_definition_ids')
|
|
7111
|
+
? pre_review_check_definition_ids ?? '[]'
|
|
7112
|
+
: project.pre_review_check_definition_ids;
|
|
7113
|
+
const updateResult = db.transaction(() => {
|
|
7114
|
+
const policyReferences = validateProjectRequiredCheckPolicyReferences({
|
|
7115
|
+
projectId: project.id,
|
|
7116
|
+
checkDefinitionsJson: nextCheckDefinitions,
|
|
7117
|
+
requiredCheckDefinitionIdsJson: nextRequiredCheckDefinitionIds,
|
|
7118
|
+
preReviewCheckDefinitionIdsJson: nextPreReviewCheckDefinitionIds,
|
|
7119
|
+
});
|
|
7120
|
+
if ('error' in policyReferences) {
|
|
7121
|
+
return policyReferences;
|
|
7122
|
+
}
|
|
7123
|
+
updateProject.run(name ?? project.name, repo_path ?? project.repo_path, hasOwn(validation.values, 'run_setup') ? run_setup : project.run_setup, hasOwn(validation.values, 'run_services') ? run_services : project.run_services, nextCheckDefinitions, nextRequiredCheckDefinitionIds, nextPreReviewCheckDefinitionIds, 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, 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);
|
|
7124
|
+
if (hasOwn(validation.values, 'linked_project_ids')) {
|
|
7125
|
+
replaceProjectLinks(project.id, linked_project_ids ?? []);
|
|
7126
|
+
}
|
|
7127
|
+
return { ok: true };
|
|
7128
|
+
})();
|
|
7129
|
+
if ('error' in updateResult) {
|
|
7130
|
+
return res.status(400).json({ error: updateResult.error });
|
|
6826
7131
|
}
|
|
6827
7132
|
const updated = db.prepare('SELECT * FROM projects WHERE id = ?').get(req.params.id);
|
|
6828
7133
|
res.json(serializeProject(updated ?? null));
|