@straiffi/archon 1.10.1 → 1.10.2
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-CdDT5tgr.js +1 -0
- package/dist/client/assets/{GitHubActionsDialog-BABPYwJP.js → GitHubActionsDialog-NdYtgMhg.js} +1 -1
- package/dist/client/assets/{VerificationDialog-LN87YY0r.js → VerificationDialog-BfIKtVjt.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DBXhcjPI.js → architectureDiagram-3BPJPVTR-C4zoWnXM.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-c3auwNH7.js → blockDiagram-GPEHLZMM-ZhRwV8ma.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-DH2YznEQ.js → c4Diagram-AAUBKEIU-CA2USxCJ.js} +1 -1
- package/dist/client/assets/channel-C4I-VlJu.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-D0_MoyXZ.js → chunk-2J33WTMH-CY32Brnt.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-DLvSp1DN.js → chunk-3OPIFGDE-H70UH7rH.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-B4sX8Htk.js → chunk-5ZQYHXKU-DC1dllSt.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-CkdnShG1.js → chunk-727SXJPM-DVIgI7hM.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-BdPfgkcs.js → chunk-AQP2D5EJ-gwSYEPou.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-CK-DpVF6.js → chunk-CSCIHK7Q-Z1cfABPc.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-DSbTWVl2.js → chunk-KSCS5N6A-DFoW6dtq.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-DuQ4EPLl.js → chunk-L5ZTLDWV-CmQbbP8b.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-CtpoXWMY.js → chunk-LZXEDZCA-Ba16nX-R.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-CDfNOP6o.js → chunk-ND2GUHAM-Bc7u1Zqm.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-s6ReY4ev.js → chunk-NZK2D7GU-DNXYx7JX.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-DxqYGKhS.js → chunk-O5CBEL6O-Ba00cuZ5.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-BvrhxyV8.js → chunk-WU5MYG2G-SJ_ny5dU.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-Ca3KxBnW.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CSpMessw.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-DEK_rftr.js → dagre-BM42HDAG-CL2dKbj9.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-CpobcZnv.js → diagram-2AECGRRQ-DQq1qZ0l.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-zL1D1L_8.js → diagram-5GNKFQAL-Zf0YQuRe.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-gyW-Vc7c.js → diagram-KO2AKTUF-DcUxL9SG.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DDEYc8sh.js → diagram-LMA3HP47-BAIixEu7.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BtUrfJnE.js → diagram-OG6HWLK6-Dhhjm84p.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-qGrmpmmk.js → erDiagram-TEJ5UH35-BcQOacBP.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-DO1Nm1FA.js → flowDiagram-I6XJVG4X-BZIJqLp3.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DGuMVCAc.js → ganttDiagram-6RSMTGT7-DFC6qgrY.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CehPAc8-.js → gitGraphDiagram-PVQCEYII-Ds0nwSU0.js} +1 -1
- package/dist/client/assets/index-Bg3l17L3.css +2 -0
- package/dist/client/assets/index-D_KmViSu.js +276 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BkRaMDId.js → infoDiagram-5YYISTIA-DfDrR5Mz.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-B45ubODJ.js → ishikawaDiagram-YF4QCWOH-B2v4Byji.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BLxrlitK.js → journeyDiagram-JHISSGLW-CO6laklO.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-DmyeJDyy.js → kanban-definition-UN3LZRKU-BziFO199.js} +1 -1
- package/dist/client/assets/{line-BhwjsX6t.js → line-Vb0A8-Oe.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-CPvivy_u.js → mermaid-parser.core-Bm3Xv0Zt.js} +1 -1
- package/dist/client/assets/{mermaid.core-Dr0kld-g.js → mermaid.core-DXBRp0XG.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-dfudPzBR.js → mindmap-definition-RKZ34NQL-4GueJvPT.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BhsIQVNX.js → pieDiagram-4H26LBE5-Djy0sVJR.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CAKxScLD.js → quadrantDiagram-W4KKPZXB-3rWAi4K5.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-Br6jIbke.js → requirementDiagram-4Y6WPE33-D7-WCnjH.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BqujNgnY.js → sankeyDiagram-5OEKKPKP-B4-3BUQ2.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Dr_VM_ei.js → sequenceDiagram-3UESZ5HK-DCWomuSc.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CDbSbbTW.js → stateDiagram-AJRCARHV-DpsWWFaO.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-BE_IAuYt.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CnuLuWDs.js → timeline-definition-PNZ67QCA-B0Mh4MHF.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-CVAhxdBZ.js → vennDiagram-CIIHVFJN-Dpxr8LTG.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Dmczey27.js → wardleyDiagram-YWT4CUSO-BdAz5ERd.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-Bl6JGLCU.js → xychartDiagram-2RQKCTM6-BV9Ah-jk.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +640 -0
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +787 -124
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agentCatalog.js +35 -0
- package/dist/server/lib/agentCatalog.js.map +1 -0
- package/dist/server/lib/agentModelConfig.js +151 -0
- package/dist/server/lib/agentModelConfig.js.map +1 -0
- package/dist/server/lib/agentRuns.js +1 -0
- package/dist/server/lib/agentRuns.js.map +1 -1
- package/dist/server/lib/automationCheckGate.js +98 -9
- package/dist/server/lib/automationCheckGate.js.map +1 -1
- package/dist/server/lib/automationLoopAgentEvidence.js +42 -0
- package/dist/server/lib/automationLoopAgentEvidence.js.map +1 -0
- package/dist/server/lib/automationLoopProjection.js +339 -0
- package/dist/server/lib/automationLoopProjection.js.map +1 -0
- package/dist/server/lib/automationProgression.js +115 -6
- package/dist/server/lib/automationProgression.js.map +1 -1
- package/dist/server/lib/automationReconciliation.js +27 -11
- package/dist/server/lib/automationReconciliation.js.map +1 -1
- package/dist/server/lib/automationResumeDecision.js +55 -15
- package/dist/server/lib/automationResumeDecision.js.map +1 -1
- package/dist/server/lib/automationReviewGate.js +352 -26
- package/dist/server/lib/automationReviewGate.js.map +1 -1
- package/dist/server/lib/buildFlow.js +12 -0
- package/dist/server/lib/buildFlow.js.map +1 -1
- package/dist/server/lib/bundleReviewOperations.js +40 -23
- package/dist/server/lib/bundleReviewOperations.js.map +1 -1
- package/dist/server/lib/chatOperations.js +26 -4
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/checkAutoFix.js +5 -4
- package/dist/server/lib/checkAutoFix.js.map +1 -1
- package/dist/server/lib/checkAutoFixDetails.js +54 -9
- package/dist/server/lib/checkAutoFixDetails.js.map +1 -1
- package/dist/server/lib/checkGateEvaluations.js +6 -1
- package/dist/server/lib/checkGateEvaluations.js.map +1 -1
- package/dist/server/lib/checkRepair.js +30 -0
- package/dist/server/lib/checkRepair.js.map +1 -1
- package/dist/server/lib/claudeAgentProvider.js +19 -0
- package/dist/server/lib/claudeAgentProvider.js.map +1 -1
- package/dist/server/lib/executionRuns.js +17 -3
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/executionTimeline.js +3 -0
- package/dist/server/lib/executionTimeline.js.map +1 -1
- package/dist/server/lib/lightweightPrompt.js +13 -40
- package/dist/server/lib/lightweightPrompt.js.map +1 -1
- package/dist/server/lib/mobileAccess.js +47 -3
- package/dist/server/lib/mobileAccess.js.map +1 -1
- package/dist/server/lib/modelResolutionErrors.js +24 -0
- package/dist/server/lib/modelResolutionErrors.js.map +1 -0
- package/dist/server/lib/models.js +9 -9
- package/dist/server/lib/models.js.map +1 -1
- package/dist/server/lib/projectAutoConfig.js +15 -52
- package/dist/server/lib/projectAutoConfig.js.map +1 -1
- package/dist/server/lib/projectMemoryScan.js +15 -9
- package/dist/server/lib/projectMemoryScan.js.map +1 -1
- package/dist/server/lib/projects.js +59 -4
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/reviewRepairCompletion.js +126 -0
- package/dist/server/lib/reviewRepairCompletion.js.map +1 -0
- package/dist/server/lib/reviewRepairIterationRecords.js +149 -0
- package/dist/server/lib/reviewRepairIterationRecords.js.map +1 -0
- package/dist/server/lib/reviewRepairIterations.js +590 -0
- package/dist/server/lib/reviewRepairIterations.js.map +1 -0
- package/dist/server/lib/reviewRepairReconciliation.js +588 -0
- package/dist/server/lib/reviewRepairReconciliation.js.map +1 -0
- package/dist/server/lib/reviewerConfig.js +18 -7
- package/dist/server/lib/reviewerConfig.js.map +1 -1
- package/dist/server/lib/run.js +7 -2
- package/dist/server/lib/run.js.map +1 -1
- package/dist/server/lib/specArtifact.js +1 -1
- package/dist/server/lib/specArtifact.js.map +1 -1
- package/dist/server/lib/specGraphFeature.js +2 -2
- package/dist/server/lib/specGraphFeature.js.map +1 -1
- package/dist/server/lib/specOperations.js +26 -4
- package/dist/server/lib/specOperations.js.map +1 -1
- package/dist/server/lib/specRepositoryEvidenceFormatting.js +2 -2
- package/dist/server/lib/specRepositoryEvidenceFormatting.js.map +1 -1
- package/dist/server/lib/specRepositoryImpact.js +3 -3
- package/dist/server/lib/specRepositoryImpact.js.map +1 -1
- package/dist/server/lib/specReviewContext.js +7 -1
- package/dist/server/lib/specReviewContext.js.map +1 -1
- package/dist/server/lib/specReviewOperations.js +20 -7
- package/dist/server/lib/specReviewOperations.js.map +1 -1
- package/dist/server/lib/specSnapshotEvidence.js +3 -3
- package/dist/server/lib/specSnapshotEvidence.js.map +1 -1
- package/dist/server/lib/ticketAutomation.js +9 -11
- package/dist/server/lib/ticketAutomation.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +21 -11
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +3 -1
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/ticketSettingsOperations.js +9 -0
- package/dist/server/lib/ticketSettingsOperations.js.map +1 -1
- package/dist/server/lib/ticketWorkflowOperations.js +2 -6
- package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
- package/dist/server/lib/tickets.js +16 -6
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/lib/types.js +45 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/workers/followUp.js +76 -1
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/review.js +292 -60
- package/dist/server/workers/review.js.map +1 -1
- package/dist/server/workers/specReview.js +17 -8
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +33 -23
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/ActivityView-C5OrI0uK.js +0 -1
- package/dist/client/assets/channel-CYsnLOcX.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CElk31Q4.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-lnAahwmt.js +0 -1
- package/dist/client/assets/index-1CokwSFm.css +0 -2
- package/dist/client/assets/index-DtefHOHC.js +0 -276
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-p-kfFJi7.js +0 -1
|
@@ -23,17 +23,21 @@ import { captureStageBaseline, captureStageSuccess } from '../lib/ticketUndo.js'
|
|
|
23
23
|
import { beginTicketThinkingRun, bindTicketThinkingMessage } from '../lib/thinkingState.js';
|
|
24
24
|
import { autoParkTicketIfStale, getTicket, resolveTicketBranch, resolveTicketTool, resolveTicketWorkerKey } from '../lib/tickets.js';
|
|
25
25
|
import { createAgentRun, emitAgentRunsUpdated, emitExecutionAgentRunsUpdated, getAgentRun, listAgentRunsForExecutionRun, terminalizeAgentRunsForExecutionRun, } from '../lib/agentRuns.js';
|
|
26
|
-
import { buildAutomationFixInstruction, buildAutomationFixStatusMessage, decideReviewAutomation, depthAtLeast, getBundleAutomationState, resetBundleAutomationLoop, resolveAutomationConfig,
|
|
26
|
+
import { buildAutomationFixInstruction, buildAutomationFixStatusMessage, countBlockingFindings, decideReviewAutomation, depthAtLeast, getBundleAutomationState, resetBundleAutomationLoop, resolveAutomationConfig, } from '../lib/ticketAutomation.js';
|
|
27
27
|
import { runAutomationCommitChain } from '../lib/ticketAutomationCommit.js';
|
|
28
28
|
import { submitTicketFollowUp } from '../lib/ticketFollowUpOperations.js';
|
|
29
|
-
import { completeAutomationProgression,
|
|
29
|
+
import { completeAutomationProgressionInTransaction, completeAutomationProgression, completeAutomationReviewFixActionInTransaction, createAutomationReviewFixInTransaction, ensureAutomationProgression, finishAutomationReviewFix, pauseAutomationProgression, resolveProgressionForChild, waitAutomationProgression, } from '../lib/automationProgression.js';
|
|
30
|
+
import { assertAutomationAuthorizationCurrent, assertAutomationBoundaryNotRequired, AutomationCheckGateError, } from '../lib/automationCheckGate.js';
|
|
31
|
+
import { attachReviewRepairActionEnvelopeInTransaction, attachReviewRepairActionInTransaction, appendReviewRepairIterationDecisionInTransaction, attachReviewRepairResultInTransaction, claimReviewRepairIterationInTransaction, getReviewRepairIteration, getReviewRepairIterationByVerification, pauseReviewRepairIteration, pauseReviewRepairIterationInTransaction, terminalizeReviewRepairIterationInTransaction, } from '../lib/reviewRepairIterations.js';
|
|
30
32
|
import { formatBuildOpenQuestionAnswersPrompt, listAnsweredBuildOpenQuestionsForBundle } from '../lib/buildOpenQuestions.js';
|
|
31
33
|
import { validateWorkflowContext } from '../lib/types.js';
|
|
32
|
-
import {
|
|
34
|
+
import { isModelResolutionError } from '../lib/modelResolutionErrors.js';
|
|
33
35
|
import { assertProviderSessionAuthorityMatches, createExecutionProfileSelectionMetadata } from '../lib/executionRunAuthority.js';
|
|
34
36
|
import { classifyTicketExecutionTarget, resolveExecutionTarget } from '../lib/executionTargets.js';
|
|
35
37
|
import { resolveWorkloadExecutionEnvironment } from '../lib/workloadExecutionEnvironment.js';
|
|
36
38
|
import { getModelProvider } from '../lib/models.js';
|
|
39
|
+
import { captureCheckWorkspaceIdentity } from '../lib/checkWorkspaceIdentity.js';
|
|
40
|
+
import { persistReviewCompletionAutomationInTransaction, } from '../lib/reviewRepairCompletion.js';
|
|
37
41
|
const getErrorMessage = (error) => {
|
|
38
42
|
return error instanceof Error ? error.message : String(error);
|
|
39
43
|
};
|
|
@@ -368,7 +372,7 @@ Every finding must set \`file_path\` to a path in \`<review_scope>\` and set at
|
|
|
368
372
|
|
|
369
373
|
Do not include planning text, implementation steps, or commentary about changing modes.`, ticket.skills);
|
|
370
374
|
};
|
|
371
|
-
const runReviewCompletionAutomation = async (ticket, project, reviewRunId, parsedStatus, findings, io, executionContext, initiation) => {
|
|
375
|
+
const runReviewCompletionAutomation = async (ticket, project, reviewRunId, parsedStatus, findings, io, executionContext, initiation, persistedAutomation) => {
|
|
372
376
|
if (!ticket.worktree_bundle_id || !ticket.project_id) {
|
|
373
377
|
return false;
|
|
374
378
|
}
|
|
@@ -376,12 +380,74 @@ const runReviewCompletionAutomation = async (ticket, project, reviewRunId, parse
|
|
|
376
380
|
const bundleId = ticket.worktree_bundle_id;
|
|
377
381
|
const liveTicket = getTicket(ticket.id) ?? ticket;
|
|
378
382
|
const liveProject = getEffectiveProject(liveTicket) ?? project;
|
|
379
|
-
const config = resolveAutomationConfig(liveTicket.bundle ?? null, liveProject);
|
|
383
|
+
const config = persistedAutomation?.config ?? resolveAutomationConfig(liveTicket.bundle ?? null, liveProject);
|
|
380
384
|
const bundleState = getBundleAutomationState(projectId, bundleId);
|
|
381
|
-
const decision =
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
+
const decision = persistedAutomation?.decision
|
|
386
|
+
?? decideReviewAutomation(config, bundleState, reviewRunId, parsedStatus, findings);
|
|
387
|
+
const progressionRunId = persistedAutomation?.progressionRunId
|
|
388
|
+
?? (initiation.initiator === 'automation'
|
|
389
|
+
? resolveProgressionForChild({ projectId, bundleId, childRunId: executionContext.runId }).id
|
|
390
|
+
: null);
|
|
391
|
+
const progression = progressionRunId ? { id: progressionRunId } : null;
|
|
392
|
+
if (progression) {
|
|
393
|
+
const iteration = getReviewRepairIterationByVerification(projectId, executionContext.runId);
|
|
394
|
+
if (iteration?.phase === 'verification_active'
|
|
395
|
+
&& iteration.resulting_review_execution_run_id === executionContext.runId) {
|
|
396
|
+
const resultingBlockingCount = parsedStatus === 'completed'
|
|
397
|
+
? countBlockingFindings(findings, config)
|
|
398
|
+
: null;
|
|
399
|
+
withExecutionRunTransaction(transaction => {
|
|
400
|
+
if (parsedStatus === 'completed' && reviewRunId) {
|
|
401
|
+
attachReviewRepairResultInTransaction(transaction, {
|
|
402
|
+
projectId,
|
|
403
|
+
iterationId: iteration.id,
|
|
404
|
+
expectedPhase: 'verification_active',
|
|
405
|
+
expectedVerificationRunId: executionContext.runId,
|
|
406
|
+
resultingReviewRunId: reviewRunId,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
appendReviewRepairIterationDecisionInTransaction(transaction, {
|
|
410
|
+
projectId,
|
|
411
|
+
iterationId: iteration.id,
|
|
412
|
+
decisionPoint: 'verification_completion',
|
|
413
|
+
effectiveAutomationConfig: config,
|
|
414
|
+
decisionCode: parsedStatus === 'completed' ? 'verification_completed' : 'verification_failed',
|
|
415
|
+
operationRunId: executionContext.runId,
|
|
416
|
+
});
|
|
417
|
+
const terminal = decision.kind === 'fix_iteration'
|
|
418
|
+
? { outcome: 'continuing', stopReason: null }
|
|
419
|
+
: decision.kind === 'clean'
|
|
420
|
+
? { outcome: 'repaired', stopReason: 'no_blocking_findings' }
|
|
421
|
+
: decision.kind === 'exhausted'
|
|
422
|
+
? { outcome: 'exhausted', stopReason: 'max_iterations' }
|
|
423
|
+
: decision.kind === 'pause_blocking'
|
|
424
|
+
? { outcome: 'interrupted', stopReason: 'automation_disabled' }
|
|
425
|
+
: parsedStatus !== 'completed'
|
|
426
|
+
? { outcome: 'failed', stopReason: 'verification_failed' }
|
|
427
|
+
: { outcome: 'interrupted', stopReason: 'configuration_changed' };
|
|
428
|
+
if (parsedStatus !== 'completed') {
|
|
429
|
+
pauseReviewRepairIterationInTransaction(transaction, {
|
|
430
|
+
projectId,
|
|
431
|
+
iterationId: iteration.id,
|
|
432
|
+
expectedPhase: 'verification_active',
|
|
433
|
+
expectedCurrentRunId: executionContext.runId,
|
|
434
|
+
stopReason: 'verification_failed',
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
terminalizeReviewRepairIterationInTransaction(transaction, {
|
|
439
|
+
projectId,
|
|
440
|
+
iterationId: iteration.id,
|
|
441
|
+
expectedPhase: 'verification_active',
|
|
442
|
+
expectedCurrentRunId: executionContext.runId,
|
|
443
|
+
outcome: terminal.outcome,
|
|
444
|
+
stopReason: terminal.stopReason,
|
|
445
|
+
resultingBlockingCount,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}, asGenericEmitter(io), 'immediate');
|
|
449
|
+
}
|
|
450
|
+
}
|
|
385
451
|
switch (decision.kind) {
|
|
386
452
|
case 'manual':
|
|
387
453
|
if (progression) {
|
|
@@ -431,41 +497,66 @@ const runReviewCompletionAutomation = async (ticket, project, reviewRunId, parse
|
|
|
431
497
|
if (!reviewRunId) {
|
|
432
498
|
throw new Error('Review fix cannot start without persisted review findings');
|
|
433
499
|
}
|
|
434
|
-
const previousIteration = bundleState?.review_iteration_count ?? 0;
|
|
435
|
-
const previousFixLoopActive = bundleState?.fix_loop_active ?? 0;
|
|
436
|
-
upsertBundleAutomationState(projectId, bundleId, {
|
|
437
|
-
review_iteration_count: decision.iteration,
|
|
438
|
-
fix_loop_active: 1,
|
|
439
|
-
});
|
|
440
500
|
const instruction = buildAutomationFixInstruction(config.reviewSeverity);
|
|
441
501
|
const reviewFixWorkflowContext = validateWorkflowContext({
|
|
442
502
|
...(initiation.workflowContext ?? {}),
|
|
443
503
|
review_finding_run_id: reviewRunId,
|
|
444
504
|
review_severity: config.reviewSeverity,
|
|
445
505
|
});
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
506
|
+
const repairProgressionRunId = progression?.id ?? ensureAutomationProgression({
|
|
507
|
+
projectId,
|
|
508
|
+
bundleId,
|
|
509
|
+
ticketId: ticket.id,
|
|
510
|
+
ticketTitle: ticket.title,
|
|
511
|
+
parentRunId: executionContext.runId,
|
|
512
|
+
workflowContext: initiation.workflowContext,
|
|
513
|
+
broadcaster: asGenericEmitter(io),
|
|
514
|
+
}).runId;
|
|
515
|
+
let reviewFix = persistedAutomation?.repair?.reviewFix ?? null;
|
|
516
|
+
let iterationId = persistedAutomation?.repair?.iterationId ?? null;
|
|
517
|
+
if (persistedAutomation && !persistedAutomation.repair) {
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
if (!reviewFix) {
|
|
521
|
+
const claimed = withExecutionRunTransaction(transaction => {
|
|
522
|
+
const iteration = claimReviewRepairIterationInTransaction(transaction, {
|
|
523
|
+
projectId,
|
|
524
|
+
worktreeBundleId: bundleId,
|
|
525
|
+
ownerTicketId: ticket.id,
|
|
526
|
+
automationProgressionRunId: repairProgressionRunId,
|
|
527
|
+
triggeringReviewExecutionRunId: executionContext.runId,
|
|
528
|
+
triggeringReviewRunId: reviewRunId,
|
|
529
|
+
triggeringBlockingCount: countBlockingFindings(findings, config),
|
|
530
|
+
effectiveAutomationConfig: config,
|
|
531
|
+
decisionCode: 'repair_admitted',
|
|
532
|
+
});
|
|
533
|
+
if (iteration.phase !== 'observed') {
|
|
534
|
+
return { iteration, reviewFix: null };
|
|
535
|
+
}
|
|
536
|
+
const createdReviewFix = createAutomationReviewFixInTransaction(transaction, {
|
|
450
537
|
projectId,
|
|
451
538
|
bundleId,
|
|
452
539
|
ticketId: ticket.id,
|
|
453
540
|
ticketTitle: ticket.title,
|
|
454
|
-
progressionRunId:
|
|
541
|
+
progressionRunId: repairProgressionRunId,
|
|
455
542
|
workflowContext: reviewFixWorkflowContext,
|
|
456
543
|
triggeringReviewRunId: executionContext.runId,
|
|
457
544
|
reviewFindingRunId: reviewRunId,
|
|
458
545
|
reviewSeverity: config.reviewSeverity,
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
546
|
+
});
|
|
547
|
+
attachReviewRepairActionEnvelopeInTransaction(transaction, {
|
|
548
|
+
projectId,
|
|
549
|
+
iterationId: iteration.id,
|
|
550
|
+
expectedPhase: 'observed',
|
|
551
|
+
runId: createdReviewFix.runId,
|
|
552
|
+
});
|
|
553
|
+
return { iteration, reviewFix: createdReviewFix };
|
|
554
|
+
}, asGenericEmitter(io), 'immediate');
|
|
555
|
+
iterationId = claimed.iteration.id;
|
|
556
|
+
reviewFix = claimed.reviewFix;
|
|
462
557
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
review_iteration_count: previousIteration,
|
|
466
|
-
fix_loop_active: previousFixLoopActive,
|
|
467
|
-
});
|
|
468
|
-
throw error;
|
|
558
|
+
if (!reviewFix) {
|
|
559
|
+
return true;
|
|
469
560
|
}
|
|
470
561
|
const started = submitTicketFollowUp({
|
|
471
562
|
ticketId: ticket.id,
|
|
@@ -475,16 +566,30 @@ const runReviewCompletionAutomation = async (ticket, project, reviewRunId, parse
|
|
|
475
566
|
persistTriggerMessage: false,
|
|
476
567
|
initiation: {
|
|
477
568
|
initiator: 'automation',
|
|
478
|
-
causalParentRunId: reviewFix
|
|
569
|
+
causalParentRunId: reviewFix.runId,
|
|
479
570
|
workflowContext: reviewFixWorkflowContext,
|
|
480
571
|
},
|
|
572
|
+
onExecutionCreated: (createdContext, transaction) => {
|
|
573
|
+
attachReviewRepairActionInTransaction(transaction, {
|
|
574
|
+
projectId,
|
|
575
|
+
iterationId: iterationId,
|
|
576
|
+
expectedPhase: 'action_claimed',
|
|
577
|
+
runId: createdContext.runId,
|
|
578
|
+
});
|
|
579
|
+
},
|
|
580
|
+
onExecutionCompleted: (completedContext, transaction) => {
|
|
581
|
+
const currentTicket = getTicket(ticket.id) ?? ticket;
|
|
582
|
+
const currentProject = getEffectiveProject(currentTicket) ?? project;
|
|
583
|
+
const currentConfig = resolveAutomationConfig(currentTicket.bundle ?? null, currentProject);
|
|
584
|
+
completeAutomationReviewFixActionInTransaction(transaction, {
|
|
585
|
+
projectId,
|
|
586
|
+
actionRunId: completedContext.runId,
|
|
587
|
+
effectiveAutomationConfig: currentConfig,
|
|
588
|
+
});
|
|
589
|
+
},
|
|
481
590
|
});
|
|
482
591
|
if (!started.ok) {
|
|
483
|
-
|
|
484
|
-
review_iteration_count: previousIteration,
|
|
485
|
-
fix_loop_active: previousFixLoopActive,
|
|
486
|
-
});
|
|
487
|
-
if (reviewFix && progression) {
|
|
592
|
+
if (reviewFix) {
|
|
488
593
|
finishAutomationReviewFix({
|
|
489
594
|
projectId,
|
|
490
595
|
reviewFixRunId: reviewFix.runId,
|
|
@@ -494,24 +599,27 @@ const runReviewCompletionAutomation = async (ticket, project, reviewRunId, parse
|
|
|
494
599
|
waitAutomationProgression({
|
|
495
600
|
projectId,
|
|
496
601
|
bundleId,
|
|
497
|
-
progressionRunId:
|
|
602
|
+
progressionRunId: repairProgressionRunId,
|
|
498
603
|
pauseCode: 'review',
|
|
499
604
|
pauseReason: `fix follow-up could not start: ${started.error}`,
|
|
500
605
|
reasonCode: 'stage_failed',
|
|
501
606
|
pausedStageRunId: reviewFix.runId,
|
|
502
607
|
broadcaster: asGenericEmitter(io),
|
|
503
608
|
});
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
609
|
+
const failedIteration = getReviewRepairIteration(projectId, iterationId);
|
|
610
|
+
if (failedIteration && !['paused', 'terminal'].includes(failedIteration.phase)) {
|
|
611
|
+
pauseReviewRepairIteration({
|
|
612
|
+
projectId,
|
|
613
|
+
iterationId: failedIteration.id,
|
|
614
|
+
expectedPhase: failedIteration.phase,
|
|
615
|
+
expectedCurrentRunId: failedIteration.resulting_review_execution_run_id
|
|
616
|
+
?? failedIteration.gate_batch_run_id
|
|
617
|
+
?? failedIteration.action_run_id
|
|
618
|
+
?? failedIteration.action_envelope_run_id,
|
|
619
|
+
stopReason: 'action_failed',
|
|
620
|
+
broadcaster: asGenericEmitter(io),
|
|
621
|
+
});
|
|
622
|
+
}
|
|
515
623
|
}
|
|
516
624
|
const pausedTicket = getTicket(ticket.id);
|
|
517
625
|
if (pausedTicket) {
|
|
@@ -557,6 +665,36 @@ const runReviewCompletionAutomation = async (ticket, project, reviewRunId, parse
|
|
|
557
665
|
}
|
|
558
666
|
return true;
|
|
559
667
|
}
|
|
668
|
+
case 'exhausted': {
|
|
669
|
+
if (progression) {
|
|
670
|
+
waitAutomationProgression({
|
|
671
|
+
projectId,
|
|
672
|
+
bundleId,
|
|
673
|
+
progressionRunId: progression.id,
|
|
674
|
+
pauseCode: 'review',
|
|
675
|
+
pauseReason: 'Blocking Review findings remain after repair verification.',
|
|
676
|
+
reasonCode: 'precondition_failed',
|
|
677
|
+
pausedStageRunId: executionContext.runId,
|
|
678
|
+
broadcaster: asGenericEmitter(io),
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
pauseAutomationProgression({
|
|
683
|
+
projectId,
|
|
684
|
+
bundleId,
|
|
685
|
+
pauseCode: 'review',
|
|
686
|
+
pauseReason: 'Blocking Review findings remain after repair verification.',
|
|
687
|
+
reasonCode: 'precondition_failed',
|
|
688
|
+
pausedStageRunId: null,
|
|
689
|
+
broadcaster: asGenericEmitter(io),
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
const pausedTicket = getTicket(ticket.id);
|
|
693
|
+
if (pausedTicket) {
|
|
694
|
+
io.emit('ticket:updated', pausedTicket);
|
|
695
|
+
}
|
|
696
|
+
return true;
|
|
697
|
+
}
|
|
560
698
|
case 'clean': {
|
|
561
699
|
resetBundleAutomationLoop(projectId, bundleId);
|
|
562
700
|
if (depthAtLeast(config.depth, 'auto_commit')) {
|
|
@@ -617,15 +755,10 @@ export function startReview(ticket, io, options) {
|
|
|
617
755
|
compensateAcceptance = acceptance.compensate;
|
|
618
756
|
}
|
|
619
757
|
const acceptedTool = resolveTicketTool(acceptedTicket, config.tool ?? 'opencode');
|
|
620
|
-
const acceptedReviewer =
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
})
|
|
625
|
-
: {
|
|
626
|
-
model: acceptedTicket.model,
|
|
627
|
-
variant: acceptedTicket.model ? acceptedTicket.variant : null,
|
|
628
|
-
};
|
|
758
|
+
const acceptedReviewer = resolveReviewerConfig(acceptedTicket.bundle, project, {
|
|
759
|
+
model: acceptedTicket.model,
|
|
760
|
+
variant: acceptedTicket.variant,
|
|
761
|
+
}, acceptedTool);
|
|
629
762
|
acceptedReviewExecution = {
|
|
630
763
|
tool: acceptedTool,
|
|
631
764
|
model: acceptedReviewer.model,
|
|
@@ -677,12 +810,14 @@ export function startReview(ticket, io, options) {
|
|
|
677
810
|
},
|
|
678
811
|
eventType: initiation.retrySourceRunId ? 'retry_started' : 'review_created',
|
|
679
812
|
});
|
|
680
|
-
|
|
813
|
+
const createdContext = {
|
|
681
814
|
runId: executionRun.id,
|
|
682
815
|
correlationId: executionRun.correlation_id,
|
|
683
816
|
projectId: executionRun.project_id,
|
|
684
817
|
kind: executionRun.kind,
|
|
685
818
|
};
|
|
819
|
+
options?.onExecutionCreated?.(createdContext, transaction);
|
|
820
|
+
return createdContext;
|
|
686
821
|
}, asGenericEmitter(io));
|
|
687
822
|
}
|
|
688
823
|
catch (error) {
|
|
@@ -716,6 +851,93 @@ export function startReview(ticket, io, options) {
|
|
|
716
851
|
throw new Error('The queued Review has no immutable execution configuration');
|
|
717
852
|
}
|
|
718
853
|
const cwd = currentTicket.bundle?.kind === 'project_root' ? project.repo_path : resolveWorktreePath(branch, project);
|
|
854
|
+
const verificationIteration = getReviewRepairIterationByVerification(project.id, executionContext.runId);
|
|
855
|
+
if (verificationIteration) {
|
|
856
|
+
const admittedIdentity = verificationIteration.workspace_evidence?.workspaceIdentity;
|
|
857
|
+
const currentIdentity = await captureCheckWorkspaceIdentity(cwd);
|
|
858
|
+
const liveConfig = resolveAutomationConfig(currentTicket.bundle ?? null, project);
|
|
859
|
+
if (liveConfig.depth === 'manual') {
|
|
860
|
+
withExecutionRunTransaction(transaction => {
|
|
861
|
+
terminalizeReviewRepairIterationInTransaction(transaction, {
|
|
862
|
+
projectId: project.id,
|
|
863
|
+
iterationId: verificationIteration.id,
|
|
864
|
+
expectedPhase: 'verification_active',
|
|
865
|
+
expectedCurrentRunId: executionContext.runId,
|
|
866
|
+
outcome: 'interrupted',
|
|
867
|
+
stopReason: 'configuration_changed',
|
|
868
|
+
});
|
|
869
|
+
completeAutomationProgressionInTransaction(transaction, {
|
|
870
|
+
projectId: project.id,
|
|
871
|
+
bundleId: verificationIteration.worktree_bundle_id,
|
|
872
|
+
progressionRunId: verificationIteration.automation_progression_run_id,
|
|
873
|
+
domainStatus: 'manual_boundary_reached',
|
|
874
|
+
});
|
|
875
|
+
}, asGenericEmitter(io), 'immediate');
|
|
876
|
+
throw new Error('Automated Review was disabled before verification started');
|
|
877
|
+
}
|
|
878
|
+
if (admittedIdentity?.state !== 'available'
|
|
879
|
+
|| currentIdentity.state !== 'available'
|
|
880
|
+
|| admittedIdentity.fingerprint !== currentIdentity.fingerprint) {
|
|
881
|
+
pauseReviewRepairIteration({
|
|
882
|
+
projectId: project.id,
|
|
883
|
+
iterationId: verificationIteration.id,
|
|
884
|
+
expectedPhase: 'verification_active',
|
|
885
|
+
expectedCurrentRunId: executionContext.runId,
|
|
886
|
+
stopReason: 'stale_evidence',
|
|
887
|
+
workspaceEvidence: {
|
|
888
|
+
...verificationIteration.workspace_evidence,
|
|
889
|
+
startupWorkspaceIdentity: currentIdentity,
|
|
890
|
+
},
|
|
891
|
+
broadcaster: asGenericEmitter(io),
|
|
892
|
+
});
|
|
893
|
+
throw new Error('Automated Review workspace is stale relative to gate admission');
|
|
894
|
+
}
|
|
895
|
+
if (!currentTicket.bundle) {
|
|
896
|
+
throw new Error('Automated Review bundle no longer exists');
|
|
897
|
+
}
|
|
898
|
+
try {
|
|
899
|
+
if (verificationIteration.gate_evaluation_id) {
|
|
900
|
+
await assertAutomationAuthorizationCurrent({
|
|
901
|
+
project,
|
|
902
|
+
bundle: currentTicket.bundle,
|
|
903
|
+
progressionRunId: verificationIteration.automation_progression_run_id,
|
|
904
|
+
cwd,
|
|
905
|
+
evaluationId: verificationIteration.gate_evaluation_id,
|
|
906
|
+
boundaryKind: 'automation_review',
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
else if (typeof verificationIteration.workspace_evidence?.policyFingerprint === 'string') {
|
|
910
|
+
assertAutomationBoundaryNotRequired({
|
|
911
|
+
project,
|
|
912
|
+
bundle: currentTicket.bundle,
|
|
913
|
+
progressionRunId: verificationIteration.automation_progression_run_id,
|
|
914
|
+
policyFingerprint: verificationIteration.workspace_evidence.policyFingerprint,
|
|
915
|
+
boundaryKind: 'automation_review',
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
throw new AutomationCheckGateError('invalid_lineage', 'Automated Review gate evidence is unavailable');
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
catch (error) {
|
|
923
|
+
if (!(error instanceof AutomationCheckGateError)) {
|
|
924
|
+
throw error;
|
|
925
|
+
}
|
|
926
|
+
pauseReviewRepairIteration({
|
|
927
|
+
projectId: project.id,
|
|
928
|
+
iterationId: verificationIteration.id,
|
|
929
|
+
expectedPhase: 'verification_active',
|
|
930
|
+
expectedCurrentRunId: executionContext.runId,
|
|
931
|
+
stopReason: 'stale_evidence',
|
|
932
|
+
workspaceEvidence: {
|
|
933
|
+
...verificationIteration.workspace_evidence,
|
|
934
|
+
startupWorkspaceIdentity: currentIdentity,
|
|
935
|
+
},
|
|
936
|
+
broadcaster: asGenericEmitter(io),
|
|
937
|
+
});
|
|
938
|
+
throw new Error(`Automated Review gate authorization is stale: ${error.message}`);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
719
941
|
const { tool, skills } = acceptedReviewExecution;
|
|
720
942
|
const reviewerConfig = {
|
|
721
943
|
model: acceptedReviewExecution.model,
|
|
@@ -907,6 +1129,15 @@ export function startReview(ticket, io, options) {
|
|
|
907
1129
|
expectedParent: { entityType: 'ticket', entityId: currentTicket.id },
|
|
908
1130
|
},
|
|
909
1131
|
});
|
|
1132
|
+
if (verificationIteration) {
|
|
1133
|
+
attachReviewRepairResultInTransaction(transaction, {
|
|
1134
|
+
projectId: executionContext.projectId,
|
|
1135
|
+
iterationId: verificationIteration.id,
|
|
1136
|
+
expectedPhase: 'verification_active',
|
|
1137
|
+
expectedVerificationRunId: executionContext.runId,
|
|
1138
|
+
resultingReviewRunId: activeReviewRunId,
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
910
1141
|
}, asGenericEmitter(io));
|
|
911
1142
|
beginTicketThinkingRun(ticket.id);
|
|
912
1143
|
const blindRunId = createAgentRun({
|
|
@@ -1025,7 +1256,7 @@ export function startReview(ticket, io, options) {
|
|
|
1025
1256
|
});
|
|
1026
1257
|
}
|
|
1027
1258
|
catch (error) {
|
|
1028
|
-
if (
|
|
1259
|
+
if (reviewerConfig.model && isModelResolutionError(error, tool)) {
|
|
1029
1260
|
throw getReviewerExecutionError(error, reviewerConfig.model, reviewerConfig.variant);
|
|
1030
1261
|
}
|
|
1031
1262
|
throw error;
|
|
@@ -1195,7 +1426,8 @@ export function startReview(ticket, io, options) {
|
|
|
1195
1426
|
...(parseFailed ? { failure: { code: 'parse_failed', message: 'Review output could not be parsed' } } : {}),
|
|
1196
1427
|
eventType: parseFailed ? 'review_parse_failed' : 'review_completed',
|
|
1197
1428
|
});
|
|
1198
|
-
|
|
1429
|
+
const persistedAutomation = persistReviewCompletionAutomationInTransaction(transaction, currentTicket, project, activeReviewRunId, parsedStatus, parsedFindings, executionContext, initiation);
|
|
1430
|
+
return { messageId, reviewRunId: activeReviewRunId, persistedAutomation };
|
|
1199
1431
|
}, asGenericEmitter(io));
|
|
1200
1432
|
persistedMessageId = persisted.messageId;
|
|
1201
1433
|
reviewRunId = persisted.reviewRunId;
|
|
@@ -1232,7 +1464,7 @@ export function startReview(ticket, io, options) {
|
|
|
1232
1464
|
captureStageSuccess(ticket.id, 'review');
|
|
1233
1465
|
let handled = false;
|
|
1234
1466
|
try {
|
|
1235
|
-
handled = await runReviewCompletionAutomation(updated, project, reviewRunId, parsedStatus, parsedFindings, io, executionContext, initiation);
|
|
1467
|
+
handled = await runReviewCompletionAutomation(updated, project, reviewRunId, parsedStatus, parsedFindings, io, executionContext, initiation, persisted.persistedAutomation);
|
|
1236
1468
|
}
|
|
1237
1469
|
catch (automationError) {
|
|
1238
1470
|
if (ticket.project_id && ticket.worktree_bundle_id) {
|