@straiffi/archon 1.8.2 → 1.8.4
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-CZwuxu-k.js +1 -0
- package/dist/client/assets/GitHubActionsDialog-m0WCUbsY.js +1 -0
- package/dist/client/assets/VerificationDialog-D0LL2bcG.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DSq-Vw-s.js → architectureDiagram-3BPJPVTR-Da0b3yts.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-C_0U0auf.js → blockDiagram-GPEHLZMM-DvzsxBUN.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CEHt0Kjy.js → c4Diagram-AAUBKEIU-BEKrFtx2.js} +1 -1
- package/dist/client/assets/channel-CHuNNrYD.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-C0Kxxq-6.js → chunk-2J33WTMH-BAKgBD7I.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-QvjUuKmV.js → chunk-3OPIFGDE-BKPTlfa5.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-Csrpz86K.js → chunk-5ZQYHXKU-BDqDj4QJ.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-B3vZVGMR.js → chunk-727SXJPM-Cs2r0JtD.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-Cs9__8di.js → chunk-AQP2D5EJ-DQbaJPN-.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-C9X7lfBM.js → chunk-CSCIHK7Q-CxuNtNrM.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-CY0NGeTu.js → chunk-KSCS5N6A-Cw9Q8JPi.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-BboXbWo7.js → chunk-L5ZTLDWV-CtuZjEe8.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-CUBnjoBD.js → chunk-LZXEDZCA-BQQddDdh.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-BJqpZMk2.js → chunk-ND2GUHAM-AK6DBTJe.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-BHRnsVyz.js → chunk-NZK2D7GU-CWRA29FQ.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-Anqw_yuF.js → chunk-O5CBEL6O-X-Oio9FM.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-BgGztexj.js → chunk-WU5MYG2G-CETO3v_f.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BZQ7jv-A.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-7EFkByjs.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-BaQbcdG0.js → dagre-BM42HDAG-Dt0-rccy.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-Brv-rcOf.js → diagram-2AECGRRQ-BWRTEjaU.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-D3eStICz.js → diagram-5GNKFQAL-C2H5QcoG.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-CrZfGF7-.js → diagram-KO2AKTUF-RBK3VSKM.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-Dtk6gUIn.js → diagram-LMA3HP47-RGh2ZH4s.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-Bmarlaaa.js → diagram-OG6HWLK6-DRZPfcn0.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-BC_ZzN2S.js → erDiagram-TEJ5UH35-BMjeuzHP.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-DpCPHLj5.js → flowDiagram-I6XJVG4X-DoLSPv4x.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CaLaeFMa.js → ganttDiagram-6RSMTGT7-By8_6nMe.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-36phJ4N5.js → gitGraphDiagram-PVQCEYII-2rHM4CiD.js} +1 -1
- package/dist/client/assets/index-3dSPyX_Q.js +274 -0
- package/dist/client/assets/index-DZqqZx53.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BI5oO32P.js → infoDiagram-5YYISTIA-DWOg8hUJ.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-bgfzr0xn.js → ishikawaDiagram-YF4QCWOH-C9YznvSm.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DrmwNzOC.js → journeyDiagram-JHISSGLW-DSQDDTNI.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Cg5rkyMP.js → kanban-definition-UN3LZRKU-BkmCufHa.js} +1 -1
- package/dist/client/assets/{line-CFlz4TDX.js → line-cufAthH2.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-C7CnvU1K.js → mermaid-parser.core-BzbhogG7.js} +1 -1
- package/dist/client/assets/{mermaid.core-Dbab-VXW.js → mermaid.core-CsQKe9Kh.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-DJze85_k.js → mindmap-definition-RKZ34NQL-Ci6JrMb6.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DJAQkhKY.js → pieDiagram-4H26LBE5-CU9I_3Q_.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BD8d4qar.js → quadrantDiagram-W4KKPZXB-DytyOGrA.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-C5mokQZP.js → requirementDiagram-4Y6WPE33-CnrtyW9-.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-EkdPZKJO.js → sankeyDiagram-5OEKKPKP-CGAC1tbH.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B-5oe-32.js → sequenceDiagram-3UESZ5HK-Cqlp3Fns.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-BFHel4DJ.js → stateDiagram-AJRCARHV-DspbWEGS.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Bcxu99EH.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DvyAtzba.js → timeline-definition-PNZ67QCA-Bd0SWRDD.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-C9vIulQP.js → vennDiagram-CIIHVFJN-BZduwhis.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CQTFOoRr.js → wardleyDiagram-YWT4CUSO-D6LrBEnX.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-CyXsRLmO.js → xychartDiagram-2RQKCTM6-CoLKir5a.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/notification-service-worker.js +70 -0
- package/dist/server/db.js +11 -0
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +83 -95
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/automationBuildContinuation.js +141 -0
- package/dist/server/lib/automationBuildContinuation.js.map +1 -0
- package/dist/server/lib/buildSequences.js +13 -6
- package/dist/server/lib/buildSequences.js.map +1 -1
- package/dist/server/lib/chatOperations.js +23 -5
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/chatTargets.js +3 -129
- package/dist/server/lib/chatTargets.js.map +1 -1
- package/dist/server/lib/chats.js +4 -40
- package/dist/server/lib/chats.js.map +1 -1
- package/dist/server/lib/checkRepair.js +28 -1
- package/dist/server/lib/checkRepair.js.map +1 -1
- package/dist/server/lib/executionRetry.js +14 -6
- package/dist/server/lib/executionRetry.js.map +1 -1
- package/dist/server/lib/executionRetryContext.js +11 -3
- package/dist/server/lib/executionRetryContext.js.map +1 -1
- package/dist/server/lib/executionRuns.js +11 -4
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/git.js +3 -2
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/projectTargets.js +5 -0
- package/dist/server/lib/projectTargets.js.map +1 -1
- package/dist/server/lib/pullRequestContent.js +8 -4
- package/dist/server/lib/pullRequestContent.js.map +1 -1
- package/dist/server/lib/reviewFindings.js +1 -1
- package/dist/server/lib/reviewFindings.js.map +1 -1
- package/dist/server/lib/sessionTargets.js +166 -0
- package/dist/server/lib/sessionTargets.js.map +1 -0
- package/dist/server/lib/specOperations.js +6 -0
- package/dist/server/lib/specOperations.js.map +1 -1
- package/dist/server/lib/specReviewOperations.js +5 -0
- package/dist/server/lib/specReviewOperations.js.map +1 -1
- package/dist/server/lib/specWorkspaceActivity.js +35 -0
- package/dist/server/lib/specWorkspaceActivity.js.map +1 -0
- package/dist/server/lib/specs.js +15 -4
- package/dist/server/lib/specs.js.map +1 -1
- package/dist/server/lib/ticketAutomation.js +2 -1
- package/dist/server/lib/ticketAutomation.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +1 -4
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/tickets.js +15 -8
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/workers/build.js +3 -1
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/plan.js +1 -1
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/specReview.js +21 -4
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +42 -19
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/ActivityView-CF8punHV.js +0 -1
- package/dist/client/assets/GitHubActionsDialog-Ckb99-ve.js +0 -1
- package/dist/client/assets/VerificationDialog-BgEDRfgP.js +0 -4
- package/dist/client/assets/channel-BjDfVBsO.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DSaSDx3D.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BwfjAHrx.js +0 -1
- package/dist/client/assets/index-D4qr0sQx.css +0 -2
- package/dist/client/assets/index-Os2WLcbu.js +0 -274
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-iGqsY8gO.js +0 -1
package/dist/server/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { createProjectChatSession, resolveChatTool, resolveProjectChatPlanQuesti
|
|
|
15
15
|
import { createProjectSpecSession, deleteProjectSpecSession, resolveProjectSpecPlanQuestionSet, stopProjectSpecSessionResponse, submitProjectSpecSessionMessage, updateProjectSpecSessionMode, } from './lib/specOperations.js';
|
|
16
16
|
import { buildProjectSpecReviewRevisionDraft, getProjectSpecReviewFindings, startProjectSpecReview, stopProjectSpecReview, } from './lib/specReviewOperations.js';
|
|
17
17
|
import { resolveChatSessionTarget } from './lib/chatTargets.js';
|
|
18
|
+
import { resolveSessionTargetForExecution } from './lib/sessionTargets.js';
|
|
18
19
|
import { createChatMessage, getChatMessage, updateChatMessageContent } from './lib/chatMessages.js';
|
|
19
20
|
import { attachChatTicketProposalsToMessageContent } from './lib/chatTicketProposals.js';
|
|
20
21
|
import { createCorsOriginResolver, parseCorsOrigins } from './lib/cors.js';
|
|
@@ -43,6 +44,7 @@ import { decodeProjectMemoryCursor } from './lib/projectMemoryCursor.js';
|
|
|
43
44
|
import { getProjectFileSuggestions } from './lib/projectFileSuggestions.js';
|
|
44
45
|
import { getProjectFileManifest, ProjectFileContentError, ProjectFileTargetUnavailableError, readProjectFileContent } from './lib/projectFiles.js';
|
|
45
46
|
import { updateProjectTargetSelection } from './lib/projectTargets.js';
|
|
47
|
+
import { hasActiveBundleSpecWork } from './lib/specWorkspaceActivity.js';
|
|
46
48
|
import { exportProjectMemoryArchive, importProjectMemoryArchive } from './lib/projectMemoryTransfer.js';
|
|
47
49
|
import { buildReviewFindingsResponse, computeDiffSignature, getLatestReviewRunForContext, listReviewFindings } from './lib/reviewFindings.js';
|
|
48
50
|
import { formatBuildOpenQuestionAnswersPrompt, getLatestBuildOpenQuestionBatchStatus, hasActiveBuildOpenQuestionBatch, listBuildOpenQuestionsForBundle, loadBuildOpenQuestionsByBundleIds, } from './lib/buildOpenQuestions.js';
|
|
@@ -55,11 +57,11 @@ import { pausedRunBelongsToProgression, resolveAutomationResumeDecision } from '
|
|
|
55
57
|
import { getAutomationStageDetails, } from './lib/automationStageDetails.js';
|
|
56
58
|
import { buildAutomationFixInstruction, clearAutomationPause, countBlockingFindings, depthAtLeast, getBundleAutomationState, isAutomationDepth, recordAutomationPause, resolveAutomationConfig, upsertBundleAutomationState, } from './lib/ticketAutomation.js';
|
|
57
59
|
import { resolveAutomationCheckGateResume, runAutomationCommitChain, runAutomationCommitOperation } from './lib/ticketAutomationCommit.js';
|
|
58
|
-
import {
|
|
59
|
-
import {
|
|
60
|
+
import { resolveBuildTicketCommitCheckpointLineage, canMutateBuildTicketCommitCheckpoint } from './lib/buildTicketCommit.js';
|
|
61
|
+
import { continueAfterBuildCheckpoint } from './lib/automationBuildContinuation.js';
|
|
60
62
|
import { getDiscoveredSkills, normalizeSkillNames } from './lib/skills.js';
|
|
61
63
|
import { clearAllPreviewProxies } from './lib/previewProxy.js';
|
|
62
|
-
import { createExecutionRun, addExecutionRunLink, addExecutionRunLinks, getExecutionRun, hasActiveBuildExecutionRunForTicket, getGitHubActionsExecutionDetails, getTestExecutionDetails, GitHubActionsDispatchConflictError, listExecutionRunLinks, listExecutionRuns, listLifecycleEvents, listProjectLifecycleEvents, toCanonicalLifecycleEvent, transitionExecutionRun, withExecutionRunTransaction, } from './lib/executionRuns.js';
|
|
64
|
+
import { createExecutionRun, addExecutionRunLink, addExecutionRunLinks, getExecutionRun, getLifecycleEvent, hasActiveBuildExecutionRunForTicket, getGitHubActionsExecutionDetails, getTestExecutionDetails, GitHubActionsDispatchConflictError, listExecutionRunLinks, listExecutionRuns, listLifecycleEvents, listProjectLifecycleEvents, toCanonicalLifecycleEvent, transitionExecutionRun, withExecutionRunTransaction, } from './lib/executionRuns.js';
|
|
63
65
|
import { dispatchExecutionRetry, getExecutionRetryEligibility, resolveExecutionRetry } from './lib/executionRetry.js';
|
|
64
66
|
import { listExecutionTimeline } from './lib/executionTimeline.js';
|
|
65
67
|
import { loadExecutionArtifactSummariesForRuns, openExecutionArtifactForRetrieval, } from './lib/executionArtifacts.js';
|
|
@@ -814,7 +816,7 @@ const uniqueBundleBranchName = (name, projectId, options = {}) => {
|
|
|
814
816
|
}
|
|
815
817
|
return branch;
|
|
816
818
|
};
|
|
817
|
-
const createAutoPlanningBundle = (projectId) => {
|
|
819
|
+
const createAutoPlanningBundle = (projectId, baseBranch = null) => {
|
|
818
820
|
const name = uniqueAutoBundleName(projectId);
|
|
819
821
|
const branch = uniqueBundleBranchName(name, projectId);
|
|
820
822
|
if (!branch) {
|
|
@@ -823,6 +825,7 @@ const createAutoPlanningBundle = (projectId) => {
|
|
|
823
825
|
const bundle = createBundle({
|
|
824
826
|
name,
|
|
825
827
|
branch,
|
|
828
|
+
baseBranch,
|
|
826
829
|
projectId,
|
|
827
830
|
});
|
|
828
831
|
if (!bundle) {
|
|
@@ -830,7 +833,7 @@ const createAutoPlanningBundle = (projectId) => {
|
|
|
830
833
|
}
|
|
831
834
|
return bundle;
|
|
832
835
|
};
|
|
833
|
-
const createAutoBundleForName = (name, projectId) => {
|
|
836
|
+
const createAutoBundleForName = (name, projectId, baseBranch = null) => {
|
|
834
837
|
const trimmedName = name.trim();
|
|
835
838
|
const requestedName = trimmedName || uniqueAutoBundleName(projectId);
|
|
836
839
|
const branch = uniqueBundleBranchName(requestedName, projectId);
|
|
@@ -840,6 +843,7 @@ const createAutoBundleForName = (name, projectId) => {
|
|
|
840
843
|
const bundle = createBundle({
|
|
841
844
|
name: branch,
|
|
842
845
|
branch,
|
|
846
|
+
baseBranch,
|
|
843
847
|
projectId,
|
|
844
848
|
});
|
|
845
849
|
if (!bundle) {
|
|
@@ -2370,7 +2374,11 @@ const createPlanningAgentTickets = db.transaction(({ draft, initiativePrompt, pr
|
|
|
2370
2374
|
return { tickets: createdTickets, dependencies: createdDependencies };
|
|
2371
2375
|
});
|
|
2372
2376
|
const createChatProposedTickets = db.transaction(({ project, chatSession, proposals, }) => {
|
|
2373
|
-
const
|
|
2377
|
+
const targetResult = resolveSessionTargetForExecution(chatSession, project, 'Chat session');
|
|
2378
|
+
if (!targetResult.ok) {
|
|
2379
|
+
throw new HttpError(409, targetResult.error);
|
|
2380
|
+
}
|
|
2381
|
+
const bundle = createAutoPlanningBundle(project.id, targetResult.target.branch);
|
|
2374
2382
|
const { createdTickets, createdDependencies, ticketIdsByKey } = materializeTicketsWithDependencies({
|
|
2375
2383
|
options: {
|
|
2376
2384
|
projectId: project.id,
|
|
@@ -3087,11 +3095,21 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/create-ti
|
|
|
3087
3095
|
error: `Spec tickets must include testing or verification guidance in their descriptions before they can be created on the board. Missing guidance in: ${ticketKeys}`,
|
|
3088
3096
|
});
|
|
3089
3097
|
}
|
|
3098
|
+
let generatedBundleId = null;
|
|
3090
3099
|
try {
|
|
3100
|
+
const targetResult = resolveSessionTargetForExecution(specSession, project, 'Spec session');
|
|
3101
|
+
if (!targetResult.ok) {
|
|
3102
|
+
throw new HttpError(409, targetResult.error);
|
|
3103
|
+
}
|
|
3104
|
+
const target = targetResult.target;
|
|
3091
3105
|
const bundleName = specSession.external_source?.external_key ?? '';
|
|
3092
3106
|
const bundle = bundleName
|
|
3093
|
-
? createAutoBundleForName(bundleName, project.id)
|
|
3094
|
-
: createAutoPlanningBundle(project.id);
|
|
3107
|
+
? createAutoBundleForName(bundleName, project.id, target.branch)
|
|
3108
|
+
: createAutoPlanningBundle(project.id, target.branch);
|
|
3109
|
+
if (!bundle || isProjectRootBundle(bundle)) {
|
|
3110
|
+
throw new HttpError(409, 'Unable to create a bundle for this Spec snapshot.');
|
|
3111
|
+
}
|
|
3112
|
+
generatedBundleId = bundle.id;
|
|
3095
3113
|
const ticketsForMaterialization = snapshot.tickets.map(ticket => {
|
|
3096
3114
|
const appendices = [
|
|
3097
3115
|
buildVisualizationAppendix(ticket.relevant_visualizations ?? [], snapshot),
|
|
@@ -3130,6 +3148,9 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/create-ti
|
|
|
3130
3148
|
});
|
|
3131
3149
|
}
|
|
3132
3150
|
catch (error) {
|
|
3151
|
+
if (generatedBundleId) {
|
|
3152
|
+
cleanupBundleIfEmpty(generatedBundleId, project);
|
|
3153
|
+
}
|
|
3133
3154
|
if (error instanceof HttpError) {
|
|
3134
3155
|
return res.status(error.status).json({ error: error.message });
|
|
3135
3156
|
}
|
|
@@ -3149,6 +3170,10 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/implement
|
|
|
3149
3170
|
if (!snapshot || snapshot.spec_session_id !== specSession.id) {
|
|
3150
3171
|
return res.status(404).json({ error: 'Not found' });
|
|
3151
3172
|
}
|
|
3173
|
+
const targetResult = resolveSessionTargetForExecution(specSession, project, 'Spec session');
|
|
3174
|
+
if (!targetResult.ok) {
|
|
3175
|
+
return res.status(409).json({ error: targetResult.error });
|
|
3176
|
+
}
|
|
3152
3177
|
const draftText = buildSpecImplementationDraft({ snapshot, specSession });
|
|
3153
3178
|
return res.status(200).json({
|
|
3154
3179
|
draft_text: draftText,
|
|
@@ -3169,11 +3194,15 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/export',
|
|
|
3169
3194
|
if (!snapshot || snapshot.spec_session_id !== specSession.id) {
|
|
3170
3195
|
return res.status(404).json({ error: 'Not found' });
|
|
3171
3196
|
}
|
|
3197
|
+
const targetResult = resolveSessionTargetForExecution(specSession, project, 'Spec session');
|
|
3198
|
+
if (!targetResult.ok) {
|
|
3199
|
+
return res.status(409).json({ error: targetResult.error });
|
|
3200
|
+
}
|
|
3172
3201
|
try {
|
|
3173
3202
|
const overwrite = req.body?.overwrite === true;
|
|
3174
3203
|
const collision = checkSpecExportCollision({
|
|
3175
3204
|
specSession,
|
|
3176
|
-
repoPath:
|
|
3205
|
+
repoPath: targetResult.target.cwd,
|
|
3177
3206
|
});
|
|
3178
3207
|
if (collision && !overwrite) {
|
|
3179
3208
|
return res.status(409).json({
|
|
@@ -3184,7 +3213,7 @@ app.post('/projects/:id/spec-sessions/:sessionId/snapshots/:snapshotId/export',
|
|
|
3184
3213
|
const result = exportSpecToDocs({
|
|
3185
3214
|
snapshot,
|
|
3186
3215
|
specSession,
|
|
3187
|
-
repoPath:
|
|
3216
|
+
repoPath: targetResult.target.cwd,
|
|
3188
3217
|
});
|
|
3189
3218
|
return res.status(201).json({
|
|
3190
3219
|
path: result.filePath,
|
|
@@ -3748,6 +3777,7 @@ app.post('/bundles', async (req, res) => {
|
|
|
3748
3777
|
const bundle = createBundle({
|
|
3749
3778
|
name,
|
|
3750
3779
|
branch,
|
|
3780
|
+
baseBranch: requestedBaseBranch || null,
|
|
3751
3781
|
projectId: result.project.id,
|
|
3752
3782
|
});
|
|
3753
3783
|
if (!bundle) {
|
|
@@ -3783,6 +3813,9 @@ app.delete('/bundles/:id', (req, res) => {
|
|
|
3783
3813
|
if (hasActiveBundleCheckWork(result.project.id, bundle.id)) {
|
|
3784
3814
|
return res.status(409).json({ error: 'Cannot delete a bundle while check work is active' });
|
|
3785
3815
|
}
|
|
3816
|
+
if (hasActiveBundleSpecWork(result.project.id, bundle.id)) {
|
|
3817
|
+
return res.status(409).json({ error: 'Cannot delete a bundle while Spec work is active' });
|
|
3818
|
+
}
|
|
3786
3819
|
if (countBundleTickets(bundle.id, result.project.id) > 0) {
|
|
3787
3820
|
return res.status(409).json({ error: 'Cannot delete a bundle that is still used by tickets' });
|
|
3788
3821
|
}
|
|
@@ -3792,6 +3825,9 @@ app.delete('/bundles/:id', (req, res) => {
|
|
|
3792
3825
|
const affectedChatSessionIds = listChatSessions(result.project.id)
|
|
3793
3826
|
.filter(chatSession => chatSession.target_bundle_id === bundle.id)
|
|
3794
3827
|
.map(chatSession => chatSession.id);
|
|
3828
|
+
const affectedSpecSessionIds = listSpecSessions(result.project.id)
|
|
3829
|
+
.filter(specSession => specSession.target_bundle_id === bundle.id)
|
|
3830
|
+
.map(specSession => specSession.id);
|
|
3795
3831
|
try {
|
|
3796
3832
|
deleteWorktree(bundle.branch, result.project);
|
|
3797
3833
|
}
|
|
@@ -3807,6 +3843,12 @@ app.delete('/bundles/:id', (req, res) => {
|
|
|
3807
3843
|
io.emit('chat-session:updated', updatedChatSession);
|
|
3808
3844
|
}
|
|
3809
3845
|
});
|
|
3846
|
+
affectedSpecSessionIds.forEach(specSessionId => {
|
|
3847
|
+
const updatedSpecSession = getProjectSpecSession(result.project.id, specSessionId);
|
|
3848
|
+
if (updatedSpecSession) {
|
|
3849
|
+
io.emit('spec-session:updated', updatedSpecSession);
|
|
3850
|
+
}
|
|
3851
|
+
});
|
|
3810
3852
|
res.status(204).end();
|
|
3811
3853
|
});
|
|
3812
3854
|
app.patch('/bundles/:id', (req, res) => {
|
|
@@ -3899,6 +3941,19 @@ app.patch('/bundles/:id', (req, res) => {
|
|
|
3899
3941
|
return res.status(400).json({ error: 'automation_pause_on_open_questions must be a boolean' });
|
|
3900
3942
|
}
|
|
3901
3943
|
}
|
|
3944
|
+
let automationReviewMaxIterations = bundle.automation_review_max_iterations ?? null;
|
|
3945
|
+
if (hasOwn(req.body, 'automation_review_max_iterations')) {
|
|
3946
|
+
const value = req.body.automation_review_max_iterations;
|
|
3947
|
+
if (value === null) {
|
|
3948
|
+
automationReviewMaxIterations = null;
|
|
3949
|
+
}
|
|
3950
|
+
else if (typeof value === 'number' && Number.isInteger(value) && value >= 1 && value <= 10) {
|
|
3951
|
+
automationReviewMaxIterations = value;
|
|
3952
|
+
}
|
|
3953
|
+
else {
|
|
3954
|
+
return res.status(400).json({ error: 'automation_review_max_iterations must be an integer between 1 and 10' });
|
|
3955
|
+
}
|
|
3956
|
+
}
|
|
3902
3957
|
let updated = null;
|
|
3903
3958
|
try {
|
|
3904
3959
|
updated = db.transaction(() => {
|
|
@@ -3916,6 +3971,7 @@ app.patch('/bundles/:id', (req, res) => {
|
|
|
3916
3971
|
automationDepth,
|
|
3917
3972
|
automationReviewFixEnabled,
|
|
3918
3973
|
automationPauseOnOpenQuestions,
|
|
3974
|
+
automationReviewMaxIterations,
|
|
3919
3975
|
});
|
|
3920
3976
|
})();
|
|
3921
3977
|
}
|
|
@@ -4331,94 +4387,15 @@ app.post('/bundles/:id/resume-automation', async (req, res) => {
|
|
|
4331
4387
|
return res.status(409).json({ error: error instanceof Error ? error.message : String(error) });
|
|
4332
4388
|
}
|
|
4333
4389
|
const workflowContext = validateWorkflowContext(checkpointLineage.progression.metadata);
|
|
4334
|
-
|
|
4390
|
+
await continueAfterBuildCheckpoint({
|
|
4335
4391
|
ticket: owner,
|
|
4392
|
+
project: result.project,
|
|
4393
|
+
parentRunId: checkpointLineage.parent.id,
|
|
4394
|
+
workflowContext,
|
|
4395
|
+
io,
|
|
4336
4396
|
emitUpdatedTickets,
|
|
4397
|
+
commitCheckpoint: false,
|
|
4337
4398
|
});
|
|
4338
|
-
if (continuation.nextBuild) {
|
|
4339
|
-
const nextBuild = continuation.nextBuild;
|
|
4340
|
-
const nextSequenceId = continuation.nextSequenceId;
|
|
4341
|
-
const scheduling = startBuild(nextBuild, io, {
|
|
4342
|
-
initiation: {
|
|
4343
|
-
initiator: 'automation',
|
|
4344
|
-
causalParentRunId: checkpointLineage.parent.id,
|
|
4345
|
-
workflowContext,
|
|
4346
|
-
},
|
|
4347
|
-
sequenceId: nextSequenceId,
|
|
4348
|
-
accept: () => {
|
|
4349
|
-
const transition = prepareTicketForBuild(nextBuild.id, {
|
|
4350
|
-
ignoredBlockerTicketIds: continuation.ignoredBlockerTicketIds,
|
|
4351
|
-
});
|
|
4352
|
-
if (!transition.ok) {
|
|
4353
|
-
throw new Error(transition.error);
|
|
4354
|
-
}
|
|
4355
|
-
if (!nextSequenceId) {
|
|
4356
|
-
throw new Error('Build sequence no longer exists');
|
|
4357
|
-
}
|
|
4358
|
-
activateQueuedBuildSequenceTicket(nextSequenceId, transition.ticket.id);
|
|
4359
|
-
return {
|
|
4360
|
-
ticket: transition.ticket,
|
|
4361
|
-
sequenceId: nextSequenceId,
|
|
4362
|
-
compensate: () => compensateBuildSequenceTicketActivation(nextSequenceId, transition.ticket.id),
|
|
4363
|
-
};
|
|
4364
|
-
},
|
|
4365
|
-
});
|
|
4366
|
-
if (!scheduling.accepted) {
|
|
4367
|
-
const stoppedSequence = stopBuildSequence(nextBuild.id);
|
|
4368
|
-
emitUpdatedTickets(stoppedSequence.affectedTicketIds);
|
|
4369
|
-
}
|
|
4370
|
-
}
|
|
4371
|
-
else if (!continuation.nextTicketId && owner.project_id && owner.worktree_bundle_id) {
|
|
4372
|
-
const resumedOwnerForReview = getTicket(owner.id) ?? owner;
|
|
4373
|
-
const liveProject = getEffectiveProject(resumedOwnerForReview) ?? result.project;
|
|
4374
|
-
const automationConfig = resolveAutomationConfig(resumedOwnerForReview.bundle ?? null, liveProject);
|
|
4375
|
-
const autoReviewEnabled = depthAtLeast(automationConfig.depth, 'auto_review');
|
|
4376
|
-
const latestBundleState = getBundleAutomationState(owner.project_id, owner.worktree_bundle_id);
|
|
4377
|
-
const openQuestions = listBuildOpenQuestionsForBundle(owner.project_id, owner.worktree_bundle_id);
|
|
4378
|
-
const shouldPauseForOpenQuestions = autoReviewEnabled
|
|
4379
|
-
&& automationConfig.pauseOnOpenQuestions
|
|
4380
|
-
&& openQuestions.length > 0;
|
|
4381
|
-
if (shouldPauseForOpenQuestions) {
|
|
4382
|
-
const reviewProgression = ensureAutomationProgression({
|
|
4383
|
-
projectId: owner.project_id,
|
|
4384
|
-
bundleId: owner.worktree_bundle_id,
|
|
4385
|
-
ticketId: owner.id,
|
|
4386
|
-
ticketTitle: owner.title,
|
|
4387
|
-
parentRunId: checkpointLineage.parent.id,
|
|
4388
|
-
workflowContext,
|
|
4389
|
-
broadcaster: io,
|
|
4390
|
-
});
|
|
4391
|
-
waitAutomationProgression({
|
|
4392
|
-
projectId: owner.project_id,
|
|
4393
|
-
bundleId: owner.worktree_bundle_id,
|
|
4394
|
-
progressionRunId: reviewProgression.runId,
|
|
4395
|
-
pauseCode: 'open_questions',
|
|
4396
|
-
pauseReason: `${openQuestions.length} unresolved Build open question${openQuestions.length === 1 ? '' : 's'}`,
|
|
4397
|
-
reasonCode: 'precondition_failed',
|
|
4398
|
-
pausedStageRunId: checkpointLineage.parent.id,
|
|
4399
|
-
broadcaster: io,
|
|
4400
|
-
});
|
|
4401
|
-
}
|
|
4402
|
-
else if (autoReviewEnabled && (!latestBundleState?.automation_paused_reason || latestBundleState.automation_paused_code === 'open_questions')) {
|
|
4403
|
-
const reviewProgression = ensureAutomationProgression({
|
|
4404
|
-
projectId: owner.project_id,
|
|
4405
|
-
bundleId: owner.worktree_bundle_id,
|
|
4406
|
-
ticketId: owner.id,
|
|
4407
|
-
ticketTitle: owner.title,
|
|
4408
|
-
parentRunId: checkpointLineage.parent.id,
|
|
4409
|
-
workflowContext,
|
|
4410
|
-
broadcaster: io,
|
|
4411
|
-
});
|
|
4412
|
-
await runAutomationReviewGateOrPause({
|
|
4413
|
-
projectId: owner.project_id,
|
|
4414
|
-
bundleId: owner.worktree_bundle_id,
|
|
4415
|
-
progressionRunId: reviewProgression.runId,
|
|
4416
|
-
broadcaster: io,
|
|
4417
|
-
pausedStageRunId: checkpointLineage.parent.id,
|
|
4418
|
-
initiation: { workflowContext },
|
|
4419
|
-
});
|
|
4420
|
-
}
|
|
4421
|
-
}
|
|
4422
4399
|
const resumedOwner = getTicket(owner.id);
|
|
4423
4400
|
if (resumedOwner) {
|
|
4424
4401
|
io.emit('ticket:updated', resumedOwner);
|
|
@@ -8489,6 +8466,17 @@ app.get('/projects/:id/lifecycle-events', (req, res) => {
|
|
|
8489
8466
|
throw error;
|
|
8490
8467
|
}
|
|
8491
8468
|
});
|
|
8469
|
+
app.get('/projects/:id/lifecycle-events/:eventId', (req, res) => {
|
|
8470
|
+
const project = getProjectById(req.params.id);
|
|
8471
|
+
if (!project) {
|
|
8472
|
+
return res.status(404).json({ error: 'Not found' });
|
|
8473
|
+
}
|
|
8474
|
+
const event = getLifecycleEvent(project.id, req.params.eventId);
|
|
8475
|
+
if (!event) {
|
|
8476
|
+
return res.status(404).json({ error: 'Lifecycle event not found' });
|
|
8477
|
+
}
|
|
8478
|
+
return res.json(toCanonicalLifecycleEvent(event));
|
|
8479
|
+
});
|
|
8492
8480
|
app.get('/projects/:id/execution-timeline', (req, res) => {
|
|
8493
8481
|
const project = getProjectById(req.params.id);
|
|
8494
8482
|
if (!project) {
|