@straiffi/archon 1.11.2 → 1.11.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.
Files changed (118) hide show
  1. package/dist/client/assets/{ActivityView-DJq1H7eJ.js → ActivityView-Cj-JRM9h.js} +1 -1
  2. package/dist/client/assets/{GitHubActionsDialog-uhkY79FP.js → GitHubActionsDialog-Bz7x-EXk.js} +1 -1
  3. package/dist/client/assets/{VerificationDialog-B1fn5Xb_.js → VerificationDialog-C1g5teUk.js} +1 -1
  4. package/dist/client/assets/{architectureDiagram-3BPJPVTR-BIJiODuH.js → architectureDiagram-3BPJPVTR-Czgp4_s_.js} +1 -1
  5. package/dist/client/assets/{blockDiagram-GPEHLZMM-zF74yReS.js → blockDiagram-GPEHLZMM-D_eKxSQA.js} +1 -1
  6. package/dist/client/assets/{c4Diagram-AAUBKEIU-Bhedpri8.js → c4Diagram-AAUBKEIU-D6nMuDM5.js} +1 -1
  7. package/dist/client/assets/channel-BsoUrvI0.js +1 -0
  8. package/dist/client/assets/{chunk-2J33WTMH-Cii8qtH1.js → chunk-2J33WTMH-B6Mn8gmT.js} +1 -1
  9. package/dist/client/assets/{chunk-3OPIFGDE-Hsh5MsIU.js → chunk-3OPIFGDE-BBoS7imT.js} +1 -1
  10. package/dist/client/assets/{chunk-5ZQYHXKU-B2H33geG.js → chunk-5ZQYHXKU-CdhOo0Gr.js} +1 -1
  11. package/dist/client/assets/{chunk-727SXJPM-o3GIhJ7i.js → chunk-727SXJPM-Dq8Odwy5.js} +1 -1
  12. package/dist/client/assets/{chunk-AQP2D5EJ-DZGEJOYd.js → chunk-AQP2D5EJ-DsKFdfMh.js} +1 -1
  13. package/dist/client/assets/{chunk-CSCIHK7Q-D7-p3_zX.js → chunk-CSCIHK7Q-4Ol5HlMd.js} +1 -1
  14. package/dist/client/assets/{chunk-KSCS5N6A-Dg344Qr2.js → chunk-KSCS5N6A-Ao7uFEEm.js} +1 -1
  15. package/dist/client/assets/{chunk-L5ZTLDWV-DTLPM19a.js → chunk-L5ZTLDWV-C9Gzx6GF.js} +1 -1
  16. package/dist/client/assets/{chunk-LZXEDZCA-13gIpIRU.js → chunk-LZXEDZCA-Ceca_Ske.js} +2 -2
  17. package/dist/client/assets/{chunk-ND2GUHAM-Bhl3l4MJ.js → chunk-ND2GUHAM-Cs2auQCc.js} +1 -1
  18. package/dist/client/assets/{chunk-NZK2D7GU-BDZ0gHw4.js → chunk-NZK2D7GU-fssKuUqc.js} +1 -1
  19. package/dist/client/assets/{chunk-O5CBEL6O-C1xjgaqI.js → chunk-O5CBEL6O-BdRwmtR1.js} +1 -1
  20. package/dist/client/assets/{chunk-WU5MYG2G-DXrekGgA.js → chunk-WU5MYG2G-DnWsSIYg.js} +1 -1
  21. package/dist/client/assets/classDiagram-4FO5ZUOK-D79OdDcf.js +1 -0
  22. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CyG7JUxO.js +1 -0
  23. package/dist/client/assets/{dagre-BM42HDAG-ymk8yb4x.js → dagre-BM42HDAG-B71wyESx.js} +1 -1
  24. package/dist/client/assets/{diagram-2AECGRRQ-BFKit5Xx.js → diagram-2AECGRRQ-D7Xht5lG.js} +1 -1
  25. package/dist/client/assets/{diagram-5GNKFQAL-BLuEM5D6.js → diagram-5GNKFQAL-BIL2jzaH.js} +1 -1
  26. package/dist/client/assets/{diagram-KO2AKTUF-_wS_dDU4.js → diagram-KO2AKTUF-CKLHtkTQ.js} +1 -1
  27. package/dist/client/assets/{diagram-LMA3HP47-DXIrjyQ-.js → diagram-LMA3HP47-CoTDrm1f.js} +1 -1
  28. package/dist/client/assets/{diagram-OG6HWLK6-DquYa7lV.js → diagram-OG6HWLK6-a6qcioel.js} +1 -1
  29. package/dist/client/assets/{erDiagram-TEJ5UH35-MKI9p3C-.js → erDiagram-TEJ5UH35-CUTe5tSP.js} +1 -1
  30. package/dist/client/assets/{flowDiagram-I6XJVG4X-DMZ4-2rY.js → flowDiagram-I6XJVG4X-CSDL4PU-.js} +1 -1
  31. package/dist/client/assets/{ganttDiagram-6RSMTGT7-GgzwvVRo.js → ganttDiagram-6RSMTGT7-Ck4JCO9N.js} +1 -1
  32. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-Br_tAiVM.js → gitGraphDiagram-PVQCEYII-D8h23S3l.js} +1 -1
  33. package/dist/client/assets/index-Ckj_syqH.js +287 -0
  34. package/dist/client/assets/index-RM0FaS4q.css +2 -0
  35. package/dist/client/assets/{infoDiagram-5YYISTIA-DbbDZQMC.js → infoDiagram-5YYISTIA-Bq1wj1vH.js} +1 -1
  36. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CqZ2rJxu.js → ishikawaDiagram-YF4QCWOH-C6ry_1gD.js} +1 -1
  37. package/dist/client/assets/{journeyDiagram-JHISSGLW-B29_JOsJ.js → journeyDiagram-JHISSGLW-BCoSw_Ye.js} +1 -1
  38. package/dist/client/assets/{kanban-definition-UN3LZRKU-CESA-TYi.js → kanban-definition-UN3LZRKU-CvHdWXxq.js} +1 -1
  39. package/dist/client/assets/{line-DdPRuRKH.js → line-DDPHAHbi.js} +1 -1
  40. package/dist/client/assets/{mermaid-parser.core-vFFzvyX4.js → mermaid-parser.core-B7v3eJbR.js} +1 -1
  41. package/dist/client/assets/{mermaid.core-DkyZ6FR3.js → mermaid.core-DoJjZ2zS.js} +3 -3
  42. package/dist/client/assets/{mindmap-definition-RKZ34NQL-ChH-rvOD.js → mindmap-definition-RKZ34NQL-D8uwnlrG.js} +1 -1
  43. package/dist/client/assets/{pieDiagram-4H26LBE5-BjrFBvU1.js → pieDiagram-4H26LBE5-B2zLClZg.js} +1 -1
  44. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-2Si58cQa.js → quadrantDiagram-W4KKPZXB-DGGYHTHx.js} +1 -1
  45. package/dist/client/assets/{requirementDiagram-4Y6WPE33-C7VJ8QDP.js → requirementDiagram-4Y6WPE33-JfCBqWur.js} +1 -1
  46. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Boka1d1I.js → sankeyDiagram-5OEKKPKP-D9nUF-4P.js} +1 -1
  47. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-A2g_mJL3.js → sequenceDiagram-3UESZ5HK-DGnNkDzT.js} +1 -1
  48. package/dist/client/assets/{stateDiagram-AJRCARHV-DZN-P8xp.js → stateDiagram-AJRCARHV-CFZlnYcA.js} +1 -1
  49. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BB3Eu4sn.js +1 -0
  50. package/dist/client/assets/{timeline-definition-PNZ67QCA-C_IatSHm.js → timeline-definition-PNZ67QCA-C-KYYKMX.js} +1 -1
  51. package/dist/client/assets/{vennDiagram-CIIHVFJN-CICUDBE3.js → vennDiagram-CIIHVFJN-C3MGIjT1.js} +1 -1
  52. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BStcFc77.js → wardleyDiagram-YWT4CUSO-CUD7E4c3.js} +1 -1
  53. package/dist/client/assets/{xychartDiagram-2RQKCTM6-Cby4OnB9.js → xychartDiagram-2RQKCTM6-CM2Q4-TE.js} +1 -1
  54. package/dist/client/index.html +2 -2
  55. package/dist/server/db.js +1 -2
  56. package/dist/server/db.js.map +1 -1
  57. package/dist/server/index.js +205 -12
  58. package/dist/server/index.js.map +1 -1
  59. package/dist/server/lib/agent.js +76 -16
  60. package/dist/server/lib/agent.js.map +1 -1
  61. package/dist/server/lib/agentPreview.js +41 -0
  62. package/dist/server/lib/agentPreview.js.map +1 -0
  63. package/dist/server/lib/agentRuns.js +15 -0
  64. package/dist/server/lib/agentRuns.js.map +1 -1
  65. package/dist/server/lib/buildExecutionEnvironment.js +1 -1
  66. package/dist/server/lib/buildExecutionEnvironment.js.map +1 -1
  67. package/dist/server/lib/buildSequences.js +31 -0
  68. package/dist/server/lib/buildSequences.js.map +1 -1
  69. package/dist/server/lib/bundleBuildRecovery.js +110 -0
  70. package/dist/server/lib/bundleBuildRecovery.js.map +1 -0
  71. package/dist/server/lib/codexAgentProvider.js +192 -4
  72. package/dist/server/lib/codexAgentProvider.js.map +1 -1
  73. package/dist/server/lib/codexAppServer.js +169 -9
  74. package/dist/server/lib/codexAppServer.js.map +1 -1
  75. package/dist/server/lib/dockerSandboxExecutionEnvironment.js +124 -23
  76. package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -1
  77. package/dist/server/lib/dockerSandboxExecutionProvider.js +6 -2
  78. package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -1
  79. package/dist/server/lib/dockerSandboxNetworkPolicy.js +17 -3
  80. package/dist/server/lib/dockerSandboxNetworkPolicy.js.map +1 -1
  81. package/dist/server/lib/dockerSandboxReleaseProfiles.js +57 -3
  82. package/dist/server/lib/dockerSandboxReleaseProfiles.js.map +1 -1
  83. package/dist/server/lib/executionProfileStore.js +24 -23
  84. package/dist/server/lib/executionProfileStore.js.map +1 -1
  85. package/dist/server/lib/git.js +479 -2
  86. package/dist/server/lib/git.js.map +1 -1
  87. package/dist/server/lib/planModeQuestions.js +1 -1
  88. package/dist/server/lib/planModeQuestions.js.map +1 -1
  89. package/dist/server/lib/preview.js +37 -24
  90. package/dist/server/lib/preview.js.map +1 -1
  91. package/dist/server/lib/promptSkills.js +6 -4
  92. package/dist/server/lib/promptSkills.js.map +1 -1
  93. package/dist/server/lib/run.js +40 -5
  94. package/dist/server/lib/run.js.map +1 -1
  95. package/dist/server/lib/runPreviewCandidate.js +6 -0
  96. package/dist/server/lib/runPreviewCandidate.js.map +1 -0
  97. package/dist/server/lib/tickets.js +4 -1
  98. package/dist/server/lib/tickets.js.map +1 -1
  99. package/dist/server/lib/types.js.map +1 -1
  100. package/dist/server/workers/build.js +3 -3
  101. package/dist/server/workers/build.js.map +1 -1
  102. package/dist/server/workers/chat.js +15 -6
  103. package/dist/server/workers/chat.js.map +1 -1
  104. package/dist/server/workers/followUp.js +5 -1
  105. package/dist/server/workers/followUp.js.map +1 -1
  106. package/dist/server/workers/plan.js +40 -6
  107. package/dist/server/workers/plan.js.map +1 -1
  108. package/dist/server/workers/review.js +2 -2
  109. package/dist/server/workers/review.js.map +1 -1
  110. package/dist/server/workers/specSession.js +2 -2
  111. package/dist/server/workers/specSession.js.map +1 -1
  112. package/package.json +1 -1
  113. package/dist/client/assets/channel-DZI461ra.js +0 -1
  114. package/dist/client/assets/classDiagram-4FO5ZUOK-DWu6cWxw.js +0 -1
  115. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CAI_KWMC.js +0 -1
  116. package/dist/client/assets/index-4RQBXPuO.css +0 -2
  117. package/dist/client/assets/index-X5cdbVG5.js +0 -279
  118. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Cqrxk_FO.js +0 -1
