@straiffi/archon 1.8.8 → 1.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/{ActivityView--4X_m6mR.js → ActivityView-gBeoYQdD.js} +1 -1
- package/dist/client/assets/{GitHubActionsDialog-DZ1lHM01.js → GitHubActionsDialog-fc1Vwafm.js} +1 -1
- package/dist/client/assets/RepositoryGraphDialog-DCOjwUR3.js +1 -0
- package/dist/client/assets/VerificationDialog-CIObj1Rw.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-CY5xTOZJ.js → architectureDiagram-3BPJPVTR-B1tJZe1S.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DkMi7gMh.js → blockDiagram-GPEHLZMM-D_90AQ2Z.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-ZZxXBBU4.js → c4Diagram-AAUBKEIU-DSyJfqly.js} +1 -1
- package/dist/client/assets/channel-DFw1f2Rh.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-C9PiKMs-.js → chunk-2J33WTMH-B9RStQGj.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-B81aUmvi.js → chunk-3OPIFGDE-CHKuJYq0.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-Bk2Owm90.js → chunk-5ZQYHXKU-Cznw7LTJ.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-Bx-79aJk.js → chunk-727SXJPM-ix6OeZwJ.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-GQNXYOf0.js → chunk-AQP2D5EJ-DrPJIcE7.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-BV22j6vn.js → chunk-CSCIHK7Q-BSEHTnBR.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-C9LlcbWv.js → chunk-KSCS5N6A-MdDdaLn8.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-D8PJqJnh.js → chunk-L5ZTLDWV-D_5xeDG1.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-DcbPPozR.js → chunk-LZXEDZCA-Bz8_Fyt2.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-NV-_2KqZ.js → chunk-ND2GUHAM-DCINKlk8.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-CbqA26gb.js → chunk-NZK2D7GU-rGPgryKx.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-B0DMN44B.js → chunk-O5CBEL6O-BHB8UIYA.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-CYpcnwf9.js → chunk-WU5MYG2G-Bz5BJWjF.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-Dt0kmMzQ.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BuxhA4Gw.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-B5HD9fyK.js → dagre-BM42HDAG-B4TXLkOG.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BCXvWFpM.js → diagram-2AECGRRQ-CxMup1wq.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CSpWGfAO.js → diagram-5GNKFQAL-CTfP_wnS.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-CFECGppT.js → diagram-KO2AKTUF-31NKNt4r.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-Dpb99QbZ.js → diagram-LMA3HP47-Cxo7yvjc.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-DJcTGnx0.js → diagram-OG6HWLK6-ChgSAMLv.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-jWArJxNU.js → erDiagram-TEJ5UH35-u6msywL_.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-DDF3P1hY.js → flowDiagram-I6XJVG4X-CimeXkDN.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-Corwr_18.js → ganttDiagram-6RSMTGT7-DOu5sDUI.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-WzlpszWn.js → gitGraphDiagram-PVQCEYII-zIToibUf.js} +1 -1
- package/dist/client/assets/index-C-VHd0Pr.js +274 -0
- package/dist/client/assets/index-D3xlEyeM.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-C0VwTwNC.js → infoDiagram-5YYISTIA-CAtWGGJI.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-m9l3k2qX.js → ishikawaDiagram-YF4QCWOH-7N-C7DEt.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DMhT8HTW.js → journeyDiagram-JHISSGLW-D7VUypFG.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-C2ZkcOi0.js → kanban-definition-UN3LZRKU-AmbDmzSD.js} +1 -1
- package/dist/client/assets/{line-gKkUdUWR.js → line-qf4UZ8vh.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-DdBfJWbP.js → mermaid-parser.core-BssCd1kF.js} +1 -1
- package/dist/client/assets/{mermaid.core-DXnhq-eu.js → mermaid.core-DzeMqg9Y.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-B0gX4aJy.js → mindmap-definition-RKZ34NQL-dEnNQcDm.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BHYdLmpx.js → pieDiagram-4H26LBE5-VjMue0a-.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-C-H-yQwU.js → quadrantDiagram-W4KKPZXB-DQFdm-0f.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DY_pSCFy.js → requirementDiagram-4Y6WPE33-CHIaXlsy.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-CC61HRGf.js → sankeyDiagram-5OEKKPKP-D-kzGaKb.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-B8fXWNxw.js → sequenceDiagram-3UESZ5HK-CiDmlD8k.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-C_VYKsXW.js → stateDiagram-AJRCARHV-BKlnnFdT.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DhJxc4em.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-0fB4PIIX.js → timeline-definition-PNZ67QCA-D-BK07Un.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-CfpVF7Aa.js → vennDiagram-CIIHVFJN-CB9_GqSx.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CgdK4FcC.js → wardleyDiagram-YWT4CUSO-BEuNfyLT.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-BEfatQYR.js → xychartDiagram-2RQKCTM6-CSS5WMrZ.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +481 -27
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +72 -18
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/activeAutomationChild.js +1 -0
- package/dist/server/lib/activeAutomationChild.js.map +1 -1
- package/dist/server/lib/agent.js +127 -15
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/agentRuns.js +12 -0
- package/dist/server/lib/agentRuns.js.map +1 -1
- package/dist/server/lib/agentSpawnPermits.js +37 -0
- package/dist/server/lib/agentSpawnPermits.js.map +1 -0
- package/dist/server/lib/automationCheckGate.js +9 -1
- package/dist/server/lib/automationCheckGate.js.map +1 -1
- package/dist/server/lib/automationProgression.js +19 -5
- package/dist/server/lib/automationProgression.js.map +1 -1
- package/dist/server/lib/automationReviewGate.js +1 -0
- package/dist/server/lib/automationReviewGate.js.map +1 -1
- package/dist/server/lib/buildCompletionContinuation.js +144 -4
- package/dist/server/lib/buildCompletionContinuation.js.map +1 -1
- package/dist/server/lib/buildSequences.js +13 -1
- package/dist/server/lib/buildSequences.js.map +1 -1
- package/dist/server/lib/bundleActivity.js +19 -0
- package/dist/server/lib/bundleActivity.js.map +1 -1
- package/dist/server/lib/chatOperations.js +81 -2
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/checkAutoFix.js +604 -0
- package/dist/server/lib/checkAutoFix.js.map +1 -0
- package/dist/server/lib/checkAutoFixDetails.js +83 -0
- package/dist/server/lib/checkAutoFixDetails.js.map +1 -0
- package/dist/server/lib/checkAutoFixPolicy.js +59 -0
- package/dist/server/lib/checkAutoFixPolicy.js.map +1 -0
- package/dist/server/lib/checkRepair.js +149 -54
- package/dist/server/lib/checkRepair.js.map +1 -1
- package/dist/server/lib/checkRepairDispatch.js +91 -0
- package/dist/server/lib/checkRepairDispatch.js.map +1 -0
- package/dist/server/lib/checkRepairEvidence.js +84 -0
- package/dist/server/lib/checkRepairEvidence.js.map +1 -0
- package/dist/server/lib/checkRepairParent.js +21 -0
- package/dist/server/lib/checkRepairParent.js.map +1 -0
- package/dist/server/lib/checkRepairReconciliation.js +14 -5
- package/dist/server/lib/checkRepairReconciliation.js.map +1 -1
- package/dist/server/lib/checkRunner.js +27 -8
- package/dist/server/lib/checkRunner.js.map +1 -1
- package/dist/server/lib/checkRuns.js +63 -4
- package/dist/server/lib/checkRuns.js.map +1 -1
- package/dist/server/lib/executionReconciliation.js +387 -8
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRuns.js +24 -1
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/integrations/github.js +10 -7
- package/dist/server/lib/integrations/github.js.map +1 -1
- package/dist/server/lib/postBuildCheckRuns.js +200 -5
- package/dist/server/lib/postBuildCheckRuns.js.map +1 -1
- package/dist/server/lib/postBuildChecks.js +83 -13
- package/dist/server/lib/postBuildChecks.js.map +1 -1
- package/dist/server/lib/projects.js +25 -1
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/queue.js +9 -3
- package/dist/server/lib/queue.js.map +1 -1
- package/dist/server/lib/repositoryGraphQueries.js +5 -3
- package/dist/server/lib/repositoryGraphQueries.js.map +1 -1
- package/dist/server/lib/repositoryGraphScan.js +13 -2
- package/dist/server/lib/repositoryGraphScan.js.map +1 -1
- package/dist/server/lib/repositoryGraphStore.js +61 -1
- package/dist/server/lib/repositoryGraphStore.js.map +1 -1
- package/dist/server/lib/specArtifact.js +10 -1
- package/dist/server/lib/specArtifact.js.map +1 -1
- package/dist/server/lib/specDraft.js +10 -2
- package/dist/server/lib/specDraft.js.map +1 -1
- package/dist/server/lib/specExport.js +70 -6
- package/dist/server/lib/specExport.js.map +1 -1
- package/dist/server/lib/specFormatting.js +3 -2
- package/dist/server/lib/specFormatting.js.map +1 -1
- package/dist/server/lib/specRepositoryEvidenceFormatting.js +75 -0
- package/dist/server/lib/specRepositoryEvidenceFormatting.js.map +1 -0
- package/dist/server/lib/specRepositoryImpact.js +447 -0
- package/dist/server/lib/specRepositoryImpact.js.map +1 -0
- package/dist/server/lib/specRepositoryImpactLimits.js +6 -0
- package/dist/server/lib/specRepositoryImpactLimits.js.map +1 -0
- package/dist/server/lib/specReviewContext.js +15 -5
- package/dist/server/lib/specReviewContext.js.map +1 -1
- package/dist/server/lib/specReviewValidation.js +1 -1
- package/dist/server/lib/specReviewValidation.js.map +1 -1
- package/dist/server/lib/specSections.js +28 -3
- package/dist/server/lib/specSections.js.map +1 -1
- package/dist/server/lib/specSnapshotEvidence.js +162 -0
- package/dist/server/lib/specSnapshotEvidence.js.map +1 -0
- package/dist/server/lib/specSnapshotEvidenceSerialization.js +202 -0
- package/dist/server/lib/specSnapshotEvidenceSerialization.js.map +1 -0
- package/dist/server/lib/specs.js +31 -5
- package/dist/server/lib/specs.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +3 -1
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +16 -12
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/ticketRunOperations.js +13 -1
- package/dist/server/lib/ticketRunOperations.js.map +1 -1
- package/dist/server/lib/ticketWorkflowOperations.js +5 -2
- package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
- package/dist/server/lib/types.js +1 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/workers/build.js +46 -148
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +141 -31
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +210 -48
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/specReview.js +17 -4
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +127 -22
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/RepositoryGraphDialog-B--YlQcV.js +0 -1
- package/dist/client/assets/VerificationDialog-BIWPtBg3.js +0 -4
- package/dist/client/assets/channel-b2AN-U3x.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C0exS5oM.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DkB9dQZ1.js +0 -1
- package/dist/client/assets/index-Bs5SQZhz.css +0 -2
- package/dist/client/assets/index-Dy-7h3lN.js +0 -274
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Ctk1r914.js +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import db from '../db.js';
|
|
2
|
+
const MAX_ATTEMPTS = 3;
|
|
3
|
+
const TERMINAL_STATUSES = new Set(['completed', 'failed', 'cancelled', 'interrupted']);
|
|
4
|
+
export const getCheckAutoFixDetails = (projectId, runOrBatchId) => {
|
|
5
|
+
const tablesAvailable = db.prepare(`
|
|
6
|
+
SELECT COUNT(*) AS count FROM sqlite_master
|
|
7
|
+
WHERE type = 'table' AND name IN ('check_auto_fix_loops', 'check_auto_fix_attempts', 'lifecycle_events')
|
|
8
|
+
`).get();
|
|
9
|
+
if (tablesAvailable.count !== 3) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const loop = db.prepare(`
|
|
13
|
+
SELECT loop.*, run.status AS execution_status FROM check_auto_fix_loops loop
|
|
14
|
+
JOIN execution_runs run ON run.id = loop.execution_run_id
|
|
15
|
+
WHERE run.project_id = ? AND (
|
|
16
|
+
loop.execution_run_id = ? OR loop.originating_batch_run_id = ? OR loop.final_batch_run_id = ?
|
|
17
|
+
OR EXISTS (
|
|
18
|
+
SELECT 1 FROM check_auto_fix_attempts attempt
|
|
19
|
+
WHERE attempt.loop_run_id = loop.execution_run_id
|
|
20
|
+
AND (attempt.source_batch_run_id = ? OR attempt.rerun_batch_run_id = ?)
|
|
21
|
+
)
|
|
22
|
+
)
|
|
23
|
+
ORDER BY loop.created_at DESC LIMIT 1
|
|
24
|
+
`).get(projectId, runOrBatchId, runOrBatchId, runOrBatchId, runOrBatchId, runOrBatchId);
|
|
25
|
+
if (!loop) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const rows = db.prepare(`
|
|
29
|
+
SELECT attempt.ordinal, attempt.source_batch_run_id, attempt.child_run_id,
|
|
30
|
+
attempt.launch_outcome, attempt.rerun_batch_run_id, attempt.terminal_reason,
|
|
31
|
+
attempt.terminal_message, attempt.created_at, attempt.updated_at,
|
|
32
|
+
EXISTS (
|
|
33
|
+
SELECT 1 FROM lifecycle_events event
|
|
34
|
+
WHERE event.execution_run_id = attempt.loop_run_id
|
|
35
|
+
AND event.event_type = 'check_auto_fix_fallback'
|
|
36
|
+
AND json_extract(event.metadata_json, '$.attempt') = attempt.ordinal
|
|
37
|
+
) AS fallback_used,
|
|
38
|
+
child.status AS child_status, rerun.status AS rerun_status
|
|
39
|
+
FROM check_auto_fix_attempts attempt
|
|
40
|
+
LEFT JOIN execution_runs child ON child.id = attempt.child_run_id
|
|
41
|
+
LEFT JOIN execution_runs rerun ON rerun.id = attempt.rerun_batch_run_id
|
|
42
|
+
WHERE attempt.loop_run_id = ? ORDER BY attempt.ordinal
|
|
43
|
+
`).all(loop.execution_run_id);
|
|
44
|
+
const active = rows[rows.length - 1];
|
|
45
|
+
const phase = loop.terminal_reason
|
|
46
|
+
? 'terminal'
|
|
47
|
+
: loop.cancellation_requested
|
|
48
|
+
? 'stopping'
|
|
49
|
+
: active?.rerun_batch_run_id && active.rerun_status && !TERMINAL_STATUSES.has(active.rerun_status)
|
|
50
|
+
? 'rerunning'
|
|
51
|
+
: active?.child_run_id && active.child_status && !TERMINAL_STATUSES.has(active.child_status)
|
|
52
|
+
? 'repairing'
|
|
53
|
+
: 'dispatching';
|
|
54
|
+
return {
|
|
55
|
+
execution_run_id: loop.execution_run_id,
|
|
56
|
+
execution_status: loop.execution_status,
|
|
57
|
+
phase,
|
|
58
|
+
originating_batch_run_id: loop.originating_batch_run_id,
|
|
59
|
+
final_batch_run_id: loop.final_batch_run_id ?? loop.originating_batch_run_id,
|
|
60
|
+
owner_type: loop.owner_type,
|
|
61
|
+
owner_id: loop.owner_id,
|
|
62
|
+
causal_execution_run_id: loop.causal_execution_run_id,
|
|
63
|
+
causal_agent_run_id: loop.causal_agent_run_id,
|
|
64
|
+
attempt_count: loop.attempt_count,
|
|
65
|
+
max_attempts: MAX_ATTEMPTS,
|
|
66
|
+
cancellation_requested: loop.cancellation_requested === 1,
|
|
67
|
+
terminal_reason: loop.terminal_reason,
|
|
68
|
+
terminal_message: loop.terminal_message,
|
|
69
|
+
attempts: rows.map(row => ({
|
|
70
|
+
ordinal: row.ordinal,
|
|
71
|
+
source_batch_run_id: row.source_batch_run_id,
|
|
72
|
+
child_run_id: row.child_run_id,
|
|
73
|
+
continuation: row.launch_outcome === 'continued' || row.launch_outcome === 'fresh' ? row.launch_outcome : null,
|
|
74
|
+
fallback_used: row.fallback_used === 1,
|
|
75
|
+
rerun_batch_run_id: row.rerun_batch_run_id,
|
|
76
|
+
terminal_reason: row.terminal_reason,
|
|
77
|
+
terminal_message: row.terminal_message,
|
|
78
|
+
created_at: row.created_at,
|
|
79
|
+
updated_at: row.updated_at,
|
|
80
|
+
})),
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=checkAutoFixDetails.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkAutoFixDetails.js","sourceRoot":"","sources":["../../../server/lib/checkAutoFixDetails.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import { getCheckDefinitionFingerprint } from './checkDefinitions.js';
|
|
3
|
+
import { parseRequiredCheckDefinitionIds } from './requiredCheckPolicy.js';
|
|
4
|
+
const updateLengthDelimited = (hash, value) => {
|
|
5
|
+
const buffer = Buffer.from(value, 'utf8');
|
|
6
|
+
const length = Buffer.alloc(8);
|
|
7
|
+
length.writeBigUInt64BE(BigInt(buffer.length));
|
|
8
|
+
hash.update(length).update(buffer);
|
|
9
|
+
};
|
|
10
|
+
const compareDefinitionIds = (left, right) => (Buffer.compare(Buffer.from(left.id, 'utf8'), Buffer.from(right.id, 'utf8')));
|
|
11
|
+
const snapshotDefinition = (definition) => ({
|
|
12
|
+
id: definition.id,
|
|
13
|
+
name: definition.name,
|
|
14
|
+
category: definition.category,
|
|
15
|
+
command: definition.command,
|
|
16
|
+
...(definition.cwd ? { cwd: definition.cwd } : {}),
|
|
17
|
+
timeout_ms: definition.timeout_ms,
|
|
18
|
+
...(definition.category === 'test' ? { runner: definition.runner } : {}),
|
|
19
|
+
});
|
|
20
|
+
export const getCheckAutoFixPolicyFingerprint = (definitions) => {
|
|
21
|
+
const hash = createHash('sha256');
|
|
22
|
+
updateLengthDelimited(hash, 'archon-check-auto-fix-policy-v1');
|
|
23
|
+
for (const definition of [...definitions].sort(compareDefinitionIds)) {
|
|
24
|
+
updateLengthDelimited(hash, definition.id);
|
|
25
|
+
updateLengthDelimited(hash, getCheckDefinitionFingerprint(definition));
|
|
26
|
+
}
|
|
27
|
+
return hash.digest('hex');
|
|
28
|
+
};
|
|
29
|
+
export const createCheckAutoFixPolicySnapshot = (project, selectedDefinitionSnapshots) => {
|
|
30
|
+
const membership = parseRequiredCheckDefinitionIds(project.auto_fix_check_definition_ids, 'auto_fix_check_definition_ids');
|
|
31
|
+
if ('error' in membership) {
|
|
32
|
+
return { status: 'invalid', error: membership.error };
|
|
33
|
+
}
|
|
34
|
+
const membershipSet = new Set(membership.value);
|
|
35
|
+
const definitions = selectedDefinitionSnapshots
|
|
36
|
+
.filter(definition => membershipSet.has(definition.id))
|
|
37
|
+
.map(snapshotDefinition)
|
|
38
|
+
.sort(compareDefinitionIds);
|
|
39
|
+
return {
|
|
40
|
+
status: 'valid',
|
|
41
|
+
snapshot: {
|
|
42
|
+
definitionIds: definitions.map(definition => definition.id),
|
|
43
|
+
definitions,
|
|
44
|
+
fingerprint: getCheckAutoFixPolicyFingerprint(definitions),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export const doCurrentDefinitionsMatchCheckAutoFixPolicySnapshot = (snapshot, currentDefinitions) => {
|
|
49
|
+
if (snapshot.fingerprint !== getCheckAutoFixPolicyFingerprint(snapshot.definitions)) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const currentDefinitionsById = new Map(currentDefinitions.map(definition => [definition.id, definition]));
|
|
53
|
+
return snapshot.definitions.every(definition => {
|
|
54
|
+
const currentDefinition = currentDefinitionsById.get(definition.id);
|
|
55
|
+
return currentDefinition !== undefined
|
|
56
|
+
&& getCheckDefinitionFingerprint(currentDefinition) === getCheckDefinitionFingerprint(definition);
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=checkAutoFixPolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkAutoFixPolicy.js","sourceRoot":"","sources":["../../../server/lib/checkAutoFixPolicy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import db from '../db.js';
|
|
2
2
|
import { stopBuildAgent } from './agent.js';
|
|
3
3
|
import { terminalizeAgentRunsForExecutionRun } from './agentRuns.js';
|
|
4
|
+
import { resolveCausalAgentRun } from './agentRuns.js';
|
|
4
5
|
import { assertNoActiveAutomationChild } from './activeAutomationChild.js';
|
|
5
6
|
import { getBundlePlanMutationBlockerById } from './bundleActivity.js';
|
|
6
7
|
import { runAutomationReviewGateOrPause } from './automationReviewGate.js';
|
|
@@ -8,14 +9,17 @@ import { resolveBundleReviewOwner } from './bundleReviewOperations.js';
|
|
|
8
9
|
import { resolveBuildTicketCommitCheckpointLineage } from './buildTicketCommit.js';
|
|
9
10
|
import { getExecutionRun, withExecutionRunTransaction } from './executionRuns.js';
|
|
10
11
|
import { getCheckDefinitionFingerprint } from './checkDefinitions.js';
|
|
11
|
-
import { findActiveCheckBatchForTarget, getCheckBatchDetails } from './checkRuns.js';
|
|
12
|
+
import { findActiveCheckAutoFixForTarget, findActiveCheckBatchForTarget, getCheckBatchDetails } from './checkRuns.js';
|
|
12
13
|
import { startCheckBatch, stopCheckBatch, waitForCheckBatch } from './checkRunner.js';
|
|
13
14
|
import { finalizeCheckRepair, finalizeCheckRepairInTransaction } from './checkRepairLifecycle.js';
|
|
14
15
|
import { captureCheckWorkspaceIdentity } from './checkWorkspaceIdentity.js';
|
|
15
16
|
import { resolveWorktreePath } from './git.js';
|
|
16
17
|
import { getProjectById, getProjectCheckDefinitions } from './projects.js';
|
|
17
18
|
import { getRequiredCheckPolicyFingerprint } from './requiredCheckPolicy.js';
|
|
18
|
-
import {
|
|
19
|
+
import { dispatchCheckRepair } from './checkRepairDispatch.js';
|
|
20
|
+
import { getChatSession } from './chats.js';
|
|
21
|
+
import { stopChatAgent } from './agent.js';
|
|
22
|
+
import { revokeAgentSpawnPermit } from './agentSpawnPermits.js';
|
|
19
23
|
import { getBundleAutomationState, resolveAutomationConfig } from './ticketAutomation.js';
|
|
20
24
|
import { continueAfterBuildCheckpoint } from './automationBuildContinuation.js';
|
|
21
25
|
import { getAutomationProgression, runAutomationProgression, waitAutomationProgression, waitAutomationProgressionInTransaction, } from './automationProgression.js';
|
|
@@ -335,6 +339,70 @@ const resolveOwnerTicket = (projectId, batch, requestedTicketId, progressionRunI
|
|
|
335
339
|
}
|
|
336
340
|
return eligible[0];
|
|
337
341
|
};
|
|
342
|
+
const resolveRepairOwner = (projectId, batch, sourceRunId, requestedTicketId, progressionRunId) => {
|
|
343
|
+
const primary = db.prepare(`
|
|
344
|
+
SELECT entity_type, entity_id
|
|
345
|
+
FROM execution_run_links
|
|
346
|
+
WHERE execution_run_id = ? AND project_id = ? AND relationship = 'primary'
|
|
347
|
+
AND entity_type IN ('ticket', 'chat_session')
|
|
348
|
+
`).get(sourceRunId, projectId);
|
|
349
|
+
if (primary?.entity_type === 'chat_session') {
|
|
350
|
+
if (requestedTicketId || progressionRunId) {
|
|
351
|
+
throw new CheckRepairError(409, 'Chat Build repair ownership conflicts with Ticket automation');
|
|
352
|
+
}
|
|
353
|
+
const session = getChatSession(primary.entity_id);
|
|
354
|
+
if (!session
|
|
355
|
+
|| session.project_id !== projectId
|
|
356
|
+
|| session.mode !== 'build'
|
|
357
|
+
|| session.target_kind !== batch.target_kind
|
|
358
|
+
|| session.target_bundle_id !== batch.target_bundle_id) {
|
|
359
|
+
throw new CheckRepairError(409, 'The causal Chat Build owner is stale or unavailable');
|
|
360
|
+
}
|
|
361
|
+
return { ownerType: 'chat_session', ownerId: session.id, ticket: null, description: session.title };
|
|
362
|
+
}
|
|
363
|
+
const ticket = resolveOwnerTicket(projectId, batch, requestedTicketId ?? (primary?.entity_type === 'ticket' ? primary.entity_id : null), progressionRunId);
|
|
364
|
+
if (primary?.entity_type === 'ticket' && primary.entity_id !== ticket.id) {
|
|
365
|
+
throw new CheckRepairError(409, 'Requested Ticket does not own the causal check batch');
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
ownerType: 'ticket',
|
|
369
|
+
ownerId: ticket.id,
|
|
370
|
+
ticket,
|
|
371
|
+
description: ticket.description || ticket.title,
|
|
372
|
+
};
|
|
373
|
+
};
|
|
374
|
+
const resolveCausalExecution = (projectId, sourceRunId, ownerType, ownerId) => {
|
|
375
|
+
const source = getExecutionRun(projectId, sourceRunId);
|
|
376
|
+
const direct = source?.parent_run_id ? getExecutionRun(projectId, source.parent_run_id) : null;
|
|
377
|
+
const expectedKinds = ownerType === 'ticket' ? ['build', 'build_follow_up'] : ['chat_turn'];
|
|
378
|
+
const directOwner = direct ? db.prepare(`
|
|
379
|
+
SELECT 1 FROM execution_run_links
|
|
380
|
+
WHERE execution_run_id = ? AND project_id = ? AND relationship = 'primary'
|
|
381
|
+
AND entity_type = ? AND entity_id = ?
|
|
382
|
+
`).get(direct.id, projectId, ownerType, ownerId) : null;
|
|
383
|
+
if (direct && expectedKinds.includes(direct.kind) && directOwner) {
|
|
384
|
+
return direct;
|
|
385
|
+
}
|
|
386
|
+
if (ownerType === 'chat_session') {
|
|
387
|
+
throw new CheckRepairError(409, 'The causal Chat Build execution is unavailable');
|
|
388
|
+
}
|
|
389
|
+
const row = db.prepare(`
|
|
390
|
+
SELECT run.id
|
|
391
|
+
FROM execution_runs run
|
|
392
|
+
JOIN execution_run_links link ON link.execution_run_id = run.id
|
|
393
|
+
AND link.project_id = run.project_id AND link.relationship = 'primary'
|
|
394
|
+
AND link.entity_type = 'ticket' AND link.entity_id = ?
|
|
395
|
+
WHERE run.project_id = ? AND run.kind IN ('build', 'build_follow_up')
|
|
396
|
+
AND run.status = 'completed'
|
|
397
|
+
AND EXISTS (SELECT 1 FROM agent_runs agent WHERE agent.execution_run_id = run.id)
|
|
398
|
+
ORDER BY run.created_at DESC, run.id DESC LIMIT 1
|
|
399
|
+
`).get(ownerId, projectId);
|
|
400
|
+
const causal = row ? getExecutionRun(projectId, row.id) : null;
|
|
401
|
+
if (!causal) {
|
|
402
|
+
throw new CheckRepairError(409, 'The causal Ticket Build execution is unavailable');
|
|
403
|
+
}
|
|
404
|
+
return causal;
|
|
405
|
+
};
|
|
338
406
|
const toRepairDestination = (purpose) => {
|
|
339
407
|
if (purpose === 'automation_review') {
|
|
340
408
|
return 'pre_review';
|
|
@@ -350,6 +418,12 @@ const toRepairDestination = (purpose) => {
|
|
|
350
418
|
}
|
|
351
419
|
return purpose === null ? 'manual' : 'unknown';
|
|
352
420
|
};
|
|
421
|
+
const assertNoActiveCheckAutoFixForTarget = (projectId, targetKind, targetBundleId) => {
|
|
422
|
+
const active = findActiveCheckAutoFixForTarget(projectId, targetKind, targetBundleId);
|
|
423
|
+
if (active) {
|
|
424
|
+
throw new CheckRepairError(409, `Check target is busy with active auto-fix ${active}`);
|
|
425
|
+
}
|
|
426
|
+
};
|
|
353
427
|
export const getCheckRepairCandidateState = async (projectId, batchRunId) => {
|
|
354
428
|
const project = getProjectById(projectId);
|
|
355
429
|
const batch = project ? getCheckBatchDetails(projectId, batchRunId) : null;
|
|
@@ -357,6 +431,7 @@ export const getCheckRepairCandidateState = async (projectId, batchRunId) => {
|
|
|
357
431
|
const purpose = batch?.automation_boundary_purpose ?? null;
|
|
358
432
|
const base = {
|
|
359
433
|
candidate_tickets: [],
|
|
434
|
+
candidate_chat_sessions: [],
|
|
360
435
|
accepts_ticket_id: false,
|
|
361
436
|
destination: toRepairDestination(purpose),
|
|
362
437
|
eligible_attempt_run_ids: [],
|
|
@@ -431,6 +506,7 @@ export const getCheckRepairCandidateState = async (projectId, batchRunId) => {
|
|
|
431
506
|
return { ...base, eligibility: { eligible: false, reason: 'workspace_changed' } };
|
|
432
507
|
}
|
|
433
508
|
if (findActiveCheckBatchForTarget(projectId, batch.target_kind, batch.target_bundle_id)
|
|
509
|
+
|| findActiveCheckAutoFixForTarget(projectId, batch.target_kind, batch.target_bundle_id)
|
|
434
510
|
|| db.prepare(`
|
|
435
511
|
SELECT 1 FROM execution_runs repair
|
|
436
512
|
JOIN check_repair_details details ON details.execution_run_id = repair.id
|
|
@@ -443,6 +519,27 @@ export const getCheckRepairCandidateState = async (projectId, batchRunId) => {
|
|
|
443
519
|
return { ...base, eligibility: { eligible: false, reason: 'busy' } };
|
|
444
520
|
}
|
|
445
521
|
const progressionRunId = sourceRun.initiated_by === 'automation' ? sourceRun.parent_run_id : null;
|
|
522
|
+
const primaryOwner = db.prepare(`
|
|
523
|
+
SELECT entity_type, entity_id FROM execution_run_links
|
|
524
|
+
WHERE execution_run_id = ? AND project_id = ? AND relationship = 'primary'
|
|
525
|
+
`).get(batchRunId, projectId);
|
|
526
|
+
if (primaryOwner?.entity_type === 'chat_session') {
|
|
527
|
+
const session = getChatSession(primaryOwner.entity_id);
|
|
528
|
+
if (!session
|
|
529
|
+
|| session.project_id !== projectId
|
|
530
|
+
|| session.mode !== 'build'
|
|
531
|
+
|| session.target_kind !== batch.target_kind
|
|
532
|
+
|| session.target_bundle_id !== batch.target_bundle_id) {
|
|
533
|
+
return { ...base, eligibility: { eligible: false, reason: 'non_repairable' } };
|
|
534
|
+
}
|
|
535
|
+
return {
|
|
536
|
+
...base,
|
|
537
|
+
eligibility: { eligible: true, reason: null },
|
|
538
|
+
candidate_chat_sessions: [{ id: session.id, title: session.title }],
|
|
539
|
+
eligible_attempt_run_ids: currentStructuredEvidence.map(row => row.execution_run_id),
|
|
540
|
+
eligible_raw_output_attempt_run_ids: currentRawOutputEvidence.map(row => row.execution_run_id),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
446
543
|
let candidates;
|
|
447
544
|
if (progressionRunId) {
|
|
448
545
|
const ticketIds = db.prepare(`
|
|
@@ -464,13 +561,14 @@ export const getCheckRepairCandidateState = async (projectId, batchRunId) => {
|
|
|
464
561
|
return {
|
|
465
562
|
eligibility: { eligible: true, reason: null },
|
|
466
563
|
candidate_tickets: candidateTickets,
|
|
564
|
+
candidate_chat_sessions: [],
|
|
467
565
|
accepts_ticket_id: !progressionRunId,
|
|
468
566
|
destination: toRepairDestination(purpose),
|
|
469
567
|
eligible_attempt_run_ids: currentStructuredEvidence.map(row => row.execution_run_id),
|
|
470
568
|
eligible_raw_output_attempt_run_ids: currentRawOutputEvidence.map(row => row.execution_run_id),
|
|
471
569
|
};
|
|
472
570
|
};
|
|
473
|
-
const formatRepairInstruction = (
|
|
571
|
+
const formatRepairInstruction = (ownerDescription, diagnosticEvidence, rawOutputEvidence) => {
|
|
474
572
|
const diagnostics = diagnosticEvidence.map(row => {
|
|
475
573
|
const location = row.file_path ? `${row.file_path}${row.start_line ? `:${row.start_line}` : ''}` : 'unknown location';
|
|
476
574
|
return `- [${escapePromptEvidence(row.definition_id)}] ${escapePromptEvidence(location)}: ${escapePromptEvidence(row.message.slice(0, MAX_PROMPT_DIAGNOSTIC_CHARS))}${row.code ? ` (${escapePromptEvidence(row.code)})` : ''}`;
|
|
@@ -484,11 +582,11 @@ const formatRepairInstruction = (ticket, diagnosticEvidence, rawOutputEvidence)
|
|
|
484
582
|
return `<check_output attempt_id="${escapePromptEvidence(row.attempt_run_id)}" evidence="${rawOnly ? 'raw_only' : 'diagnostic'}" truncated="${truncated}">\n${escapePromptEvidence(row.retained_output.slice(-MAX_PROMPT_OUTPUT_CHARS))}\n</check_output>`;
|
|
485
583
|
})
|
|
486
584
|
.join('\n\n');
|
|
487
|
-
return `You are repairing persisted command failures for an existing
|
|
585
|
+
return `You are repairing persisted command failures for an existing Build owner in its resolved workspace.
|
|
488
586
|
|
|
489
|
-
<
|
|
490
|
-
${escapePromptEvidence(
|
|
491
|
-
</
|
|
587
|
+
<build_owner>
|
|
588
|
+
${escapePromptEvidence(ownerDescription)}
|
|
589
|
+
</build_owner>
|
|
492
590
|
|
|
493
591
|
<check_diagnostics>
|
|
494
592
|
${diagnostics}
|
|
@@ -618,7 +716,9 @@ const completeRepairFollowUp = async (projectId, repairRunId, io) => {
|
|
|
618
716
|
targetLabel: sourceBatch.target_label,
|
|
619
717
|
selectedDefinitions: selected,
|
|
620
718
|
availableDefinitions: currentDefinitions,
|
|
621
|
-
sourceReference:
|
|
719
|
+
sourceReference: details.owner_type === 'ticket'
|
|
720
|
+
? { kind: 'ticket', id: details.owner_id }
|
|
721
|
+
: { kind: 'chat_session', id: details.owner_id },
|
|
622
722
|
rerunOfBatchRunId: sourceBatch.execution_run_id,
|
|
623
723
|
rerunAttemptRunIds,
|
|
624
724
|
automationParentRunId: details.automation_progression_run_id,
|
|
@@ -668,7 +768,7 @@ const completeRepairFollowUp = async (projectId, repairRunId, io) => {
|
|
|
668
768
|
});
|
|
669
769
|
return;
|
|
670
770
|
}
|
|
671
|
-
const ticket = getTicket(details.ticket_id);
|
|
771
|
+
const ticket = details.ticket_id ? getTicket(details.ticket_id) : null;
|
|
672
772
|
const bundle = getBundle(progressionBundleId, projectId);
|
|
673
773
|
if (!ticket || !bundle || getAutomationProgression(projectId, bundle.id)?.id !== details.automation_progression_run_id) {
|
|
674
774
|
throw new Error('Automation ownership changed before repaired checks completed');
|
|
@@ -773,7 +873,8 @@ const revalidateBeforeAgentStart = async (projectId, repairRunId, childRunId) =>
|
|
|
773
873
|
if (activeBatch) {
|
|
774
874
|
throw new Error(`Check target became busy before the repair agent could start (${activeBatch})`);
|
|
775
875
|
}
|
|
776
|
-
|
|
876
|
+
assertNoActiveCheckAutoFixForTarget(projectId, batch.target_kind, batch.target_bundle_id);
|
|
877
|
+
if (batch.target_bundle_id && getTargetMutationBlocker(projectId, batch.target_bundle_id, details.ticket_id ?? undefined)) {
|
|
777
878
|
throw new Error('Check target became busy with another worktree-mutating agent');
|
|
778
879
|
}
|
|
779
880
|
if (details.automation_progression_run_id) {
|
|
@@ -840,6 +941,7 @@ export const startCheckRepair = async (input) => {
|
|
|
840
941
|
if (activeBatch) {
|
|
841
942
|
throw new CheckRepairError(409, `Check target is busy with active batch ${activeBatch}`);
|
|
842
943
|
}
|
|
944
|
+
assertNoActiveCheckAutoFixForTarget(project.id, sourceBatch.target_kind, sourceBatch.target_bundle_id);
|
|
843
945
|
assertNoActiveCheckRepairForTarget(project.id, sourceBatch.target_kind, sourceBatch.target_bundle_id);
|
|
844
946
|
const progressionRunId = sourceRun.initiated_by === 'automation' ? sourceRun.parent_run_id : null;
|
|
845
947
|
const boundaryPurpose = progressionRunId ? sourceBatch.automation_boundary_purpose : null;
|
|
@@ -886,16 +988,19 @@ export const startCheckRepair = async (input) => {
|
|
|
886
988
|
targetBundleId: sourceBatch.target_bundle_id,
|
|
887
989
|
}, boundaryPurpose)
|
|
888
990
|
: null;
|
|
889
|
-
const
|
|
890
|
-
const
|
|
991
|
+
const owner = resolveRepairOwner(project.id, sourceBatch, sourceRun.id, input.ticketId ?? null, progressionRunId);
|
|
992
|
+
const causalExecution = resolveCausalExecution(project.id, sourceRun.id, owner.ownerType, owner.ownerId);
|
|
993
|
+
const causalAgentRun = resolveCausalAgentRun(causalExecution.id);
|
|
994
|
+
const mutationBlocker = getTargetMutationBlocker(project.id, targetBundleId, owner.ticket?.id);
|
|
891
995
|
if (mutationBlocker) {
|
|
892
996
|
throw new CheckRepairError(409, `Check target is busy with mutating ticket ${mutationBlocker}`);
|
|
893
997
|
}
|
|
894
998
|
const definitionIds = [...new Set(validated.evidence.map(row => row.definition_id))];
|
|
895
999
|
let repairContext;
|
|
896
1000
|
withExecutionRunTransaction(transaction => {
|
|
1001
|
+
assertNoActiveCheckAutoFixForTarget(project.id, sourceBatch.target_kind, sourceBatch.target_bundle_id);
|
|
897
1002
|
assertNoActiveCheckRepairForTarget(project.id, sourceBatch.target_kind, sourceBatch.target_bundle_id);
|
|
898
|
-
const transactionMutationBlocker = getTargetMutationBlocker(project.id, targetBundleId, ticket
|
|
1003
|
+
const transactionMutationBlocker = getTargetMutationBlocker(project.id, targetBundleId, owner.ticket?.id);
|
|
899
1004
|
if (transactionMutationBlocker) {
|
|
900
1005
|
throw new CheckRepairError(409, `Check target is busy with mutating ticket ${transactionMutationBlocker}`);
|
|
901
1006
|
}
|
|
@@ -908,9 +1013,11 @@ export const startCheckRepair = async (input) => {
|
|
|
908
1013
|
initiatedBy: progressionRunId ? 'automation' : 'user',
|
|
909
1014
|
parentRunId: progressionRunId,
|
|
910
1015
|
retryOfRunId: input.retryOfRepairRunId ?? undefined,
|
|
911
|
-
sourceReference:
|
|
912
|
-
|
|
913
|
-
|
|
1016
|
+
sourceReference: owner.ownerType === 'ticket'
|
|
1017
|
+
? { kind: 'ticket', id: owner.ownerId, label: owner.ticket?.title }
|
|
1018
|
+
: { kind: 'chat_session', id: owner.ownerId, label: owner.description },
|
|
1019
|
+
links: sourceBatch.target_bundle_id
|
|
1020
|
+
? [{ entityType: 'bundle', entityId: sourceBatch.target_bundle_id, relationship: 'context' }]
|
|
914
1021
|
: [],
|
|
915
1022
|
domainStatus: 'running',
|
|
916
1023
|
eventType: input.retryOfRepairRunId ? 'check_repair_retry_started' : 'check_repair_created',
|
|
@@ -924,12 +1031,13 @@ export const startCheckRepair = async (input) => {
|
|
|
924
1031
|
});
|
|
925
1032
|
db.prepare(`
|
|
926
1033
|
INSERT INTO check_repair_details (
|
|
927
|
-
execution_run_id, source_batch_run_id, target_kind, target_bundle_id,
|
|
1034
|
+
execution_run_id, source_batch_run_id, target_kind, target_bundle_id,
|
|
1035
|
+
owner_type, owner_id, ticket_id, causal_execution_run_id, causal_agent_run_id,
|
|
928
1036
|
automation_progression_run_id, automation_boundary_purpose, initial_workspace_identity_json,
|
|
929
1037
|
configuration_fingerprint, effective_policy_fingerprint, definition_ids_json,
|
|
930
1038
|
retry_of_check_repair_run_id
|
|
931
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
932
|
-
`).run(repair.id, sourceBatch.execution_run_id, sourceBatch.target_kind, sourceBatch.target_bundle_id, ticket.id, progressionRunId, boundaryPurpose, JSON.stringify(validated.finalIdentity), sourceBatch.configuration_fingerprint, effectivePolicyFingerprint, JSON.stringify(definitionIds), input.retryOfRepairRunId ?? null);
|
|
1039
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1040
|
+
`).run(repair.id, sourceBatch.execution_run_id, sourceBatch.target_kind, sourceBatch.target_bundle_id, owner.ownerType, owner.ownerId, owner.ticket?.id ?? null, causalExecution.id, causalAgentRun.id, progressionRunId, boundaryPurpose, JSON.stringify(validated.finalIdentity), sourceBatch.configuration_fingerprint, effectivePolicyFingerprint, JSON.stringify(definitionIds), input.retryOfRepairRunId ?? null);
|
|
933
1041
|
const insertProvenance = db.prepare(`
|
|
934
1042
|
INSERT INTO check_repair_diagnostic_provenance (
|
|
935
1043
|
check_repair_run_id, ordinal, diagnostic_id, attempt_run_id, definition_id
|
|
@@ -946,39 +1054,19 @@ export const startCheckRepair = async (input) => {
|
|
|
946
1054
|
}, asBroadcaster(input.io));
|
|
947
1055
|
const persistedDetails = getCheckRepairDetails(project.id, repairContext.runId);
|
|
948
1056
|
const persistedEvidence = assertRepairEvidence(project, persistedDetails.diagnostic_ids, persistedDetails.raw_output_attempt_run_ids);
|
|
949
|
-
const instruction = formatRepairInstruction(
|
|
950
|
-
const scheduling =
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
payload: undefined,
|
|
1057
|
+
const instruction = formatRepairInstruction(owner.description, persistedEvidence.diagnosticEvidence, persistedEvidence.rawOutputEvidence);
|
|
1058
|
+
const scheduling = dispatchCheckRepair({
|
|
1059
|
+
details: persistedDetails,
|
|
1060
|
+
instruction,
|
|
954
1061
|
broadcaster: asBroadcaster(input.io),
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
providerContinuation: 'fresh',
|
|
961
|
-
trustedTrigger: {
|
|
962
|
-
instruction,
|
|
963
|
-
onExecutionCreated: context => {
|
|
964
|
-
const updated = db.prepare(`
|
|
965
|
-
UPDATE check_repair_details SET follow_up_run_id = ?, updated_at = CURRENT_TIMESTAMP
|
|
966
|
-
WHERE execution_run_id = ? AND follow_up_run_id IS NULL
|
|
967
|
-
`).run(context.runId, repairContext.runId);
|
|
968
|
-
if (updated.changes !== 1) {
|
|
969
|
-
throw new Error('Check repair follow-up ownership could not be persisted');
|
|
970
|
-
}
|
|
1062
|
+
orchestration: {
|
|
1063
|
+
beforeStart: context => revalidateBeforeAgentStart(project.id, repairContext.runId, context.runId),
|
|
1064
|
+
onCompletion: () => completeRepairFollowUp(project.id, repairContext.runId, input.io),
|
|
1065
|
+
onCancellation: () => {
|
|
1066
|
+
failRepair(project.id, repairContext.runId, 'Check repair agent was stopped', 'cancelled', input.io);
|
|
971
1067
|
},
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
beforeStart: context => revalidateBeforeAgentStart(project.id, repairContext.runId, context.runId),
|
|
975
|
-
onCompletion: () => completeRepairFollowUp(project.id, repairContext.runId, input.io),
|
|
976
|
-
onCancellation: () => {
|
|
977
|
-
failRepair(project.id, repairContext.runId, 'Check repair follow-up was stopped', 'cancelled', input.io);
|
|
978
|
-
},
|
|
979
|
-
onFailure: (_context, message) => {
|
|
980
|
-
failRepair(project.id, repairContext.runId, message, 'failed', input.io);
|
|
981
|
-
},
|
|
1068
|
+
onFailure: (_context, message) => {
|
|
1069
|
+
failRepair(project.id, repairContext.runId, message, 'failed', input.io);
|
|
982
1070
|
},
|
|
983
1071
|
},
|
|
984
1072
|
});
|
|
@@ -1000,7 +1088,7 @@ export const retryCheckRepair = async (projectId, repairRunId, io) => {
|
|
|
1000
1088
|
projectId,
|
|
1001
1089
|
diagnosticIds: source.diagnostic_ids,
|
|
1002
1090
|
rawOutputAttemptRunIds: source.raw_output_attempt_run_ids,
|
|
1003
|
-
ticketId: source.automation_progression_run_id ? null : source.ticket_id,
|
|
1091
|
+
ticketId: source.automation_progression_run_id || source.owner_type === 'chat_session' ? null : source.ticket_id,
|
|
1004
1092
|
io,
|
|
1005
1093
|
retryOfRepairRunId: source.execution_run_id,
|
|
1006
1094
|
});
|
|
@@ -1035,11 +1123,12 @@ export const stopCheckRepair = async (projectId, repairRunId, io) => {
|
|
|
1035
1123
|
eventType: 'check_repair_follow_up_cancelled',
|
|
1036
1124
|
});
|
|
1037
1125
|
terminalizeAgentRunsForExecutionRun(followUp.id, 'stopped', 'Check repair was stopped');
|
|
1126
|
+
const ownerTable = details.owner_type === 'ticket' ? 'tickets' : 'chat_sessions';
|
|
1038
1127
|
db.prepare(`
|
|
1039
|
-
UPDATE
|
|
1128
|
+
UPDATE ${ownerTable} SET agent_status = 'stopped', agent_log = NULL,
|
|
1040
1129
|
streaming_response = NULL, updated_at = CURRENT_TIMESTAMP
|
|
1041
1130
|
WHERE id = ? AND project_id = ? AND agent_status = 'running'
|
|
1042
|
-
`).run(details.
|
|
1131
|
+
`).run(details.owner_id, projectId);
|
|
1043
1132
|
}
|
|
1044
1133
|
}
|
|
1045
1134
|
return true;
|
|
@@ -1051,7 +1140,13 @@ export const stopCheckRepair = async (projectId, repairRunId, io) => {
|
|
|
1051
1140
|
await stopCheckBatch(projectId, details.rerun_batch_run_id, io ? asBroadcaster(io) : undefined);
|
|
1052
1141
|
}
|
|
1053
1142
|
else if (stopFollowUpAgent) {
|
|
1054
|
-
|
|
1143
|
+
revokeAgentSpawnPermit(details.follow_up_run_id);
|
|
1144
|
+
if (details.owner_type === 'ticket') {
|
|
1145
|
+
await stopBuildAgent(details.owner_id);
|
|
1146
|
+
}
|
|
1147
|
+
else {
|
|
1148
|
+
await stopChatAgent(details.owner_id);
|
|
1149
|
+
}
|
|
1055
1150
|
}
|
|
1056
1151
|
return getCheckRepairDetails(projectId, repairRunId);
|
|
1057
1152
|
};
|