@straiffi/archon 1.8.7 → 1.8.9
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-D4Qh96zr.js → ActivityView-gBeoYQdD.js} +1 -1
- package/dist/client/assets/{GitHubActionsDialog-Bg03OmVv.js → GitHubActionsDialog-fc1Vwafm.js} +1 -1
- package/dist/client/assets/RepositoryGraphDialog-DCOjwUR3.js +1 -0
- package/dist/client/assets/VerificationDialog-CIObj1Rw.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-2lxabjSl.js → architectureDiagram-3BPJPVTR-B1tJZe1S.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-C80HvJmb.js → blockDiagram-GPEHLZMM-D_90AQ2Z.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BM3k_lKz.js → c4Diagram-AAUBKEIU-DSyJfqly.js} +1 -1
- package/dist/client/assets/channel-DFw1f2Rh.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-BTk3lX07.js → chunk-2J33WTMH-B9RStQGj.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-DAxdBZ_4.js → chunk-3OPIFGDE-CHKuJYq0.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-BYm9s62a.js → chunk-5ZQYHXKU-Cznw7LTJ.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-iVUM8xuV.js → chunk-727SXJPM-ix6OeZwJ.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DVM7riMJ.js → chunk-AQP2D5EJ-DrPJIcE7.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-_D1FzP9B.js → chunk-CSCIHK7Q-BSEHTnBR.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-D3XouAHf.js → chunk-KSCS5N6A-MdDdaLn8.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-B7NYWgT4.js → chunk-L5ZTLDWV-D_5xeDG1.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-Dgkkbb6A.js → chunk-LZXEDZCA-Bz8_Fyt2.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-CzO1oVCi.js → chunk-ND2GUHAM-DCINKlk8.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-re0VVZne.js → chunk-NZK2D7GU-rGPgryKx.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-BwsS59iy.js → chunk-O5CBEL6O-BHB8UIYA.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-CLyh-xCA.js → chunk-WU5MYG2G-Bz5BJWjF.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-Dt0kmMzQ.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BuxhA4Gw.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-x71fYlqQ.js → dagre-BM42HDAG-B4TXLkOG.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-CMdwzuYj.js → diagram-2AECGRRQ-CxMup1wq.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-B3l6I4qJ.js → diagram-5GNKFQAL-CTfP_wnS.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BNhypLBW.js → diagram-KO2AKTUF-31NKNt4r.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CmrhbiDt.js → diagram-LMA3HP47-Cxo7yvjc.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CRobDMLl.js → diagram-OG6HWLK6-ChgSAMLv.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CqO7K0TS.js → erDiagram-TEJ5UH35-u6msywL_.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-CuLTJZU0.js → flowDiagram-I6XJVG4X-CimeXkDN.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-Bm7v1eRG.js → ganttDiagram-6RSMTGT7-DOu5sDUI.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CNHZr-5i.js → gitGraphDiagram-PVQCEYII-zIToibUf.js} +1 -1
- package/dist/client/assets/index-C-VHd0Pr.js +274 -0
- package/dist/client/assets/index-D3xlEyeM.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-z27pUr2X.js → infoDiagram-5YYISTIA-CAtWGGJI.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CDocZ0jf.js → ishikawaDiagram-YF4QCWOH-7N-C7DEt.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CgP31lsU.js → journeyDiagram-JHISSGLW-D7VUypFG.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-DxTm1_fc.js → kanban-definition-UN3LZRKU-AmbDmzSD.js} +1 -1
- package/dist/client/assets/{line-hrZ7m44_.js → line-qf4UZ8vh.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-BThJAIK-.js → mermaid-parser.core-BssCd1kF.js} +1 -1
- package/dist/client/assets/{mermaid.core-CfVyP_kK.js → mermaid.core-DzeMqg9Y.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-CuISnLgW.js → mindmap-definition-RKZ34NQL-dEnNQcDm.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DnWAdd44.js → pieDiagram-4H26LBE5-VjMue0a-.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Cb-RVl5A.js → quadrantDiagram-W4KKPZXB-DQFdm-0f.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DrXg_gCS.js → requirementDiagram-4Y6WPE33-CHIaXlsy.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DzZjp_ZP.js → sankeyDiagram-5OEKKPKP-D-kzGaKb.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-CQJ3PhQD.js → sequenceDiagram-3UESZ5HK-CiDmlD8k.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-B16j9pg1.js → stateDiagram-AJRCARHV-BKlnnFdT.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DhJxc4em.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-bUG3mZQt.js → timeline-definition-PNZ67QCA-D-BK07Un.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DALCJcZD.js → vennDiagram-CIIHVFJN-CB9_GqSx.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DPQd3l9A.js → wardleyDiagram-YWT4CUSO-BEuNfyLT.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-BIv1FqXG.js → xychartDiagram-2RQKCTM6-CSS5WMrZ.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +481 -27
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +113 -54
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/activeAutomationChild.js +1 -0
- package/dist/server/lib/activeAutomationChild.js.map +1 -1
- package/dist/server/lib/agent.js +127 -15
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/agentRuns.js +12 -0
- package/dist/server/lib/agentRuns.js.map +1 -1
- package/dist/server/lib/agentSpawnPermits.js +37 -0
- package/dist/server/lib/agentSpawnPermits.js.map +1 -0
- package/dist/server/lib/automationCheckGate.js +9 -1
- package/dist/server/lib/automationCheckGate.js.map +1 -1
- package/dist/server/lib/automationProgression.js +19 -5
- package/dist/server/lib/automationProgression.js.map +1 -1
- package/dist/server/lib/automationReviewGate.js +1 -0
- package/dist/server/lib/automationReviewGate.js.map +1 -1
- package/dist/server/lib/buildCompletionContinuation.js +144 -4
- package/dist/server/lib/buildCompletionContinuation.js.map +1 -1
- package/dist/server/lib/buildSequences.js +13 -1
- package/dist/server/lib/buildSequences.js.map +1 -1
- package/dist/server/lib/bundleActivity.js +19 -0
- package/dist/server/lib/bundleActivity.js.map +1 -1
- package/dist/server/lib/chatOperations.js +81 -2
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/checkAutoFix.js +604 -0
- package/dist/server/lib/checkAutoFix.js.map +1 -0
- package/dist/server/lib/checkAutoFixDetails.js +83 -0
- package/dist/server/lib/checkAutoFixDetails.js.map +1 -0
- package/dist/server/lib/checkAutoFixPolicy.js +59 -0
- package/dist/server/lib/checkAutoFixPolicy.js.map +1 -0
- package/dist/server/lib/checkRepair.js +149 -54
- package/dist/server/lib/checkRepair.js.map +1 -1
- package/dist/server/lib/checkRepairDispatch.js +91 -0
- package/dist/server/lib/checkRepairDispatch.js.map +1 -0
- package/dist/server/lib/checkRepairEvidence.js +84 -0
- package/dist/server/lib/checkRepairEvidence.js.map +1 -0
- package/dist/server/lib/checkRepairParent.js +21 -0
- package/dist/server/lib/checkRepairParent.js.map +1 -0
- package/dist/server/lib/checkRepairReconciliation.js +14 -5
- package/dist/server/lib/checkRepairReconciliation.js.map +1 -1
- package/dist/server/lib/checkRunner.js +27 -8
- package/dist/server/lib/checkRunner.js.map +1 -1
- package/dist/server/lib/checkRuns.js +63 -4
- package/dist/server/lib/checkRuns.js.map +1 -1
- package/dist/server/lib/executionReconciliation.js +387 -8
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRuns.js +24 -1
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/git.js +302 -11
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/integrations/github.js +138 -65
- package/dist/server/lib/integrations/github.js.map +1 -1
- package/dist/server/lib/integrations/importedIssueImages.js +10 -15
- package/dist/server/lib/integrations/importedIssueImages.js.map +1 -1
- package/dist/server/lib/postBuildCheckRuns.js +200 -5
- package/dist/server/lib/postBuildCheckRuns.js.map +1 -1
- package/dist/server/lib/postBuildChecks.js +83 -13
- package/dist/server/lib/postBuildChecks.js.map +1 -1
- package/dist/server/lib/projects.js +25 -1
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/queue.js +9 -3
- package/dist/server/lib/queue.js.map +1 -1
- package/dist/server/lib/repositoryGraphQueries.js +5 -3
- package/dist/server/lib/repositoryGraphQueries.js.map +1 -1
- package/dist/server/lib/repositoryGraphScan.js +13 -2
- package/dist/server/lib/repositoryGraphScan.js.map +1 -1
- package/dist/server/lib/repositoryGraphStore.js +61 -1
- package/dist/server/lib/repositoryGraphStore.js.map +1 -1
- package/dist/server/lib/specArtifact.js +10 -1
- package/dist/server/lib/specArtifact.js.map +1 -1
- package/dist/server/lib/specDraft.js +10 -2
- package/dist/server/lib/specDraft.js.map +1 -1
- package/dist/server/lib/specExport.js +70 -6
- package/dist/server/lib/specExport.js.map +1 -1
- package/dist/server/lib/specFormatting.js +3 -2
- package/dist/server/lib/specFormatting.js.map +1 -1
- package/dist/server/lib/specRepositoryEvidenceFormatting.js +75 -0
- package/dist/server/lib/specRepositoryEvidenceFormatting.js.map +1 -0
- package/dist/server/lib/specRepositoryImpact.js +447 -0
- package/dist/server/lib/specRepositoryImpact.js.map +1 -0
- package/dist/server/lib/specRepositoryImpactLimits.js +6 -0
- package/dist/server/lib/specRepositoryImpactLimits.js.map +1 -0
- package/dist/server/lib/specReviewContext.js +15 -5
- package/dist/server/lib/specReviewContext.js.map +1 -1
- package/dist/server/lib/specReviewValidation.js +1 -1
- package/dist/server/lib/specReviewValidation.js.map +1 -1
- package/dist/server/lib/specSections.js +28 -3
- package/dist/server/lib/specSections.js.map +1 -1
- package/dist/server/lib/specSnapshotEvidence.js +162 -0
- package/dist/server/lib/specSnapshotEvidence.js.map +1 -0
- package/dist/server/lib/specSnapshotEvidenceSerialization.js +202 -0
- package/dist/server/lib/specSnapshotEvidenceSerialization.js.map +1 -0
- package/dist/server/lib/specs.js +31 -5
- package/dist/server/lib/specs.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +3 -1
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +16 -12
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/ticketRunOperations.js +13 -1
- package/dist/server/lib/ticketRunOperations.js.map +1 -1
- package/dist/server/lib/ticketWorkflowOperations.js +5 -2
- package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
- package/dist/server/lib/types.js +1 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/workers/build.js +46 -148
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +141 -31
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +210 -48
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/specReview.js +17 -4
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +127 -22
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/RepositoryGraphDialog-CS_hOqPw.js +0 -1
- package/dist/client/assets/VerificationDialog-BYH-Ek8n.js +0 -4
- package/dist/client/assets/channel-HjENOCZ0.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DnhdaVrK.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C-BjeSGJ.js +0 -1
- package/dist/client/assets/index-Bs5SQZhz.css +0 -2
- package/dist/client/assets/index-LGNsdNYM.js +0 -274
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-vNiFfHwm.js +0 -1
package/dist/server/index.js
CHANGED
|
@@ -12,6 +12,8 @@ import { pruneAllRepositoryGraphScans } from './lib/repositoryGraphRetention.js'
|
|
|
12
12
|
import { registerRepositoryGraphRoutes } from './lib/repositoryGraphRoutes.js';
|
|
13
13
|
import { deleteChatSession, getChatSession, listChatSessions } from './lib/chats.js';
|
|
14
14
|
import { deleteSpecSession, getCreatedTicketIdsForSnapshot, getSpecSession, getSpecSnapshot, listSpecSessions } from './lib/specs.js';
|
|
15
|
+
import { getSpecSnapshotRepositoryEvidenceFreshness } from './lib/specSnapshotEvidence.js';
|
|
16
|
+
import { projectSpecSnapshotForActionPrompt } from './lib/specRepositoryEvidenceFormatting.js';
|
|
15
17
|
import { createChatAttachment, createSpecAttachment, getAttachmentById, deleteChatAttachment, deleteProjectAttachments, deleteSpecSessionAttachment, getChatAttachmentForSession, getChatAttachmentLinkedMessageId, getSpecAttachmentForSession, getSpecAttachmentLinkedMessageId, MAX_CHAT_ATTACHMENTS_PER_TURN, MAX_CHAT_ATTACHMENT_SIZE_BYTES, MAX_SPEC_ATTACHMENTS_PER_TURN, MAX_SPEC_ATTACHMENT_SIZE_BYTES, readChatAttachmentContent, readSpecAttachmentContent, validateImageAttachment, } from './lib/attachments.js';
|
|
16
18
|
import { createProjectChatSession, resolveChatTool, resolveProjectChatPlanQuestionSet, stopProjectChatSessionResponse, submitProjectChatSessionMessage, updateProjectChatSessionMode, } from './lib/chatOperations.js';
|
|
17
19
|
import { createProjectSpecSession, deleteProjectSpecSession, resolveProjectSpecPlanQuestionSet, stopProjectSpecSessionResponse, submitProjectSpecSessionMessage, updateProjectSpecSessionMode, } from './lib/specOperations.js';
|
|
@@ -21,7 +23,7 @@ import { resolveSessionTargetForExecution } from './lib/sessionTargets.js';
|
|
|
21
23
|
import { createChatMessage, getChatMessage, updateChatMessageContent } from './lib/chatMessages.js';
|
|
22
24
|
import { attachChatTicketProposalsToMessageContent } from './lib/chatTicketProposals.js';
|
|
23
25
|
import { createCorsOriginResolver, parseCorsOrigins } from './lib/cors.js';
|
|
24
|
-
import { abortGitOperation, branchExistsLocally, commitGitChanges, createWorktreeAsync, deleteWorktree, getBundleReviewDiffForCwd,
|
|
26
|
+
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';
|
|
25
27
|
import config from './lib/config.js';
|
|
26
28
|
import { autoConfigProject, ProjectAutoConfigError } from './lib/projectAutoConfig.js';
|
|
27
29
|
import { analyzeRepoPath, createInitialCommit, ensureInitialCommitForWorktrees, initializeGitRepo, isInitialCommitRequiredError, } from './lib/projectRepos.js';
|
|
@@ -88,7 +90,8 @@ import { getActiveRunStatus, getActiveRunStatusForProject, getPreviewStatusForPr
|
|
|
88
90
|
import { clearAllTestSessions, createTestSession, deleteTestSession, discoverTestsForSession, doesTestFileExistForSession, getTestSession, isTestSelectionSupported, startTestSessionRun, stopTestSessionRun } from './lib/testSessions.js';
|
|
89
91
|
import { closeCheckRunnerAdmissions, getCheckBatchAttempts, openCheckRunnerAdmissions, rerunCheckBatchAndSchedule, shutdownCheckRunner, startCheckBatch, stopCheckBatch } from './lib/checkRunner.js';
|
|
90
92
|
import { CheckRepairError, getCheckRepairCandidateState, getCheckRepairDetails, getLatestCheckRepairForBatch, retryCheckRepair, startCheckRepair, stopCheckRepair } from './lib/checkRepair.js';
|
|
91
|
-
import {
|
|
93
|
+
import { getCheckAutoFixDetails, stopCheckAutoFix } from './lib/checkAutoFix.js';
|
|
94
|
+
import { findActiveCheckAutoFixForTarget, findActiveCheckBatchForTarget, getCheckAttemptDetails, getCheckBatchDetails, hasActiveProjectCheckBatch, isCheckAttemptCurrent, resolveCheckBatchRerunEligibility } from './lib/checkRuns.js';
|
|
92
95
|
import { getCheckAttemptDiagnosticResponse, getCheckBatchDiagnosticResponse } from './lib/checkDiagnostics.js';
|
|
93
96
|
import { getCheckDefinitionFingerprint } from './lib/checkDefinitions.js';
|
|
94
97
|
import { getCheckGateEvaluation, hydrateCheckGatePresentApplicability } from './lib/checkGateEvaluations.js';
|
|
@@ -113,7 +116,7 @@ import { parseIncomingExternalSource } from './lib/externalSource.js';
|
|
|
113
116
|
import { materializeTicketsWithDependencies } from './lib/ticketBatch.js';
|
|
114
117
|
import { IMPLEMENTATION_READY_DESCRIPTION_SECTION_HEADINGS } from './lib/ticketDescriptionContract.js';
|
|
115
118
|
import { buildImplementationResourcesAppendix, buildSpecImplementationDraft, buildVisualizationAppendix } from './lib/specDraft.js';
|
|
116
|
-
import { exportSpecToDocs, checkSpecExportCollision } from './lib/specExport.js';
|
|
119
|
+
import { exportSpecToDocs, checkSpecExportCollision, SpecExportCollisionError } from './lib/specExport.js';
|
|
117
120
|
import { createTicketDependency, deleteTicketDependenciesForTicket, deleteTicketDependency, getTicketDependency, isTicketBuildComplete, isTicketRunSetupReady, listTicketDependencies, validateCreateTicketDependency, } from './lib/ticketDependencies.js';
|
|
118
121
|
import { startBuild } from './workers/build.js';
|
|
119
122
|
import { expandPlanningTicketOutline, generatePlanningTicketOutline, generatePlanText, prepareLinkedPlanningResearch, startPlan, stopAllPlanAgents, } from './workers/plan.js';
|
|
@@ -425,11 +428,19 @@ const buildExecutionRunDetailResponse = async (project, run) => {
|
|
|
425
428
|
retry_eligibility: retryEligibility,
|
|
426
429
|
action_kind: null,
|
|
427
430
|
}
|
|
428
|
-
: run.kind === '
|
|
429
|
-
? {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
:
|
|
431
|
+
: run.kind === 'check_auto_fix'
|
|
432
|
+
? {
|
|
433
|
+
kind: 'check_auto_fix',
|
|
434
|
+
available: true,
|
|
435
|
+
check_auto_fix: getCheckAutoFixDetails(project.id, run.id),
|
|
436
|
+
retry_eligibility: retryEligibility,
|
|
437
|
+
action_kind: null,
|
|
438
|
+
}
|
|
439
|
+
: run.kind === 'github_actions'
|
|
440
|
+
? { ...serializeGitHubActionsExecutionDetail(getGitHubActionsExecutionDetails(project.id, run.id)), retry_eligibility: retryEligibility }
|
|
441
|
+
: ['automation_commit', 'automation_push', 'automation_pull_request'].includes(run.kind)
|
|
442
|
+
? { kind: run.kind, available: true, automation_stage: getAutomationStageDetails(project.id, run.id), retry_eligibility: retryEligibility }
|
|
443
|
+
: { kind: run.kind, available: true, retry_eligibility: retryEligibility };
|
|
433
444
|
const artifacts = loadExecutionArtifactSummariesForRuns(project.id, [run.id], MAX_ARTIFACTS_PER_RUN).get(run.id)
|
|
434
445
|
?? { artifacts: [], artifact_count: 0 };
|
|
435
446
|
return {
|
|
@@ -490,7 +501,8 @@ const getBundlePlanBlockerError = () => {
|
|
|
490
501
|
return 'AI planning is blocked because this bundle worktree is currently being modified.';
|
|
491
502
|
};
|
|
492
503
|
const hasActiveBundleCheckWork = (projectId, bundleId) => Boolean(getActiveBundleRepairBlocker(bundleId)
|
|
493
|
-
|| findActiveCheckBatchForTarget(projectId, 'bundle', bundleId)
|
|
504
|
+
|| findActiveCheckBatchForTarget(projectId, 'bundle', bundleId)
|
|
505
|
+
|| findActiveCheckAutoFixForTarget(projectId, 'bundle', bundleId));
|
|
494
506
|
const deleteTicketRecord = async (ticket) => {
|
|
495
507
|
if (ticket.project_id
|
|
496
508
|
&& ticket.worktree_bundle_id
|
|
@@ -1446,8 +1458,8 @@ const bundlePullRequestDiscoveryErrorTimestamps = new Map();
|
|
|
1446
1458
|
const bundlePullRequestSyncInFlight = new Map();
|
|
1447
1459
|
const bundlePullRequestSyncErrorTimestamps = new Map();
|
|
1448
1460
|
const getBundlePullRequestDiscoveryKey = (projectId, bundleId) => `${projectId}:${bundleId}`;
|
|
1449
|
-
const startPassiveGitHubWork = (label, callback) => {
|
|
1450
|
-
setImmediate(() => {
|
|
1461
|
+
const startPassiveGitHubWork = (response, label, callback) => {
|
|
1462
|
+
const start = () => setImmediate(() => {
|
|
1451
1463
|
try {
|
|
1452
1464
|
callback();
|
|
1453
1465
|
}
|
|
@@ -1455,6 +1467,11 @@ const startPassiveGitHubWork = (label, callback) => {
|
|
|
1455
1467
|
console.warn(`[integrations] github passive work failed ${label}`, error);
|
|
1456
1468
|
}
|
|
1457
1469
|
});
|
|
1470
|
+
if (response.writableFinished) {
|
|
1471
|
+
start();
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
response.once('finish', start);
|
|
1458
1475
|
};
|
|
1459
1476
|
const isBundlePullRequestDiscoveryCoolingDown = (timestamps, key, cooldownMs) => {
|
|
1460
1477
|
const lastAttemptAt = timestamps.get(key);
|
|
@@ -2019,7 +2036,7 @@ const buildBundleTickets = (projectId, bundleId, broadcaster) => {
|
|
|
2019
2036
|
value: details,
|
|
2020
2037
|
};
|
|
2021
2038
|
};
|
|
2022
|
-
const getCurrentReviewWorkspaceSignature = (ticket) => {
|
|
2039
|
+
const getCurrentReviewWorkspaceSignature = async (ticket) => {
|
|
2023
2040
|
if (!ticket) {
|
|
2024
2041
|
return null;
|
|
2025
2042
|
}
|
|
@@ -2027,9 +2044,9 @@ const getCurrentReviewWorkspaceSignature = (ticket) => {
|
|
|
2027
2044
|
if ('error' in workspace) {
|
|
2028
2045
|
return null;
|
|
2029
2046
|
}
|
|
2030
|
-
return
|
|
2047
|
+
return (await getGitStatusAsync(workspace.cwd, workspace.branch, workspace.project)).workspace_signature ?? null;
|
|
2031
2048
|
};
|
|
2032
|
-
const getCurrentReviewDiffSignature = (ticket) => {
|
|
2049
|
+
const getCurrentReviewDiffSignature = async (ticket) => {
|
|
2033
2050
|
if (!ticket) {
|
|
2034
2051
|
return null;
|
|
2035
2052
|
}
|
|
@@ -2037,9 +2054,9 @@ const getCurrentReviewDiffSignature = (ticket) => {
|
|
|
2037
2054
|
if ('error' in workspace) {
|
|
2038
2055
|
return null;
|
|
2039
2056
|
}
|
|
2040
|
-
return computeDiffSignature(
|
|
2057
|
+
return computeDiffSignature(await getGitUnifiedDiffAsync(workspace.cwd));
|
|
2041
2058
|
};
|
|
2042
|
-
const getBundleReviewFindings = (projectId, bundleId) => {
|
|
2059
|
+
const getBundleReviewFindings = async (projectId, bundleId) => {
|
|
2043
2060
|
const bundle = getBundle(bundleId, projectId);
|
|
2044
2061
|
if (!bundle) {
|
|
2045
2062
|
return null;
|
|
@@ -2070,13 +2087,13 @@ const getBundleReviewFindings = (projectId, bundleId) => {
|
|
|
2070
2087
|
return buildReviewFindingsResponse({
|
|
2071
2088
|
context,
|
|
2072
2089
|
isContextRunning: tickets.some(ticket => ticket.agent_status === 'running'),
|
|
2073
|
-
currentWorkspaceSignature: getCurrentReviewWorkspaceSignature(representativeTicket),
|
|
2090
|
+
currentWorkspaceSignature: await getCurrentReviewWorkspaceSignature(representativeTicket),
|
|
2074
2091
|
currentDiffSignature: latestReviewRun && latestReviewRun.workspace_signature === null
|
|
2075
|
-
? getCurrentReviewDiffSignature(representativeTicket)
|
|
2092
|
+
? await getCurrentReviewDiffSignature(representativeTicket)
|
|
2076
2093
|
: null,
|
|
2077
2094
|
});
|
|
2078
2095
|
};
|
|
2079
|
-
const getTicketReviewFindings = (ticketId) => {
|
|
2096
|
+
const getTicketReviewFindings = async (ticketId) => {
|
|
2080
2097
|
const ticket = getTicketRouteContext(ticketId);
|
|
2081
2098
|
if (!ticket) {
|
|
2082
2099
|
return null;
|
|
@@ -2090,9 +2107,9 @@ const getTicketReviewFindings = (ticketId) => {
|
|
|
2090
2107
|
return buildReviewFindingsResponse({
|
|
2091
2108
|
context,
|
|
2092
2109
|
isContextRunning: ticket.agent_status === 'running',
|
|
2093
|
-
currentWorkspaceSignature: getCurrentReviewWorkspaceSignature(ticket),
|
|
2110
|
+
currentWorkspaceSignature: await getCurrentReviewWorkspaceSignature(ticket),
|
|
2094
2111
|
currentDiffSignature: latestReviewRun && latestReviewRun.workspace_signature === null
|
|
2095
|
-
? getCurrentReviewDiffSignature(ticket)
|
|
2112
|
+
? await getCurrentReviewDiffSignature(ticket)
|
|
2096
2113
|
: null,
|
|
2097
2114
|
});
|
|
2098
2115
|
};
|
|
@@ -2733,13 +2750,14 @@ app.post('/projects/:id/chat-sessions/:sessionId/stop', async (req, res) => {
|
|
|
2733
2750
|
const result = await stopProjectChatSessionResponse({
|
|
2734
2751
|
projectId: req.params.id,
|
|
2735
2752
|
chatSessionId: req.params.sessionId,
|
|
2753
|
+
broadcaster: io,
|
|
2736
2754
|
});
|
|
2737
2755
|
if (!result.ok) {
|
|
2738
2756
|
return res.status(result.status).json({ error: result.error });
|
|
2739
2757
|
}
|
|
2740
2758
|
return res.status(result.status).json(result.value);
|
|
2741
2759
|
});
|
|
2742
|
-
app.get('/projects/:id/chat-sessions/:sessionId/diff', (req, res) => {
|
|
2760
|
+
app.get('/projects/:id/chat-sessions/:sessionId/diff', async (req, res) => {
|
|
2743
2761
|
const project = getProjectById(req.params.id);
|
|
2744
2762
|
if (!project) {
|
|
2745
2763
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -2752,14 +2770,14 @@ app.get('/projects/:id/chat-sessions/:sessionId/diff', (req, res) => {
|
|
|
2752
2770
|
if (!workspace.target_available || !workspace.cwd) {
|
|
2753
2771
|
return res.status(409).json({ error: workspace.target_unavailable_reason ?? 'Chat target is unavailable.' });
|
|
2754
2772
|
}
|
|
2755
|
-
const diffData =
|
|
2773
|
+
const diffData = await getGitDiffDataAsync(workspace.cwd);
|
|
2756
2774
|
return res.json({
|
|
2757
2775
|
stats: summarizeTicketDiffFiles(diffData.files),
|
|
2758
2776
|
files: diffData.files,
|
|
2759
2777
|
diff: diffData.diff,
|
|
2760
2778
|
});
|
|
2761
2779
|
});
|
|
2762
|
-
app.get('/projects/:id/chat-sessions/:sessionId/git-status', (req, res) => {
|
|
2780
|
+
app.get('/projects/:id/chat-sessions/:sessionId/git-status', async (req, res) => {
|
|
2763
2781
|
const project = getProjectById(req.params.id);
|
|
2764
2782
|
if (!project) {
|
|
2765
2783
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -2772,7 +2790,7 @@ app.get('/projects/:id/chat-sessions/:sessionId/git-status', (req, res) => {
|
|
|
2772
2790
|
if (!workspace.target_available || !workspace.cwd) {
|
|
2773
2791
|
return res.status(409).json({ error: workspace.target_unavailable_reason ?? 'Chat target is unavailable.' });
|
|
2774
2792
|
}
|
|
2775
|
-
return res.json(
|
|
2793
|
+
return res.json(await getGitStatusAsync(workspace.cwd, workspace.branch, project));
|
|
2776
2794
|
});
|
|
2777
2795
|
app.delete('/projects/:id/chat-sessions/:sessionId', (req, res) => {
|
|
2778
2796
|
const project = getProjectById(req.params.id);
|
|
@@ -3073,7 +3091,7 @@ app.delete('/projects/:id/spec-sessions/:sessionId', (req, res) => {
|
|
|
3073
3091
|
});
|
|
3074
3092
|
return res.json({ ok: true });
|
|
3075
3093
|
});
|
|
3076
|
-
app.get('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId', (req, res) => {
|
|
3094
|
+
app.get('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId', async (req, res) => {
|
|
3077
3095
|
const project = getProjectById(req.params.id);
|
|
3078
3096
|
if (!project) {
|
|
3079
3097
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -3091,6 +3109,7 @@ app.get('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId', (req, re
|
|
|
3091
3109
|
}
|
|
3092
3110
|
return res.json({
|
|
3093
3111
|
...snapshot,
|
|
3112
|
+
repository_evidence_freshness: await getSpecSnapshotRepositoryEvidenceFreshness(project, snapshot.repository_evidence),
|
|
3094
3113
|
created_ticket_ids: getCreatedTicketIdsForSnapshot(snapshot.id, project.id),
|
|
3095
3114
|
});
|
|
3096
3115
|
});
|
|
@@ -3190,7 +3209,7 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/create-ti
|
|
|
3190
3209
|
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to create tickets from the spec snapshot.' });
|
|
3191
3210
|
}
|
|
3192
3211
|
});
|
|
3193
|
-
app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/implement-in-chat', (req, res) => {
|
|
3212
|
+
app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/implement-in-chat', async (req, res) => {
|
|
3194
3213
|
const project = getProjectById(req.params.id);
|
|
3195
3214
|
if (!project) {
|
|
3196
3215
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -3207,14 +3226,20 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/implement
|
|
|
3207
3226
|
if (!targetResult.ok) {
|
|
3208
3227
|
return res.status(409).json({ error: targetResult.error });
|
|
3209
3228
|
}
|
|
3210
|
-
const
|
|
3229
|
+
const repositoryEvidenceFreshness = await getSpecSnapshotRepositoryEvidenceFreshness(project, snapshot.repository_evidence, { uncached: true });
|
|
3230
|
+
const promptSnapshot = projectSpecSnapshotForActionPrompt(snapshot, repositoryEvidenceFreshness);
|
|
3231
|
+
const draftText = buildSpecImplementationDraft({
|
|
3232
|
+
snapshot: promptSnapshot,
|
|
3233
|
+
specSession,
|
|
3234
|
+
repositoryEvidenceFreshness,
|
|
3235
|
+
});
|
|
3211
3236
|
return res.status(200).json({
|
|
3212
3237
|
draft_text: draftText,
|
|
3213
3238
|
spec_session_id: specSession.id,
|
|
3214
3239
|
spec_snapshot_id: snapshot.id,
|
|
3215
3240
|
});
|
|
3216
3241
|
});
|
|
3217
|
-
app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/export', (req, res) => {
|
|
3242
|
+
app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/export', async (req, res) => {
|
|
3218
3243
|
const project = getProjectById(req.params.id);
|
|
3219
3244
|
if (!project) {
|
|
3220
3245
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -3243,10 +3268,14 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/export',
|
|
|
3243
3268
|
conflicting_path: collision,
|
|
3244
3269
|
});
|
|
3245
3270
|
}
|
|
3271
|
+
const repositoryEvidenceFreshness = await getSpecSnapshotRepositoryEvidenceFreshness(project, snapshot.repository_evidence, { uncached: true });
|
|
3272
|
+
const exportSnapshot = projectSpecSnapshotForActionPrompt(snapshot, repositoryEvidenceFreshness);
|
|
3246
3273
|
const result = exportSpecToDocs({
|
|
3247
|
-
snapshot,
|
|
3274
|
+
snapshot: exportSnapshot,
|
|
3248
3275
|
specSession,
|
|
3249
3276
|
repoPath: targetResult.target.cwd,
|
|
3277
|
+
repositoryEvidenceFreshness,
|
|
3278
|
+
overwrite,
|
|
3250
3279
|
});
|
|
3251
3280
|
return res.status(201).json({
|
|
3252
3281
|
path: result.filePath,
|
|
@@ -3254,6 +3283,12 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/export',
|
|
|
3254
3283
|
});
|
|
3255
3284
|
}
|
|
3256
3285
|
catch (error) {
|
|
3286
|
+
if (error instanceof SpecExportCollisionError) {
|
|
3287
|
+
return res.status(409).json({
|
|
3288
|
+
error: error.message,
|
|
3289
|
+
conflicting_path: error.filePath,
|
|
3290
|
+
});
|
|
3291
|
+
}
|
|
3257
3292
|
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to export the spec snapshot.' });
|
|
3258
3293
|
}
|
|
3259
3294
|
});
|
|
@@ -3353,14 +3388,14 @@ app.get('/tickets/:id', async (req, res) => {
|
|
|
3353
3388
|
res.json(ticket);
|
|
3354
3389
|
if (passivePullRequestContext) {
|
|
3355
3390
|
const { project, bundle } = passivePullRequestContext;
|
|
3356
|
-
startPassiveGitHubWork('ticket-open-pr-sync', () => {
|
|
3391
|
+
startPassiveGitHubWork(res, 'ticket-open-pr-sync', () => {
|
|
3357
3392
|
startTrackedBundlePullRequestSyncIfNeeded(project, bundle);
|
|
3358
3393
|
startBundlePullRequestDiscoveryIfNeeded(project, bundle);
|
|
3359
3394
|
});
|
|
3360
3395
|
}
|
|
3361
3396
|
return;
|
|
3362
3397
|
});
|
|
3363
|
-
app.get('/tickets/:id/review-findings', (req, res) => {
|
|
3398
|
+
app.get('/tickets/:id/review-findings', async (req, res) => {
|
|
3364
3399
|
const ticket = getTicketRouteContext(req.params.id);
|
|
3365
3400
|
if (!ticket) {
|
|
3366
3401
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -3368,7 +3403,7 @@ app.get('/tickets/:id/review-findings', (req, res) => {
|
|
|
3368
3403
|
if (!matchesTicketProjectContext(ticket, req)) {
|
|
3369
3404
|
return res.status(404).json({ error: 'Not found' });
|
|
3370
3405
|
}
|
|
3371
|
-
const response = getTicketReviewFindings(ticket.id);
|
|
3406
|
+
const response = await getTicketReviewFindings(ticket.id);
|
|
3372
3407
|
if (!response) {
|
|
3373
3408
|
return res.status(404).json({ error: 'Not found' });
|
|
3374
3409
|
}
|
|
@@ -3384,7 +3419,7 @@ app.get('/tickets/:id/agent-runs', (req, res) => {
|
|
|
3384
3419
|
}
|
|
3385
3420
|
return res.json({ runs: listAgentRunsForParent('ticket', ticket.id) });
|
|
3386
3421
|
});
|
|
3387
|
-
app.get('/tickets/:id/diff', (req, res) => {
|
|
3422
|
+
app.get('/tickets/:id/diff', async (req, res) => {
|
|
3388
3423
|
const ticket = getTicketRouteContext(req.params.id);
|
|
3389
3424
|
if (!ticket) {
|
|
3390
3425
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -3397,7 +3432,7 @@ app.get('/tickets/:id/diff', (req, res) => {
|
|
|
3397
3432
|
const { status, error } = workspace;
|
|
3398
3433
|
return res.status(status).json({ error });
|
|
3399
3434
|
}
|
|
3400
|
-
const diffData =
|
|
3435
|
+
const diffData = await getGitDiffDataAsync(workspace.cwd);
|
|
3401
3436
|
return res.json({
|
|
3402
3437
|
stats: summarizeTicketDiffFiles(diffData.files),
|
|
3403
3438
|
files: diffData.files,
|
|
@@ -3418,7 +3453,7 @@ app.get('/tickets/:id/committed-diff', (req, res) => {
|
|
|
3418
3453
|
}
|
|
3419
3454
|
return sendUnpushedCommitDiff(res, workspace, getCommitHashQuery(req));
|
|
3420
3455
|
});
|
|
3421
|
-
app.get('/tickets/:id/git-status', (req, res) => {
|
|
3456
|
+
app.get('/tickets/:id/git-status', async (req, res) => {
|
|
3422
3457
|
const ticket = getTicketRouteContext(req.params.id);
|
|
3423
3458
|
if (!ticket) {
|
|
3424
3459
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -3431,9 +3466,9 @@ app.get('/tickets/:id/git-status', (req, res) => {
|
|
|
3431
3466
|
return res.status(workspace.status).json({ error: workspace.error });
|
|
3432
3467
|
}
|
|
3433
3468
|
const refreshRemote = req.query.refresh_remote === 'true';
|
|
3434
|
-
return res.json(
|
|
3469
|
+
return res.json(await getGitStatusAsync(workspace.cwd, workspace.branch, workspace.project, { refreshRemote }));
|
|
3435
3470
|
});
|
|
3436
|
-
app.get('/tickets/:id/git-commits', (req, res) => {
|
|
3471
|
+
app.get('/tickets/:id/git-commits', async (req, res) => {
|
|
3437
3472
|
const ticket = getTicketRouteContext(req.params.id);
|
|
3438
3473
|
if (!ticket) {
|
|
3439
3474
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -3445,7 +3480,7 @@ app.get('/tickets/:id/git-commits', (req, res) => {
|
|
|
3445
3480
|
if ('error' in workspace) {
|
|
3446
3481
|
return res.status(workspace.status).json({ error: workspace.error });
|
|
3447
3482
|
}
|
|
3448
|
-
const summary =
|
|
3483
|
+
const summary = await getUnpushedCommitSummaryForCwdAsync(workspace.cwd, workspace.branch, workspace.project);
|
|
3449
3484
|
return res.json({ commits: summary.commits, total_count: summary.totalCount });
|
|
3450
3485
|
});
|
|
3451
3486
|
app.get('/bundles', async (req, res) => {
|
|
@@ -3465,7 +3500,7 @@ app.get('/bundles', async (req, res) => {
|
|
|
3465
3500
|
timing.mark('serialize_bundles');
|
|
3466
3501
|
timing.end({ count: serializedBundles.length });
|
|
3467
3502
|
res.json(serializedBundles);
|
|
3468
|
-
startPassiveGitHubWork('project-bundle-pr-sync', () => {
|
|
3503
|
+
startPassiveGitHubWork(res, 'project-bundle-pr-sync', () => {
|
|
3469
3504
|
startProjectBundlePullRequestSyncIfNeeded(result.project, bundles);
|
|
3470
3505
|
});
|
|
3471
3506
|
});
|
|
@@ -3493,16 +3528,16 @@ app.get('/bundles/:id/conversation', (req, res) => {
|
|
|
3493
3528
|
}
|
|
3494
3529
|
const payload = serializeBundleConversationDetails(result.project, bundle);
|
|
3495
3530
|
res.json(payload);
|
|
3496
|
-
startPassiveGitHubWork('bundle-conversation-pr-discovery', () => {
|
|
3531
|
+
startPassiveGitHubWork(res, 'bundle-conversation-pr-discovery', () => {
|
|
3497
3532
|
startBundlePullRequestDiscoveryIfNeeded(result.project, bundle);
|
|
3498
3533
|
});
|
|
3499
3534
|
});
|
|
3500
|
-
app.get('/bundles/:id/review-findings', (req, res) => {
|
|
3535
|
+
app.get('/bundles/:id/review-findings', async (req, res) => {
|
|
3501
3536
|
const result = getRequiredProject(req);
|
|
3502
3537
|
if ('error' in result) {
|
|
3503
3538
|
return res.status(400).json({ error: result.error });
|
|
3504
3539
|
}
|
|
3505
|
-
const response = getBundleReviewFindings(result.project.id, req.params.id);
|
|
3540
|
+
const response = await getBundleReviewFindings(result.project.id, req.params.id);
|
|
3506
3541
|
if (!response) {
|
|
3507
3542
|
return res.status(404).json({ error: 'Bundle not found' });
|
|
3508
3543
|
}
|
|
@@ -5933,7 +5968,7 @@ app.post('/projects', (req, res) => {
|
|
|
5933
5968
|
return res.status(400).json({ error: validation.error });
|
|
5934
5969
|
}
|
|
5935
5970
|
const projectCount = Number(db.prepare('SELECT COUNT(*) AS count FROM projects').get()?.count ?? 0);
|
|
5936
|
-
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, 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;
|
|
5971
|
+
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, 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;
|
|
5937
5972
|
if (!repo_path) {
|
|
5938
5973
|
return res.status(400).json({ error: 'repo_path must be a non-empty string' });
|
|
5939
5974
|
}
|
|
@@ -5957,6 +5992,7 @@ app.post('/projects', (req, res) => {
|
|
|
5957
5992
|
required_check_definition_ids,
|
|
5958
5993
|
pre_review_check_definition_ids,
|
|
5959
5994
|
post_build_check_definition_ids,
|
|
5995
|
+
auto_fix_check_definition_ids,
|
|
5960
5996
|
test_commands,
|
|
5961
5997
|
run_ide,
|
|
5962
5998
|
preview_service_name,
|
|
@@ -5978,8 +6014,8 @@ app.post('/projects', (req, res) => {
|
|
|
5978
6014
|
automation_review_severity,
|
|
5979
6015
|
automation_review_max_iterations
|
|
5980
6016
|
)
|
|
5981
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5982
|
-
`).run(id, name, normalizedRepoPath, run_setup, run_services, check_definitions, required_check_definition_ids ?? '[]', pre_review_check_definition_ids ?? '[]', post_build_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);
|
|
6017
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
6018
|
+
`).run(id, name, normalizedRepoPath, 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 ?? 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);
|
|
5983
6019
|
replaceProjectLinks(id, linked_project_ids ?? []);
|
|
5984
6020
|
ensureProjectRootBundle(id);
|
|
5985
6021
|
if (projectCount === 0) {
|
|
@@ -6873,7 +6909,7 @@ app.post('/projects/:id/git-abort', async (req, res) => {
|
|
|
6873
6909
|
return res.status(500).json({ error: 'Unable to determine project branch' });
|
|
6874
6910
|
}
|
|
6875
6911
|
});
|
|
6876
|
-
app.get('/projects/:id/diff', (req, res) => {
|
|
6912
|
+
app.get('/projects/:id/diff', async (req, res) => {
|
|
6877
6913
|
const project = getProjectById(req.params.id);
|
|
6878
6914
|
if (!project) {
|
|
6879
6915
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -6882,7 +6918,7 @@ app.get('/projects/:id/diff', (req, res) => {
|
|
|
6882
6918
|
if ('error' in workspace) {
|
|
6883
6919
|
return res.status(workspace.status).json({ error: workspace.error });
|
|
6884
6920
|
}
|
|
6885
|
-
const diffData =
|
|
6921
|
+
const diffData = await getGitDiffDataAsync(workspace.cwd);
|
|
6886
6922
|
return res.json({
|
|
6887
6923
|
stats: summarizeTicketDiffFiles(diffData.files),
|
|
6888
6924
|
files: diffData.files,
|
|
@@ -6900,7 +6936,7 @@ app.get('/projects/:id/committed-diff', (req, res) => {
|
|
|
6900
6936
|
}
|
|
6901
6937
|
return sendUnpushedCommitDiff(res, workspace, getCommitHashQuery(req));
|
|
6902
6938
|
});
|
|
6903
|
-
app.get('/projects/:id/git-status', (req, res) => {
|
|
6939
|
+
app.get('/projects/:id/git-status', async (req, res) => {
|
|
6904
6940
|
const project = getProjectById(req.params.id);
|
|
6905
6941
|
if (!project) {
|
|
6906
6942
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -6910,9 +6946,9 @@ app.get('/projects/:id/git-status', (req, res) => {
|
|
|
6910
6946
|
return res.status(workspace.status).json({ error: workspace.error });
|
|
6911
6947
|
}
|
|
6912
6948
|
const refreshRemote = req.query.refresh_remote === 'true';
|
|
6913
|
-
return res.json(
|
|
6949
|
+
return res.json(await getGitStatusAsync(workspace.cwd, workspace.branch, workspace.project, { refreshRemote }));
|
|
6914
6950
|
});
|
|
6915
|
-
app.get('/projects/:id/git-commits', (req, res) => {
|
|
6951
|
+
app.get('/projects/:id/git-commits', async (req, res) => {
|
|
6916
6952
|
const project = getProjectById(req.params.id);
|
|
6917
6953
|
if (!project) {
|
|
6918
6954
|
return res.status(404).json({ error: 'Not found' });
|
|
@@ -6921,7 +6957,7 @@ app.get('/projects/:id/git-commits', (req, res) => {
|
|
|
6921
6957
|
if ('error' in workspace) {
|
|
6922
6958
|
return res.status(workspace.status).json({ error: workspace.error });
|
|
6923
6959
|
}
|
|
6924
|
-
const summary =
|
|
6960
|
+
const summary = await getUnpushedCommitSummaryForCwdAsync(workspace.cwd, workspace.branch, workspace.project);
|
|
6925
6961
|
return res.json({ commits: summary.commits, total_count: summary.totalCount });
|
|
6926
6962
|
});
|
|
6927
6963
|
app.post('/projects/:id/git-commit', async (req, res) => {
|
|
@@ -7186,7 +7222,7 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
7186
7222
|
});
|
|
7187
7223
|
}
|
|
7188
7224
|
}
|
|
7189
|
-
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, 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;
|
|
7225
|
+
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, 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;
|
|
7190
7226
|
const updateProject = db.prepare(`
|
|
7191
7227
|
UPDATE projects SET
|
|
7192
7228
|
name = ?,
|
|
@@ -7197,6 +7233,7 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
7197
7233
|
required_check_definition_ids = ?,
|
|
7198
7234
|
pre_review_check_definition_ids = ?,
|
|
7199
7235
|
post_build_check_definition_ids = ?,
|
|
7236
|
+
auto_fix_check_definition_ids = ?,
|
|
7200
7237
|
test_commands = ?,
|
|
7201
7238
|
run_ide = ?,
|
|
7202
7239
|
preview_service_name = ?,
|
|
@@ -7230,6 +7267,9 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
7230
7267
|
const nextPostBuildCheckDefinitionIds = hasOwn(validation.values, 'post_build_check_definition_ids')
|
|
7231
7268
|
? post_build_check_definition_ids ?? '[]'
|
|
7232
7269
|
: project.post_build_check_definition_ids ?? '[]';
|
|
7270
|
+
const nextAutoFixCheckDefinitionIds = hasOwn(validation.values, 'auto_fix_check_definition_ids')
|
|
7271
|
+
? auto_fix_check_definition_ids ?? '[]'
|
|
7272
|
+
: project.auto_fix_check_definition_ids;
|
|
7233
7273
|
const updateResult = db.transaction(() => {
|
|
7234
7274
|
const policyReferences = validateProjectRequiredCheckPolicyReferences({
|
|
7235
7275
|
projectId: project.id,
|
|
@@ -7237,11 +7277,12 @@ app.patch('/projects/:id', (req, res) => {
|
|
|
7237
7277
|
requiredCheckDefinitionIdsJson: nextRequiredCheckDefinitionIds,
|
|
7238
7278
|
preReviewCheckDefinitionIdsJson: nextPreReviewCheckDefinitionIds,
|
|
7239
7279
|
postBuildCheckDefinitionIdsJson: nextPostBuildCheckDefinitionIds,
|
|
7280
|
+
autoFixCheckDefinitionIdsJson: nextAutoFixCheckDefinitionIds,
|
|
7240
7281
|
});
|
|
7241
7282
|
if ('error' in policyReferences) {
|
|
7242
7283
|
return policyReferences;
|
|
7243
7284
|
}
|
|
7244
|
-
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, nextPostBuildCheckDefinitionIds, 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);
|
|
7285
|
+
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, 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, 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);
|
|
7245
7286
|
if (hasOwn(validation.values, 'linked_project_ids')) {
|
|
7246
7287
|
replaceProjectLinks(project.id, linked_project_ids ?? []);
|
|
7247
7288
|
}
|
|
@@ -7278,6 +7319,13 @@ const assertProjectDeletionEligible = (projectId, claimId) => {
|
|
|
7278
7319
|
if (hasActiveProjectCheckBatch(projectId)) {
|
|
7279
7320
|
throw new ProjectDeletionError(409, 'Cannot delete a project while checks are active');
|
|
7280
7321
|
}
|
|
7322
|
+
if (db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'check_auto_fix_loops'").get() && db.prepare(`
|
|
7323
|
+
SELECT 1 FROM check_auto_fix_loops loop
|
|
7324
|
+
JOIN execution_runs run ON run.id = loop.execution_run_id
|
|
7325
|
+
WHERE run.project_id = ? AND loop.terminal_reason IS NULL LIMIT 1
|
|
7326
|
+
`).get(projectId)) {
|
|
7327
|
+
throw new ProjectDeletionError(409, 'Cannot delete a project while automatic check repair is active');
|
|
7328
|
+
}
|
|
7281
7329
|
if (!claimId && hasActiveProjectRepositoryGraphScan(projectId)) {
|
|
7282
7330
|
throw new ProjectDeletionError(409, 'Cannot delete a project while a repository graph scan is active');
|
|
7283
7331
|
}
|
|
@@ -7311,6 +7359,12 @@ const completeClaimedProjectDeletion = async (projectId, claimId) => {
|
|
|
7311
7359
|
WHERE evaluation_id IN (SELECT id FROM check_gate_evaluations WHERE project_id = ?)
|
|
7312
7360
|
`).run(projectId);
|
|
7313
7361
|
db.prepare('DELETE FROM check_gate_evaluations WHERE project_id = ?').run(projectId);
|
|
7362
|
+
if (db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'check_auto_fix_loops'").get()) {
|
|
7363
|
+
db.prepare(`
|
|
7364
|
+
DELETE FROM check_auto_fix_loops
|
|
7365
|
+
WHERE execution_run_id IN (SELECT id FROM execution_runs WHERE project_id = ?)
|
|
7366
|
+
`).run(projectId);
|
|
7367
|
+
}
|
|
7314
7368
|
if (db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'check_repair_details'").get()) {
|
|
7315
7369
|
db.prepare(`
|
|
7316
7370
|
DELETE FROM check_repair_details
|
|
@@ -8361,6 +8415,9 @@ app.post('/projects/:id/check-repairs/:repairRunId/stop', async (req, res) => {
|
|
|
8361
8415
|
return res.status(404).json({ error: 'Not found' });
|
|
8362
8416
|
}
|
|
8363
8417
|
try {
|
|
8418
|
+
if (getCheckAutoFixDetails(req.params.id, req.params.repairRunId)) {
|
|
8419
|
+
return res.json(await stopCheckAutoFix(req.params.id, req.params.repairRunId, io));
|
|
8420
|
+
}
|
|
8364
8421
|
return res.json(await stopCheckRepair(req.params.id, req.params.repairRunId, io));
|
|
8365
8422
|
}
|
|
8366
8423
|
catch (error) {
|
|
@@ -8499,6 +8556,7 @@ app.get('/projects/:id/check-batches/:batchRunId/diagnostics', async (req, res)
|
|
|
8499
8556
|
...diagnostics,
|
|
8500
8557
|
repair: await getCheckRepairCandidateState(project.id, req.params.batchRunId),
|
|
8501
8558
|
latest_repair: getLatestCheckRepairForBatch(project.id, req.params.batchRunId),
|
|
8559
|
+
auto_fix: getCheckAutoFixDetails(project.id, req.params.batchRunId),
|
|
8502
8560
|
});
|
|
8503
8561
|
});
|
|
8504
8562
|
app.get('/projects/:id/check-attempts/:attemptRunId/diagnostics', (req, res) => {
|
|
@@ -8936,6 +8994,7 @@ app.post('/tickets/:id/stop-build', async (req, res) => {
|
|
|
8936
8994
|
const result = await stopBuildTicketRun({
|
|
8937
8995
|
ticketId: req.params.id,
|
|
8938
8996
|
requestedProjectId: getRequestedProjectId(req),
|
|
8997
|
+
broadcaster: io,
|
|
8939
8998
|
});
|
|
8940
8999
|
if (!result.ok) {
|
|
8941
9000
|
return res.status(result.status).json({ error: result.error });
|