@@ -13,7 +13,9 @@ import { registerRepositoryGraphRoutes } from './lib/repositoryGraphRoutes.js';
13
13
  import { registerExecutionEnvironmentRoutes } from './lib/executionEnvironmentRoutes.js';
14
14
  import { registerExecutionProfileRoutes } from './lib/executionProfileRoutes.js';
15
15
  import { executionProfileSupportsChecks, hasConfiguredCheckPolicy } from './lib/executionProfileCheckPolicy.js';
16
- import { getActiveExecutionProfileRevision } from './lib/executionProfileStore.js';
16
+ import { activateExecutionProfileRevisionInTransaction, getActiveExecutionProfileRevision } from './lib/executionProfileStore.js';
17
+ import { normalizeExecutionProfile } from './lib/executionProfiles.js';
18
+ import { requestExecutionEnvironmentRetirementForProfile } from './lib/executionEnvironments.js';
17
19
  import { registerApprovalRoutes } from './lib/approvalRoutes.js';
18
20
  import { admitForcePush, finalizeGitPushApproval, resumeGitPushApproval } from './lib/gitPushApprovals.js';
19
21
  import { reconcileApprovalRequests } from './lib/approvalReconciliation.js';
@@ -32,7 +34,7 @@ import { resolveSessionTargetForExecution } from './lib/sessionTargets.js';
32
34
  import { createChatMessage, getChatMessage, updateChatMessageContent } from './lib/chatMessages.js';
33
35
  import { attachChatTicketProposalsToMessageContent } from './lib/chatTicketProposals.js';
34
36
  import { createCorsOriginResolver, parseCorsOrigins } from './lib/cors.js';
35
- import { abortGitOperation, branchExistsLocally, commitGitChanges, createWorktreeAsync, deleteLocalBranch, deleteWorktree, getBundleReviewDiffForCwd, getGitDiffDataAsync, getGitDiffFiles, getGitDiffFilesAsync, getGitStatus, getGitStatusAsync, getGitUnifiedDiff, getGitUnifiedDiffAsync, getLocalProjectBranch, getProjectBranch, getProjectBranchAsync, getProjectBranchSuggestions, getReviewDiffDataAsync, getSelectedGitUnifiedDiff, getUnpushedCommitDiffForCwd, getUnpushedCommitSummaryForCwd, getUnpushedCommitSummaryForCwdAsync, hasKnownBranchRef, listUnpushedCommitsForCwd, pullGitBranch, pushCurrentBranch, rebaseGitBranchOntoBase, resolveExistingWorktreePath, resolveWorktreePath, squashUnpushedCommitsForCwd, summarizeTicketDiffFiles, switchProjectBranch, syncWorktreeFilesAsync, undoLatestUnpushedCommitForCwd, UnpushedCommitDiffSelectionError } from './lib/git.js';
37
+ import { abortGitOperation, branchExistsLocally, commitGitChanges, continueGitRebase, createWorktreeAsync, deleteLocalBranch, deleteWorktree, getActiveRebaseBranch, getBundleReviewDiffForCwd, getGitDiffDataAsync, getGitDiffFiles, getGitDiffFilesAsync, getGitStatus, getGitStatusAsync, getGitUnifiedDiff, getGitUnifiedDiffAsync, getLocalProjectBranch, getProjectBranch, getProjectBranchAsync, getProjectBranchSuggestions, getRebaseStagedDiff, getReviewDiffDataAsync, getSelectedGitUnifiedDiff, getUnpushedCommitDiffForCwd, getUnpushedCommitSummaryForCwd, getUnpushedCommitSummaryForCwdAsync, hasKnownBranchRef, listUnpushedCommitsForCwd, pullGitBranch, pushCurrentBranch, rebaseGitBranchOntoBase, resolveExistingWorktreePath, resolveWorktreePath, skipGitRebaseStep, squashUnpushedCommitsForCwd, summarizeTicketDiffFiles, switchProjectBranch, syncWorktreeFilesAsync, undoLatestUnpushedCommitForCwd, UnpushedCommitDiffSelectionError } from './lib/git.js';
36
38
  import config from './lib/config.js';
37
39
  import { getActiveTool, initializeActiveTool, setActiveTool } from './lib/activeTool.js';
38
40
  import { autoConfigProject, ProjectAutoConfigError } from './lib/projectAutoConfig.js';
@@ -45,6 +47,7 @@ import { refreshChatSessionUsageSnapshot, refreshSpecSessionUsageSnapshot, stopA
45
47
  import { runTrackedLightweightPrompt } from './lib/lightweightPrompt.js';
46
48
  import { advanceBuildChain, startBuildChain, stopBuildChain } from './lib/buildChains.js';
47
49
  import { activateQueuedBuildSequenceTicket, bindBuildSequenceTicketExecutionRun, compensateBuildSequenceAcceptance, enqueueBundledBuild, getDependencyOrderedBundleTicketIds, getBuildSequenceIdForTicket, getBuildSequenceTicketExecutionProfileSelection, hasActiveSequenceForBundle, releaseQueuedBuildSequenceTicketExecutionRunForRetry, removeTicketFromBuildSequence, stopBuildSequence, } from './lib/buildSequences.js';
50
+ import { resumeRemainingBundleBuilds } from './lib/bundleBuildRecovery.js';
48
51
  import { createExecutionProfileSelection, createServiceExecutionProfileSelection, executionProfileSelectionMetadata, validateExecutionProfileSelection } from './lib/executionRunAuthority.js';
49
52
  import { prepareTicketForBuild } from './lib/buildFlow.js';
50
53
  import { getActiveBundleRepairBlocker, getBundlePlanMutationBlockerById, shouldBlockPlanForBundleMutationById, } from './lib/bundleActivity.js';
@@ -99,7 +102,7 @@ import { dispatchGitHubWorkflow, getGitHubWorkflowDispatchConfig, getGitHubWorkf
99
102
  import { clearAllGitHubActionsSessions, getActiveTrackedRunCount, getTrackedGitHubActionsRuns, startGitHubActionsPolling, trackGitHubActionsRun, } from './lib/integrations/githubActionsSessions.js';
100
103
  import { reconcileStartupExecutions } from './lib/executionReconciliation.js';
101
104
  import { cleanupProjectExecutionEnvironments, cleanupExecutionEnvironmentsForTarget, ExecutionEnvironmentCleanupError, reconcileOrphanedExecutionEnvironments, reconcileExecutionEnvironments, reconcileExecutionEnvironmentLifecycleOperations, reconcileProductionExecutionEnvironmentBindings, } from './lib/executionEnvironmentReconciliation.js';
102
- import { createExecutionTargetKey } from './lib/executionTargets.js';
105
+ import { createExecutionTargetKey, resolveExecutionTarget, resolveProjectRootExecutionTarget } from './lib/executionTargets.js';
103
106
  import { getExecutionEnvironmentContextForRun } from './lib/executionEnvironmentContexts.js';
104
107
  import { PlanningReferenceError, resolveExternalPlanningDescription } from './lib/integrations/planning.js';
105
108
  import { refreshIfNeeded as refreshAssignedIssues, clearCachedAssignedIssues } from './lib/integrations/assignedIssuesCache.js';
@@ -1223,12 +1226,13 @@ const resolveTicketGitWorkspaceFromContext = (ticket) => {
1223
1226
  };
1224
1227
  const resolveProjectRootGitWorkspace = (project) => {
1225
1228
  const branchState = getProjectBranch(project, { includeDiffStats: false });
1226
- if (branchState.status !== 'ready' || !branchState.branch) {
1229
+ const branch = branchState.status === 'ready' ? branchState.branch : getActiveRebaseBranch(project.repo_path);
1230
+ if (!branch) {
1227
1231
  return { error: 'Project root must be on a named branch', status: 409 };
1228
1232
  }
1229
1233
  return {
1230
1234
  project,
1231
- branch: branchState.branch,
1235
+ branch,
1232
1236
  cwd: project.repo_path,
1233
1237
  };
1234
1238
  };
@@ -3728,6 +3732,63 @@ app.get('/tickets/:id/git-status', async (req, res) => {
3728
3732
  const refreshRemote = req.query.refresh_remote === 'true';
3729
3733
  return res.json(await getGitStatusAsync(workspace.cwd, workspace.branch, workspace.project, { refreshRemote }));
3730
3734
  });
3735
+ app.get('/tickets/:id/rebase-staged-diff', (req, res) => {
3736
+ const ticket = getTicketRouteContext(req.params.id);
3737
+ if (!ticket || !matchesTicketProjectContext(ticket, req)) {
3738
+ return res.status(404).json({ error: 'Not found' });
3739
+ }
3740
+ const workspace = resolveTicketGitWorkspaceFromContext(ticket);
3741
+ if ('error' in workspace) {
3742
+ return res.status(workspace.status).json({ error: workspace.error });
3743
+ }
3744
+ return res.json(getRebaseStagedDiff(workspace.cwd));
3745
+ });
3746
+ app.post('/tickets/:id/git-rebase-continue', async (req, res) => {
3747
+ const ticket = getTicketRouteContext(req.params.id);
3748
+ if (!ticket || !matchesTicketProjectContext(ticket, req)) {
3749
+ return res.status(404).json({ error: 'Not found' });
3750
+ }
3751
+ const workspace = resolveTicketGitWorkspaceFromContext(ticket);
3752
+ if ('error' in workspace) {
3753
+ return res.status(workspace.status).json({ error: workspace.error });
3754
+ }
3755
+ const result = await continueGitRebase(workspace.cwd, workspace.branch, workspace.project, {
3756
+ expectedStepSignature: typeof req.body?.expected_step_signature === 'string' ? req.body.expected_step_signature : '',
3757
+ branch: typeof req.body?.branch === 'string' ? req.body.branch.trim() : '',
3758
+ selectedPaths: Array.isArray(req.body?.selected_paths) ? req.body.selected_paths.filter((path) => typeof path === 'string') : [],
3759
+ acknowledgedPaths: Array.isArray(req.body?.acknowledged_paths) ? req.body.acknowledged_paths.filter((path) => typeof path === 'string') : [],
3760
+ });
3761
+ return res.status(result.outcome === 'stale_step' || result.outcome === 'rejected' ? 409 : 200).json(result);
3762
+ });
3763
+ app.post('/tickets/:id/git-rebase-skip', async (req, res) => {
3764
+ const ticket = getTicketRouteContext(req.params.id);
3765
+ if (!ticket || !matchesTicketProjectContext(ticket, req)) {
3766
+ return res.status(404).json({ error: 'Not found' });
3767
+ }
3768
+ const workspace = resolveTicketGitWorkspaceFromContext(ticket);
3769
+ if ('error' in workspace) {
3770
+ return res.status(workspace.status).json({ error: workspace.error });
3771
+ }
3772
+ const result = await skipGitRebaseStep(workspace.cwd, workspace.branch, workspace.project, typeof req.body?.expected_step_signature === 'string' ? req.body.expected_step_signature : '', typeof req.body?.branch === 'string' ? req.body.branch.trim() : '');
3773
+ return res.status(result.outcome === 'stale_step' || result.outcome === 'rejected' ? 409 : 200).json(result);
3774
+ });
3775
+ app.post('/tickets/:id/git-abort', async (req, res) => {
3776
+ const ticket = getTicketRouteContext(req.params.id);
3777
+ if (!ticket || !matchesTicketProjectContext(ticket, req)) {
3778
+ return res.status(404).json({ error: 'Not found' });
3779
+ }
3780
+ const workspace = resolveTicketGitWorkspaceFromContext(ticket);
3781
+ if ('error' in workspace) {
3782
+ return res.status(workspace.status).json({ error: workspace.error });
3783
+ }
3784
+ try {
3785
+ await abortGitOperation(workspace.cwd);
3786
+ return res.json(getGitStatus(workspace.cwd, workspace.branch, workspace.project));
3787
+ }
3788
+ catch (error) {
3789
+ return res.status(409).json({ error: getErrorMessage(error) || 'Unable to abort the current git operation right now.' });
3790
+ }
3791
+ });
3731
3792
  app.get('/tickets/:id/git-commits', async (req, res) => {
3732
3793
  const ticket = getTicketRouteContext(req.params.id);
3733
3794
  if (!ticket) {
@@ -4453,6 +4514,24 @@ app.post('/bundles/:id/build', (req, res) => {
4453
4514
  }
4454
4515
  res.status(buildResult.status).json(buildResult.value);
4455
4516
  });
4517
+ app.post('/bundles/:id/build/resume', (req, res) => {
4518
+ const result = getRequiredProject(req);
4519
+ if ('error' in result) {
4520
+ return res.status(400).json({ error: result.error });
4521
+ }
4522
+ const resumeResult = resumeRemainingBundleBuilds({
4523
+ projectId: result.project.id,
4524
+ bundleId: req.params.id,
4525
+ broadcaster: io,
4526
+ });
4527
+ if (!resumeResult.ok) {
4528
+ return res.status(resumeResult.status).json({
4529
+ error: resumeResult.error,
4530
+ ...('details' in resumeResult ? resumeResult.details : {}),
4531
+ });
4532
+ }
4533
+ return res.status(resumeResult.status).json(serializeBundleDetails(resumeResult.project, resumeResult.bundle, { target_ticket_id: resumeResult.targetTicketId }));
4534
+ });
4456
4535
  app.post('/bundles/:id/review', (req, res) => {
4457
4536
  const result = getRequiredProject(req);
4458
4537
  if ('error' in result) {
@@ -6667,7 +6746,7 @@ app.post('/planning-agent', async (req, res) => {
6667
6746
  if ('error' in requestedBundleSelection) {
6668
6747
  return res.status(requestedBundleSelection.status).json({ error: requestedBundleSelection.error });
6669
6748
  }
6670
- const bundleSelection = requestedBundleSelection.bundleId === null
6749
+ const bundleSelection = requestedBundleSelection.bundleId === null && !requestedBundleSelection.provided
6671
6750
  ? (() => {
6672
6751
  const bundle = createAutoPlanningBundle(project.id);
6673
6752
  autoCreatedBundle = bundle;
@@ -6678,6 +6757,29 @@ app.post('/planning-agent', async (req, res) => {
6678
6757
  };
6679
6758
  })()
6680
6759
  : requestedBundleSelection;
6760
+ const planningExecutionTarget = autoCreatedBundle
6761
+ ? null
6762
+ : await (async () => {
6763
+ try {
6764
+ if (bundleSelection.bundleId && bundleSelection.branch) {
6765
+ return await resolveExecutionTarget({
6766
+ project,
6767
+ descriptor: {
6768
+ kind: 'bundle-worktree',
6769
+ bundleId: bundleSelection.bundleId,
6770
+ branch: bundleSelection.branch,
6771
+ },
6772
+ });
6773
+ }
6774
+ if (bundleSelection.provided && bundleSelection.bundleId === null) {
6775
+ return await resolveProjectRootExecutionTarget(project);
6776
+ }
6777
+ }
6778
+ catch {
6779
+ // Preview context is best-effort and must not fail or redirect planning.
6780
+ }
6781
+ return null;
6782
+ })();
6681
6783
  const plannerOptions = {
6682
6784
  tool,
6683
6785
  model: typeof model === 'string' ? model : null,
@@ -6711,6 +6813,7 @@ app.post('/planning-agent', async (req, res) => {
6711
6813
  const executionPlannerOptions = {
6712
6814
  ...plannerOptions,
6713
6815
  executionContext,
6816
+ executionTarget: planningExecutionTarget ?? undefined,
6714
6817
  agentRunParent: { parentType: 'planning', parentId: project.id, io },
6715
6818
  };
6716
6819
  transitionExecutionRun({
@@ -7734,16 +7837,73 @@ app.post('/projects/:id/git-rebase', async (req, res) => {
7734
7837
  await rebaseGitBranchOntoBase(workspace.cwd, workspace.branch, workspace.project, baseBranch || null);
7735
7838
  }
7736
7839
  catch (error) {
7840
+ const status = getGitStatus(workspace.cwd, workspace.branch, workspace.project);
7841
+ if (status.operation_state === 'rebase' && status.rebase_step) {
7842
+ return res.json({ outcome: 'paused', status });
7843
+ }
7737
7844
  return res.status(409).json({ error: getErrorMessage(error) || 'Unable to rebase the current branch right now.' });
7738
7845
  }
7739
7846
  try {
7740
- return res.json(getGitStatus(workspace.cwd, workspace.branch, workspace.project));
7847
+ return res.json({
7848
+ outcome: 'completed',
7849
+ status: getGitStatus(workspace.cwd, workspace.branch, workspace.project),
7850
+ });
7741
7851
  }
7742
7852
  catch (error) {
7743
7853
  console.error(`Failed to read branch after rebase for project ${project.id}:`, error);
7744
7854
  return res.status(500).json({ error: 'Unable to determine project branch' });
7745
7855
  }
7746
7856
  });
7857
+ app.post('/projects/:id/git-rebase-continue', async (req, res) => {
7858
+ const project = getProjectById(req.params.id);
7859
+ if (!project) {
7860
+ return res.status(404).json({ error: 'Not found' });
7861
+ }
7862
+ const workspace = resolveProjectTargetGitWorkspace(project);
7863
+ if ('error' in workspace) {
7864
+ return res.status(workspace.status).json({ error: workspace.error });
7865
+ }
7866
+ const expectedStepSignature = typeof req.body?.expected_step_signature === 'string' ? req.body.expected_step_signature : '';
7867
+ const branch = typeof req.body?.branch === 'string' ? req.body.branch.trim() : '';
7868
+ const selectedPaths = Array.isArray(req.body?.selected_paths)
7869
+ ? req.body.selected_paths.filter((path) => typeof path === 'string')
7870
+ : [];
7871
+ const acknowledgedPaths = Array.isArray(req.body?.acknowledged_paths)
7872
+ ? req.body.acknowledged_paths.filter((path) => typeof path === 'string')
7873
+ : [];
7874
+ const result = await continueGitRebase(workspace.cwd, workspace.branch, workspace.project, {
7875
+ expectedStepSignature,
7876
+ branch,
7877
+ selectedPaths,
7878
+ acknowledgedPaths,
7879
+ });
7880
+ return res.status(result.outcome === 'stale_step' || result.outcome === 'rejected' ? 409 : 200).json(result);
7881
+ });
7882
+ app.get('/projects/:id/rebase-staged-diff', (req, res) => {
7883
+ const project = getProjectById(req.params.id);
7884
+ if (!project) {
7885
+ return res.status(404).json({ error: 'Not found' });
7886
+ }
7887
+ const workspace = resolveProjectTargetGitWorkspace(project);
7888
+ if ('error' in workspace) {
7889
+ return res.status(workspace.status).json({ error: workspace.error });
7890
+ }
7891
+ return res.json(getRebaseStagedDiff(workspace.cwd));
7892
+ });
7893
+ app.post('/projects/:id/git-rebase-skip', async (req, res) => {
7894
+ const project = getProjectById(req.params.id);
7895
+ if (!project) {
7896
+ return res.status(404).json({ error: 'Not found' });
7897
+ }
7898
+ const workspace = resolveProjectTargetGitWorkspace(project);
7899
+ if ('error' in workspace) {
7900
+ return res.status(workspace.status).json({ error: workspace.error });
7901
+ }
7902
+ const expectedStepSignature = typeof req.body?.expected_step_signature === 'string' ? req.body.expected_step_signature : '';
7903
+ const branch = typeof req.body?.branch === 'string' ? req.body.branch.trim() : '';
7904
+ const result = await skipGitRebaseStep(workspace.cwd, workspace.branch, workspace.project, expectedStepSignature, branch);
7905
+ return res.status(result.outcome === 'stale_step' || result.outcome === 'rejected' ? 409 : 200).json(result);
7906
+ });
7747
7907
  app.post('/projects/:id/git-abort', async (req, res) => {
7748
7908
  const project = getProjectById(req.params.id);
7749
7909
  if (!project) {
@@ -8174,6 +8334,7 @@ app.patch('/projects/:id', async (req, res) => {
8174
8334
  const nextReviewerVariant = nextReviewerModel
8175
8335
  ? (hasOwn(validation.values, 'reviewer_variant') ? reviewer_variant ?? null : project.reviewer_variant)
8176
8336
  : null;
8337
+ let activatedCheckProfileFingerprint = null;
8177
8338
  const applyUpdate = db.transaction(() => {
8178
8339
  const currentProject = getProjectById(project.id);
8179
8340
  if (!currentProject || JSON.stringify(currentProject) !== JSON.stringify(project)) {
@@ -8208,15 +8369,44 @@ app.patch('/projects/:id', async (req, res) => {
8208
8369
  post_build_check_definition_ids: nextPostBuildCheckDefinitionIds,
8209
8370
  auto_fix_check_definition_ids: nextAutoFixCheckDefinitionIds,
8210
8371
  });
8211
- if (hasConfiguredChecks && project.active_execution_profile_revision_id) {
8372
+ if (hasConfiguredChecks) {
8212
8373
  const activeProfile = getActiveExecutionProfileRevision(project.id);
8213
- if (!activeProfile || !executionProfileSupportsChecks(activeProfile.profile)) {
8374
+ if (!activeProfile) {
8214
8375
  return {
8215
- error: 'Configured check policies require an execution profile with an explicit check template',
8216
- reason: 'check_template_required',
8217
- status: 409,
8376
+ error: 'Active execution profile is unavailable',
8377
+ reason: 'profile_unavailable',
8378
+ status: 500,
8218
8379
  };
8219
8380
  }
8381
+ if (!executionProfileSupportsChecks(activeProfile.profile)) {
8382
+ const normalizedProfile = normalizeExecutionProfile({
8383
+ ...activeProfile.profile,
8384
+ eligible_workloads: [...activeProfile.profile.eligible_workloads, 'check'],
8385
+ check_template_policy: { mode: 'agent_template', agent: 'opencode' },
8386
+ });
8387
+ if (!normalizedProfile.ok) {
8388
+ return {
8389
+ error: normalizedProfile.error,
8390
+ reason: 'profile_invalid',
8391
+ status: 500,
8392
+ };
8393
+ }
8394
+ const activation = activateExecutionProfileRevisionInTransaction({
8395
+ projectId: project.id,
8396
+ expectedActiveRevisionId: activeProfile.id,
8397
+ profile: normalizedProfile.profile,
8398
+ });
8399
+ if (!activation.ok) {
8400
+ return {
8401
+ error: 'The active execution profile changed; retry the update',
8402
+ reason: 'stale_profile_revision',
8403
+ status: 409,
8404
+ };
8405
+ }
8406
+ if (activation.revision.id !== activeProfile.id) {
8407
+ activatedCheckProfileFingerprint = activation.revision.fingerprint;
8408
+ }
8409
+ }
8220
8410
  }
8221
8411
  updateProject.run(name ?? project.name, repo_path ?? project.repo_path, project.build_execution_provider, hasOwn(validation.values, 'run_setup') ? run_setup : project.run_setup, hasOwn(validation.values, 'run_services') ? run_services : project.run_services, nextCheckDefinitions, nextRequiredCheckDefinitionIds, nextPreReviewCheckDefinitionIds, nextPostBuildCheckDefinitionIds, nextAutoFixCheckDefinitionIds, hasOwn(validation.values, 'test_commands') ? test_commands : project.test_commands, hasOwn(validation.values, 'run_ide') ? run_ide : project.run_ide, hasOwn(validation.values, 'preview_service_name') ? preview_service_name : project.preview_service_name, hasOwn(validation.values, 'preview_path') ? preview_path : project.preview_path, hasOwn(validation.values, 'preview_capability_mode') ? preview_capability_mode : project.preview_capability_mode, hasOwn(validation.values, 'helper_model') ? helper_model : project.helper_model, hasOwn(validation.values, 'helper_variant') ? helper_variant : project.helper_variant, hasOwn(validation.values, 'helper_models_json') ? helper_models_json : project.helper_models_json, nextReviewerModel, nextReviewerVariant, hasOwn(validation.values, 'reviewer_models_json') ? reviewer_models_json : project.reviewer_models_json, 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);
8222
8412
  if (hasOwn(validation.values, 'linked_project_ids')) {
@@ -8243,6 +8433,9 @@ app.patch('/projects/:id', async (req, res) => {
8243
8433
  ...('reason' in updateResult ? { reason: updateResult.reason } : {}),
8244
8434
  });
8245
8435
  }
8436
+ if (activatedCheckProfileFingerprint) {
8437
+ requestExecutionEnvironmentRetirementForProfile(project.id, activatedCheckProfileFingerprint);
8438
+ }
8246
8439
  const updated = db.prepare('SELECT * FROM projects WHERE id = ?').get(req.params.id);
8247
8440
  res.json(serializeProject(updated ?? null));
8248
8441
  });