@straiffi/archon 1.7.2 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/assets/ActivityView-BgMz3NNT.js +1 -0
- package/dist/client/assets/GitHubActionsDialog-CNqWDS3E.js +1 -0
- package/dist/client/assets/TestsDialog-Cll7xJe0.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-Do9nbC8v.js → architectureDiagram-3BPJPVTR-BL5dYiul.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DGGOLHF8.js → blockDiagram-GPEHLZMM-Bi5x2v80.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-Bz7tQybs.js → c4Diagram-AAUBKEIU-esEm54Ay.js} +1 -1
- package/dist/client/assets/channel-CqNHF3FD.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CJO-GmWJ.js → chunk-2J33WTMH-DACfY8xM.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-DPAVagpC.js → chunk-3OPIFGDE-DZNUiaUs.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-Cof75Mu7.js → chunk-5ZQYHXKU-ClDfkMAp.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-COuPqQ8_.js → chunk-727SXJPM-CCwA3GWT.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CFj5KabW.js → chunk-AQP2D5EJ-Byl4DRZ9.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-C4M6w5cT.js → chunk-CSCIHK7Q-CXymZQ7A.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-ByaiwVue.js → chunk-KSCS5N6A-VV3D8g6a.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-Cx5jeot9.js → chunk-L5ZTLDWV-BL9N5GRI.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-DmGtztud.js → chunk-LZXEDZCA-DKNN-zno.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-i3yuspqL.js → chunk-ND2GUHAM-CHCpQ1yr.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-CQ4E_jP4.js → chunk-NZK2D7GU-B0Dm74mt.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-D2g4VDCd.js → chunk-O5CBEL6O-DAa5z2xG.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-exIu-zQ2.js → chunk-WU5MYG2G-DrVJWKVR.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BjEgQwKg.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-gGomH-F_.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-DvF75yLZ.js → dagre-BM42HDAG-B0fsl8mE.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DFv0HxLL.js → diagram-2AECGRRQ-Cx_VEbSS.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-C_LRir0-.js → diagram-5GNKFQAL-Cv7VVn5r.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DGZxRDRy.js → diagram-KO2AKTUF-C8Sl5czV.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-UXt0uti4.js → diagram-LMA3HP47-C3dZaLz2.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CFbZS4n5.js → diagram-OG6HWLK6-BAU9DtTr.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CfAwZDdf.js → erDiagram-TEJ5UH35-DpNc-eBD.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Cdgi5z3n.js → flowDiagram-I6XJVG4X-DGwTAT1S.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DOrkFkhu.js → ganttDiagram-6RSMTGT7-MPZhEgzJ.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-cEox0peD.js → gitGraphDiagram-PVQCEYII-CY0tHL5N.js} +1 -1
- package/dist/client/assets/index-CJRgmWwY.js +273 -0
- package/dist/client/assets/index-mRkJWu70.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-gm51u2Nn.js → infoDiagram-5YYISTIA-BBZeKjf4.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CjnoOIja.js → ishikawaDiagram-YF4QCWOH-CM_iFrES.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-Dlg4DsiO.js → journeyDiagram-JHISSGLW-Do_lY94X.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-BU0XZaSd.js → kanban-definition-UN3LZRKU-brxg3j37.js} +1 -1
- package/dist/client/assets/{line-Bert22-_.js → line-PHHbm9rj.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-BvQSGDmL.js → mermaid-parser.core-CLxAkW69.js} +1 -1
- package/dist/client/assets/{mermaid.core--qSAHJRj.js → mermaid.core-CebvSmx9.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BgFIvWWD.js → mindmap-definition-RKZ34NQL-CX_-ZaJF.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DGcbXD0M.js → pieDiagram-4H26LBE5-BJuHvql_.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-ClkBUeia.js → quadrantDiagram-W4KKPZXB-DiJll7l9.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-B8CwGToU.js → requirementDiagram-4Y6WPE33-Bg-tXgcj.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DTk3jL6B.js → sankeyDiagram-5OEKKPKP-BoK2egfZ.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BQVrcnKf.js → sequenceDiagram-3UESZ5HK-DcrDWNzv.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-DD4yMZPB.js → stateDiagram-AJRCARHV-B995qt1S.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Dn8P7Sa1.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-BnCBVqcd.js → timeline-definition-PNZ67QCA-DqSVAhqL.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-BDmLMNXS.js → vennDiagram-CIIHVFJN-D9wVraVY.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DSLuQiEv.js → wardleyDiagram-YWT4CUSO-CLff9zVd.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DAq_LA4r.js → xychartDiagram-2RQKCTM6-BuHUMMH2.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +472 -39
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +1311 -212
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +228 -71
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/agentRuns.js +205 -38
- package/dist/server/lib/agentRuns.js.map +1 -1
- package/dist/server/lib/attachments.js +24 -0
- package/dist/server/lib/attachments.js.map +1 -1
- package/dist/server/lib/automationProgression.js +464 -0
- package/dist/server/lib/automationProgression.js.map +1 -0
- package/dist/server/lib/automationReconciliation.js +498 -0
- package/dist/server/lib/automationReconciliation.js.map +1 -0
- package/dist/server/lib/automationStageDetails.js +232 -0
- package/dist/server/lib/automationStageDetails.js.map +1 -0
- package/dist/server/lib/buildOpenQuestionOperations.js +238 -0
- package/dist/server/lib/buildOpenQuestionOperations.js.map +1 -0
- package/dist/server/lib/buildOpenQuestions.js +44 -0
- package/dist/server/lib/buildOpenQuestions.js.map +1 -1
- package/dist/server/lib/buildSequences.js +130 -46
- package/dist/server/lib/buildSequences.js.map +1 -1
- package/dist/server/lib/bundleReviewOperations.js +91 -9
- package/dist/server/lib/bundleReviewOperations.js.map +1 -1
- package/dist/server/lib/chatOperations.js +67 -12
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/executionReconciliation.js +518 -0
- package/dist/server/lib/executionReconciliation.js.map +1 -0
- package/dist/server/lib/executionRetry.js +694 -0
- package/dist/server/lib/executionRetry.js.map +1 -0
- package/dist/server/lib/executionRetryContext.js +489 -0
- package/dist/server/lib/executionRetryContext.js.map +1 -0
- package/dist/server/lib/executionRetryPredicates.js +74 -0
- package/dist/server/lib/executionRetryPredicates.js.map +1 -0
- package/dist/server/lib/executionRunRetention.js +141 -0
- package/dist/server/lib/executionRunRetention.js.map +1 -0
- package/dist/server/lib/executionRuns.js +1367 -0
- package/dist/server/lib/executionRuns.js.map +1 -0
- package/dist/server/lib/executionTimeline.js +45 -0
- package/dist/server/lib/executionTimeline.js.map +1 -0
- package/dist/server/lib/git.js +385 -6
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/integrations/github.js +43 -0
- package/dist/server/lib/integrations/github.js.map +1 -1
- package/dist/server/lib/integrations/githubActions.js +1 -0
- package/dist/server/lib/integrations/githubActions.js.map +1 -1
- package/dist/server/lib/integrations/githubActionsSessions.js +337 -114
- package/dist/server/lib/integrations/githubActionsSessions.js.map +1 -1
- package/dist/server/lib/projectMemorySelections.js +7 -3
- package/dist/server/lib/projectMemorySelections.js.map +1 -1
- package/dist/server/lib/shutdown.js +2 -2
- package/dist/server/lib/shutdown.js.map +1 -1
- package/dist/server/lib/specArtifact.js +3 -0
- package/dist/server/lib/specArtifact.js.map +1 -1
- package/dist/server/lib/specFormatting.js +1 -1
- package/dist/server/lib/specFormatting.js.map +1 -1
- package/dist/server/lib/specOperations.js +78 -12
- package/dist/server/lib/specOperations.js.map +1 -1
- package/dist/server/lib/specReviewContext.js +54 -18
- package/dist/server/lib/specReviewContext.js.map +1 -1
- package/dist/server/lib/specReviewDraft.js +3 -2
- package/dist/server/lib/specReviewDraft.js.map +1 -1
- package/dist/server/lib/specReviewOperations.js +74 -9
- package/dist/server/lib/specReviewOperations.js.map +1 -1
- package/dist/server/lib/specReviewValidation.js +217 -0
- package/dist/server/lib/specReviewValidation.js.map +1 -0
- package/dist/server/lib/specReviews.js +30 -2
- package/dist/server/lib/specReviews.js.map +1 -1
- package/dist/server/lib/specs.js +18 -1
- package/dist/server/lib/specs.js.map +1 -1
- package/dist/server/lib/stageSnapshots.js +197 -0
- package/dist/server/lib/stageSnapshots.js.map +1 -0
- package/dist/server/lib/testSessions.js +160 -18
- package/dist/server/lib/testSessions.js.map +1 -1
- package/dist/server/lib/ticketAutomation.js +80 -4
- package/dist/server/lib/ticketAutomation.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +466 -91
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +270 -29
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/ticketMessages.js +16 -0
- package/dist/server/lib/ticketMessages.js.map +1 -1
- package/dist/server/lib/ticketRunOperations.js +51 -6
- package/dist/server/lib/ticketRunOperations.js.map +1 -1
- package/dist/server/lib/ticketUndo.js +77 -168
- package/dist/server/lib/ticketUndo.js.map +1 -1
- package/dist/server/lib/ticketWorkflowOperations.js +132 -28
- package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
- package/dist/server/lib/tickets.js +41 -27
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/lib/transcriptRuns.js +3 -3
- package/dist/server/lib/transcriptRuns.js.map +1 -1
- package/dist/server/lib/turnExecutionErrors.js +12 -0
- package/dist/server/lib/turnExecutionErrors.js.map +1 -0
- package/dist/server/lib/types.js +58 -1
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/workers/build.js +596 -184
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +269 -132
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +731 -203
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/plan.js +546 -188
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/planFollowUp.js +240 -75
- package/dist/server/workers/planFollowUp.js.map +1 -1
- package/dist/server/workers/review.js +790 -297
- package/dist/server/workers/review.js.map +1 -1
- package/dist/server/workers/specReview.js +212 -46
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +434 -254
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/GitHubActionsDialog-DAD5REmY.js +0 -1
- package/dist/client/assets/TestsDialog-B5NVrroq.js +0 -4
- package/dist/client/assets/TicketChangesModal-By-_gTGd.js +0 -1
- package/dist/client/assets/channel-Dd5Len0X.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-B7KUg6r8.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CQm-z5c4.js +0 -1
- package/dist/client/assets/index-BHq6-Eir.js +0 -270
- package/dist/client/assets/index-BxTc5qQT.css +0 -2
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-C8yO6POT.js +0 -1
package/dist/server/db.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
3
|
import { ensureParentDirectory, resolveArchonDbPath } from './lib/runtimePaths.js';
|
|
4
|
+
import { TRANSCRIPT_RUN_TEXT_LIMIT_BYTES, truncateUtf8 } from './lib/transcriptRuns.js';
|
|
4
5
|
const dbPath = ensureParentDirectory(resolveArchonDbPath());
|
|
5
6
|
const db = new Database(dbPath);
|
|
6
7
|
db.pragma('foreign_keys = ON');
|
|
@@ -11,6 +12,7 @@ db.exec(`
|
|
|
11
12
|
description TEXT,
|
|
12
13
|
state TEXT NOT NULL DEFAULT 'plan',
|
|
13
14
|
agent_status TEXT,
|
|
15
|
+
agent_operation TEXT,
|
|
14
16
|
parked_at DATETIME,
|
|
15
17
|
auto_park_dismissed_at DATETIME,
|
|
16
18
|
branch TEXT,
|
|
@@ -89,6 +91,7 @@ const ensureColumn = (table, column, type) => {
|
|
|
89
91
|
}
|
|
90
92
|
};
|
|
91
93
|
ensureColumn('tickets', 'model', 'TEXT');
|
|
94
|
+
ensureColumn('tickets', 'agent_operation', 'TEXT');
|
|
92
95
|
ensureColumn('tickets', 'variant', 'TEXT');
|
|
93
96
|
ensureColumn('tickets', 'skills_json', 'TEXT');
|
|
94
97
|
ensureColumn('tickets', 'session_id', 'TEXT');
|
|
@@ -1241,6 +1244,7 @@ ensureColumn('review_runs', 'workspace_signature', 'TEXT');
|
|
|
1241
1244
|
db.exec(`
|
|
1242
1245
|
CREATE TABLE IF NOT EXISTS agent_runs (
|
|
1243
1246
|
id TEXT PRIMARY KEY,
|
|
1247
|
+
execution_run_id TEXT,
|
|
1244
1248
|
parent_type TEXT NOT NULL,
|
|
1245
1249
|
parent_id TEXT NOT NULL,
|
|
1246
1250
|
run_index INTEGER NOT NULL,
|
|
@@ -1250,12 +1254,451 @@ db.exec(`
|
|
|
1250
1254
|
agent_log TEXT,
|
|
1251
1255
|
streaming_response TEXT,
|
|
1252
1256
|
response_text TEXT,
|
|
1257
|
+
failure_message TEXT,
|
|
1253
1258
|
session_id TEXT,
|
|
1259
|
+
completed_at DATETIME,
|
|
1254
1260
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
1255
|
-
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
1261
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
1262
|
+
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE,
|
|
1263
|
+
CHECK (failure_message IS NULL OR length(CAST(failure_message AS BLOB)) <= 16384)
|
|
1256
1264
|
)
|
|
1257
1265
|
`);
|
|
1266
|
+
const executionRunsTableSql = `
|
|
1267
|
+
CREATE TABLE execution_runs (
|
|
1268
|
+
id TEXT PRIMARY KEY,
|
|
1269
|
+
project_id TEXT NOT NULL,
|
|
1270
|
+
kind TEXT NOT NULL,
|
|
1271
|
+
status TEXT NOT NULL DEFAULT 'queued',
|
|
1272
|
+
domain_status TEXT,
|
|
1273
|
+
source_kind TEXT,
|
|
1274
|
+
source_id TEXT,
|
|
1275
|
+
source_label TEXT,
|
|
1276
|
+
source_url TEXT,
|
|
1277
|
+
correlation_id TEXT NOT NULL,
|
|
1278
|
+
initiated_by TEXT NOT NULL DEFAULT 'user',
|
|
1279
|
+
metadata_schema_version INTEGER NOT NULL DEFAULT 1,
|
|
1280
|
+
metadata_json TEXT,
|
|
1281
|
+
parent_run_id TEXT,
|
|
1282
|
+
retry_of_run_id TEXT,
|
|
1283
|
+
attempt INTEGER NOT NULL DEFAULT 1,
|
|
1284
|
+
failure_code TEXT,
|
|
1285
|
+
failure_message TEXT,
|
|
1286
|
+
failure_details_json TEXT,
|
|
1287
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1288
|
+
started_at DATETIME,
|
|
1289
|
+
completed_at DATETIME,
|
|
1290
|
+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1291
|
+
UNIQUE (id, project_id),
|
|
1292
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
1293
|
+
FOREIGN KEY (parent_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
1294
|
+
FOREIGN KEY (retry_of_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
1295
|
+
CHECK (length(kind) BETWEEN 1 AND 100),
|
|
1296
|
+
CHECK (status IN ('queued', 'running', 'waiting', 'completed', 'failed', 'cancelled', 'interrupted')),
|
|
1297
|
+
CHECK (length(correlation_id) >= 1),
|
|
1298
|
+
CHECK (initiated_by IN ('user', 'automation', 'recovery', 'system')),
|
|
1299
|
+
CHECK (metadata_schema_version >= 1),
|
|
1300
|
+
CHECK (metadata_json IS NULL OR length(metadata_json) <= 16384),
|
|
1301
|
+
CHECK (attempt >= 1)
|
|
1302
|
+
)
|
|
1303
|
+
`;
|
|
1304
|
+
const lifecycleEventsTableSql = `
|
|
1305
|
+
CREATE TABLE lifecycle_events (
|
|
1306
|
+
id TEXT PRIMARY KEY,
|
|
1307
|
+
project_id TEXT NOT NULL,
|
|
1308
|
+
execution_run_id TEXT NOT NULL,
|
|
1309
|
+
correlation_id TEXT NOT NULL,
|
|
1310
|
+
sequence INTEGER NOT NULL,
|
|
1311
|
+
event_type TEXT NOT NULL,
|
|
1312
|
+
from_status TEXT,
|
|
1313
|
+
to_status TEXT,
|
|
1314
|
+
domain_status TEXT,
|
|
1315
|
+
message TEXT,
|
|
1316
|
+
metadata_schema_version INTEGER NOT NULL DEFAULT 1,
|
|
1317
|
+
metadata_json TEXT,
|
|
1318
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1319
|
+
UNIQUE (execution_run_id, sequence),
|
|
1320
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
1321
|
+
FOREIGN KEY (execution_run_id, project_id) REFERENCES execution_runs(id, project_id) ON DELETE CASCADE,
|
|
1322
|
+
CHECK (length(correlation_id) >= 1),
|
|
1323
|
+
CHECK (sequence >= 1),
|
|
1324
|
+
CHECK (from_status IS NULL OR from_status IN ('queued', 'running', 'waiting', 'completed', 'failed', 'cancelled', 'interrupted')),
|
|
1325
|
+
CHECK (to_status IS NULL OR to_status IN ('queued', 'running', 'waiting', 'completed', 'failed', 'cancelled', 'interrupted')),
|
|
1326
|
+
CHECK (metadata_schema_version >= 1)
|
|
1327
|
+
)
|
|
1328
|
+
`;
|
|
1329
|
+
db.exec(executionRunsTableSql.replace('CREATE TABLE execution_runs', 'CREATE TABLE IF NOT EXISTS execution_runs'));
|
|
1330
|
+
db.exec(lifecycleEventsTableSql.replace('CREATE TABLE lifecycle_events', 'CREATE TABLE IF NOT EXISTS lifecycle_events'));
|
|
1331
|
+
const migrateExecutionLifecycleSchema = () => {
|
|
1332
|
+
const runColumns = db.prepare('PRAGMA table_info(execution_runs)').all();
|
|
1333
|
+
const eventColumns = db.prepare('PRAGMA table_info(lifecycle_events)').all();
|
|
1334
|
+
const runTableSql = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'execution_runs'").get()?.sql ?? '';
|
|
1335
|
+
const correlationColumn = runColumns.find(column => column.name === 'correlation_id');
|
|
1336
|
+
const needsMigration = !runColumns.some(column => column.name === 'initiated_by')
|
|
1337
|
+
|| !runColumns.some(column => column.name === 'metadata_json')
|
|
1338
|
+
|| correlationColumn?.notnull !== 1
|
|
1339
|
+
|| !eventColumns.some(column => column.name === 'sequence')
|
|
1340
|
+
|| !eventColumns.some(column => column.name === 'correlation_id')
|
|
1341
|
+
|| /CHECK\s*\(\s*kind\s+IN/i.test(runTableSql)
|
|
1342
|
+
|| /length\s*\(\s*correlation_id\s*\)\s+BETWEEN/i.test(runTableSql);
|
|
1343
|
+
if (!needsMigration) {
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
const sourceLabel = runColumns.some(column => column.name === 'source_label') ? 'source_label' : 'NULL';
|
|
1347
|
+
const legacyCorrelationId = runColumns.some(column => column.name === 'correlation_id')
|
|
1348
|
+
? 'CASE WHEN correlation_id IS NOT NULL AND length(trim(correlation_id)) > 0 THEN correlation_id ELSE NULL END'
|
|
1349
|
+
: 'NULL';
|
|
1350
|
+
db.exec('PRAGMA foreign_keys = OFF');
|
|
1351
|
+
try {
|
|
1352
|
+
db.exec('BEGIN');
|
|
1353
|
+
db.exec(executionRunsTableSql.replace('execution_runs', 'execution_runs_v2'));
|
|
1354
|
+
db.exec(lifecycleEventsTableSql.replace('lifecycle_events', 'lifecycle_events_v2').replaceAll('execution_runs', 'execution_runs_v2'));
|
|
1355
|
+
db.exec(`
|
|
1356
|
+
CREATE TEMP TABLE execution_run_correlations (
|
|
1357
|
+
id TEXT PRIMARY KEY,
|
|
1358
|
+
correlation_id TEXT
|
|
1359
|
+
)
|
|
1360
|
+
`);
|
|
1361
|
+
db.exec(`
|
|
1362
|
+
INSERT INTO execution_run_correlations (id, correlation_id)
|
|
1363
|
+
SELECT
|
|
1364
|
+
id,
|
|
1365
|
+
COALESCE(
|
|
1366
|
+
${legacyCorrelationId},
|
|
1367
|
+
CASE WHEN parent_run_id IS NULL THEN CASE WHEN length(id) > 0 THEN id ELSE 'legacy-run' END END
|
|
1368
|
+
)
|
|
1369
|
+
FROM execution_runs
|
|
1370
|
+
`);
|
|
1371
|
+
const inheritCorrelation = db.prepare(`
|
|
1372
|
+
UPDATE execution_run_correlations
|
|
1373
|
+
SET correlation_id = (
|
|
1374
|
+
SELECT parent.correlation_id
|
|
1375
|
+
FROM execution_runs child
|
|
1376
|
+
JOIN execution_run_correlations parent ON parent.id = child.parent_run_id
|
|
1377
|
+
WHERE child.id = execution_run_correlations.id
|
|
1378
|
+
)
|
|
1379
|
+
WHERE correlation_id IS NULL
|
|
1380
|
+
AND EXISTS (
|
|
1381
|
+
SELECT 1
|
|
1382
|
+
FROM execution_runs child
|
|
1383
|
+
JOIN execution_run_correlations parent ON parent.id = child.parent_run_id
|
|
1384
|
+
WHERE child.id = execution_run_correlations.id
|
|
1385
|
+
AND parent.correlation_id IS NOT NULL
|
|
1386
|
+
)
|
|
1387
|
+
`);
|
|
1388
|
+
while (inheritCorrelation.run().changes > 0) {
|
|
1389
|
+
// Resolve one lineage level at a time so descendants inherit the migrated root correlation.
|
|
1390
|
+
}
|
|
1391
|
+
db.exec(`
|
|
1392
|
+
UPDATE execution_run_correlations
|
|
1393
|
+
SET correlation_id = CASE WHEN length(id) > 0 THEN id ELSE 'legacy-run' END
|
|
1394
|
+
WHERE correlation_id IS NULL
|
|
1395
|
+
`);
|
|
1396
|
+
db.exec(`
|
|
1397
|
+
INSERT INTO execution_runs_v2 (
|
|
1398
|
+
id, project_id, kind, status, domain_status, source_kind, source_id, source_label,
|
|
1399
|
+
source_url, correlation_id, initiated_by, metadata_schema_version, metadata_json,
|
|
1400
|
+
parent_run_id, retry_of_run_id, attempt, failure_code, failure_message,
|
|
1401
|
+
failure_details_json, created_at, started_at, completed_at, updated_at
|
|
1402
|
+
)
|
|
1403
|
+
SELECT
|
|
1404
|
+
id, project_id, kind, status, domain_status, source_kind, source_id, ${sourceLabel},
|
|
1405
|
+
source_url,
|
|
1406
|
+
correlations.correlation_id,
|
|
1407
|
+
'system', 1, NULL, parent_run_id, retry_of_run_id, attempt, failure_code,
|
|
1408
|
+
failure_message, failure_details_json, created_at, started_at, completed_at, updated_at
|
|
1409
|
+
FROM execution_runs
|
|
1410
|
+
JOIN execution_run_correlations correlations USING (id)
|
|
1411
|
+
`);
|
|
1412
|
+
db.exec(`
|
|
1413
|
+
INSERT INTO lifecycle_events_v2 (
|
|
1414
|
+
id, project_id, execution_run_id, correlation_id, sequence, event_type,
|
|
1415
|
+
from_status, to_status, domain_status, message, metadata_schema_version,
|
|
1416
|
+
metadata_json, created_at
|
|
1417
|
+
)
|
|
1418
|
+
SELECT
|
|
1419
|
+
event.id,
|
|
1420
|
+
event.project_id,
|
|
1421
|
+
event.execution_run_id,
|
|
1422
|
+
run.correlation_id,
|
|
1423
|
+
1 + (
|
|
1424
|
+
SELECT COUNT(*)
|
|
1425
|
+
FROM lifecycle_events preceding
|
|
1426
|
+
WHERE preceding.execution_run_id = event.execution_run_id
|
|
1427
|
+
AND (
|
|
1428
|
+
preceding.created_at < event.created_at
|
|
1429
|
+
OR (preceding.created_at = event.created_at AND preceding.id < event.id)
|
|
1430
|
+
)
|
|
1431
|
+
),
|
|
1432
|
+
event.event_type,
|
|
1433
|
+
event.from_status,
|
|
1434
|
+
event.to_status,
|
|
1435
|
+
event.domain_status,
|
|
1436
|
+
event.message,
|
|
1437
|
+
event.metadata_schema_version,
|
|
1438
|
+
event.metadata_json,
|
|
1439
|
+
event.created_at
|
|
1440
|
+
FROM lifecycle_events event
|
|
1441
|
+
JOIN execution_runs_v2 run
|
|
1442
|
+
ON run.id = event.execution_run_id AND run.project_id = event.project_id
|
|
1443
|
+
`);
|
|
1444
|
+
db.exec('DROP TABLE lifecycle_events');
|
|
1445
|
+
db.exec('DROP TABLE execution_runs');
|
|
1446
|
+
db.exec('ALTER TABLE execution_runs_v2 RENAME TO execution_runs');
|
|
1447
|
+
db.exec('ALTER TABLE lifecycle_events_v2 RENAME TO lifecycle_events');
|
|
1448
|
+
db.exec('DROP TABLE execution_run_correlations');
|
|
1449
|
+
const violations = db.prepare('PRAGMA foreign_key_check').all();
|
|
1450
|
+
if (violations.some(violation => ['execution_runs', 'lifecycle_events', 'test_execution_details', 'github_actions_run_details'].includes(violation.table))) {
|
|
1451
|
+
throw new Error('Execution lifecycle migration produced foreign key violations');
|
|
1452
|
+
}
|
|
1453
|
+
db.exec('COMMIT');
|
|
1454
|
+
}
|
|
1455
|
+
catch (error) {
|
|
1456
|
+
db.exec('ROLLBACK');
|
|
1457
|
+
throw error;
|
|
1458
|
+
}
|
|
1459
|
+
finally {
|
|
1460
|
+
db.exec('PRAGMA foreign_keys = ON');
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
migrateExecutionLifecycleSchema();
|
|
1464
|
+
const migrateAgentRunsSchema = () => {
|
|
1465
|
+
const columns = db.prepare('PRAGMA table_info(agent_runs)').all();
|
|
1466
|
+
const tableSql = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'agent_runs'").get()?.sql ?? '';
|
|
1467
|
+
const needsMigration = !columns.some(column => column.name === 'execution_run_id')
|
|
1468
|
+
|| !columns.some(column => column.name === 'completed_at')
|
|
1469
|
+
|| !columns.some(column => column.name === 'failure_message')
|
|
1470
|
+
|| !/REFERENCES\s+execution_runs/i.test(tableSql)
|
|
1471
|
+
|| !/failure_message[\s\S]*16384/i.test(tableSql);
|
|
1472
|
+
if (!needsMigration) {
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1475
|
+
const executionRunId = columns.some(column => column.name === 'execution_run_id')
|
|
1476
|
+
? 'CASE WHEN execution_run_id IN (SELECT id FROM execution_runs) THEN execution_run_id ELSE NULL END'
|
|
1477
|
+
: 'NULL';
|
|
1478
|
+
const completedAt = columns.some(column => column.name === 'completed_at') ? 'completed_at' : 'NULL';
|
|
1479
|
+
const failureMessage = columns.some(column => column.name === 'failure_message')
|
|
1480
|
+
? 'CASE WHEN failure_message IS NULL OR length(CAST(failure_message AS BLOB)) <= 16384 THEN failure_message ELSE NULL END'
|
|
1481
|
+
: 'NULL';
|
|
1482
|
+
db.exec('PRAGMA foreign_keys = OFF');
|
|
1483
|
+
try {
|
|
1484
|
+
db.exec('BEGIN');
|
|
1485
|
+
db.exec(`
|
|
1486
|
+
CREATE TABLE agent_runs_v2 (
|
|
1487
|
+
id TEXT PRIMARY KEY,
|
|
1488
|
+
execution_run_id TEXT,
|
|
1489
|
+
parent_type TEXT NOT NULL,
|
|
1490
|
+
parent_id TEXT NOT NULL,
|
|
1491
|
+
run_index INTEGER NOT NULL,
|
|
1492
|
+
label TEXT NOT NULL,
|
|
1493
|
+
role TEXT NOT NULL,
|
|
1494
|
+
agent_status TEXT NOT NULL,
|
|
1495
|
+
agent_log TEXT,
|
|
1496
|
+
streaming_response TEXT,
|
|
1497
|
+
response_text TEXT,
|
|
1498
|
+
failure_message TEXT,
|
|
1499
|
+
session_id TEXT,
|
|
1500
|
+
completed_at DATETIME,
|
|
1501
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
1502
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
1503
|
+
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE,
|
|
1504
|
+
CHECK (failure_message IS NULL OR length(CAST(failure_message AS BLOB)) <= 16384)
|
|
1505
|
+
)
|
|
1506
|
+
`);
|
|
1507
|
+
db.exec(`
|
|
1508
|
+
INSERT INTO agent_runs_v2 (
|
|
1509
|
+
id, execution_run_id, parent_type, parent_id, run_index, label, role,
|
|
1510
|
+
agent_status, agent_log, streaming_response, response_text, failure_message,
|
|
1511
|
+
session_id, completed_at, created_at, updated_at
|
|
1512
|
+
)
|
|
1513
|
+
SELECT
|
|
1514
|
+
id, ${executionRunId}, parent_type, parent_id, run_index, label, role,
|
|
1515
|
+
agent_status, agent_log, streaming_response, response_text, ${failureMessage},
|
|
1516
|
+
session_id, ${completedAt}, created_at, updated_at
|
|
1517
|
+
FROM agent_runs
|
|
1518
|
+
`);
|
|
1519
|
+
db.exec('DROP TABLE agent_runs');
|
|
1520
|
+
db.exec('ALTER TABLE agent_runs_v2 RENAME TO agent_runs');
|
|
1521
|
+
const violations = db.prepare('PRAGMA foreign_key_check').all();
|
|
1522
|
+
if (violations.some(violation => violation.table === 'agent_runs' || violation.table === 'project_memory_selections')) {
|
|
1523
|
+
throw new Error('Agent run migration produced foreign key violations');
|
|
1524
|
+
}
|
|
1525
|
+
db.exec('COMMIT');
|
|
1526
|
+
}
|
|
1527
|
+
catch (error) {
|
|
1528
|
+
db.exec('ROLLBACK');
|
|
1529
|
+
throw error;
|
|
1530
|
+
}
|
|
1531
|
+
finally {
|
|
1532
|
+
db.exec('PRAGMA foreign_keys = ON');
|
|
1533
|
+
}
|
|
1534
|
+
};
|
|
1535
|
+
migrateAgentRunsSchema();
|
|
1536
|
+
const oversizedAgentRunRows = db.prepare(`
|
|
1537
|
+
SELECT id, agent_log, streaming_response, response_text, failure_message
|
|
1538
|
+
FROM agent_runs
|
|
1539
|
+
WHERE length(CAST(agent_log AS BLOB)) > ?
|
|
1540
|
+
OR length(CAST(streaming_response AS BLOB)) > ?
|
|
1541
|
+
OR length(CAST(response_text AS BLOB)) > ?
|
|
1542
|
+
OR length(CAST(failure_message AS BLOB)) > 16384
|
|
1543
|
+
`).all(TRANSCRIPT_RUN_TEXT_LIMIT_BYTES, TRANSCRIPT_RUN_TEXT_LIMIT_BYTES, TRANSCRIPT_RUN_TEXT_LIMIT_BYTES);
|
|
1544
|
+
const boundAgentRunEvidenceStatement = db.prepare(`
|
|
1545
|
+
UPDATE agent_runs
|
|
1546
|
+
SET agent_log = ?, streaming_response = ?, response_text = ?, failure_message = ?
|
|
1547
|
+
WHERE id = ?
|
|
1548
|
+
`);
|
|
1549
|
+
const boundAgentRunEvidence = db.transaction(() => {
|
|
1550
|
+
for (const row of oversizedAgentRunRows) {
|
|
1551
|
+
boundAgentRunEvidenceStatement.run(truncateUtf8(row.agent_log).text, truncateUtf8(row.streaming_response).text, truncateUtf8(row.response_text).text, truncateUtf8(row.failure_message, 16384).text, row.id);
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1554
|
+
boundAgentRunEvidence();
|
|
1258
1555
|
db.exec('CREATE INDEX IF NOT EXISTS idx_agent_runs_parent ON agent_runs(parent_type, parent_id)');
|
|
1556
|
+
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_agent_runs_execution_run_index ON agent_runs(execution_run_id, run_index) WHERE execution_run_id IS NOT NULL');
|
|
1557
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_agent_runs_active_parent ON agent_runs(parent_type, parent_id, execution_run_id, agent_status, created_at DESC, id DESC)');
|
|
1558
|
+
db.exec(`
|
|
1559
|
+
CREATE TABLE IF NOT EXISTS execution_run_links (
|
|
1560
|
+
execution_run_id TEXT NOT NULL,
|
|
1561
|
+
project_id TEXT NOT NULL,
|
|
1562
|
+
entity_type TEXT NOT NULL,
|
|
1563
|
+
entity_id TEXT NOT NULL,
|
|
1564
|
+
relationship TEXT NOT NULL,
|
|
1565
|
+
label_snapshot TEXT,
|
|
1566
|
+
url_snapshot TEXT,
|
|
1567
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1568
|
+
PRIMARY KEY (execution_run_id, entity_type, entity_id, relationship),
|
|
1569
|
+
FOREIGN KEY (execution_run_id, project_id) REFERENCES execution_runs(id, project_id) ON DELETE CASCADE,
|
|
1570
|
+
CHECK (length(entity_type) BETWEEN 1 AND 100),
|
|
1571
|
+
CHECK (length(entity_id) BETWEEN 1 AND 500),
|
|
1572
|
+
CHECK (relationship IN ('primary', 'context', 'result', 'trigger')),
|
|
1573
|
+
CHECK (label_snapshot IS NULL OR length(label_snapshot) <= 500),
|
|
1574
|
+
CHECK (url_snapshot IS NULL OR length(url_snapshot) <= 2000)
|
|
1575
|
+
)
|
|
1576
|
+
`);
|
|
1577
|
+
db.exec(`
|
|
1578
|
+
INSERT OR IGNORE INTO execution_run_links (
|
|
1579
|
+
execution_run_id, project_id, entity_type, entity_id, relationship,
|
|
1580
|
+
label_snapshot, url_snapshot, created_at
|
|
1581
|
+
)
|
|
1582
|
+
SELECT
|
|
1583
|
+
id, project_id, substr(source_kind, 1, 100), substr(source_id, 1, 500), 'primary',
|
|
1584
|
+
CASE WHEN source_label IS NULL THEN NULL ELSE substr(source_label, 1, 500) END,
|
|
1585
|
+
CASE WHEN source_url IS NULL THEN NULL ELSE substr(source_url, 1, 2000) END,
|
|
1586
|
+
created_at
|
|
1587
|
+
FROM execution_runs
|
|
1588
|
+
WHERE source_kind IS NOT NULL AND length(trim(source_kind)) > 0
|
|
1589
|
+
AND source_id IS NOT NULL AND length(trim(source_id)) > 0
|
|
1590
|
+
`);
|
|
1591
|
+
db.exec(`
|
|
1592
|
+
CREATE TABLE IF NOT EXISTS test_execution_details (
|
|
1593
|
+
execution_run_id TEXT PRIMARY KEY,
|
|
1594
|
+
command_id TEXT,
|
|
1595
|
+
command_name TEXT,
|
|
1596
|
+
command_runner TEXT,
|
|
1597
|
+
command_snapshot TEXT,
|
|
1598
|
+
active_command TEXT,
|
|
1599
|
+
target_kind TEXT,
|
|
1600
|
+
target_bundle_id TEXT,
|
|
1601
|
+
target_label TEXT,
|
|
1602
|
+
ticket_id TEXT,
|
|
1603
|
+
selection_json TEXT,
|
|
1604
|
+
summary_json TEXT,
|
|
1605
|
+
exit_code INTEGER,
|
|
1606
|
+
duration_ms INTEGER,
|
|
1607
|
+
output TEXT NOT NULL DEFAULT '',
|
|
1608
|
+
output_truncated INTEGER NOT NULL DEFAULT 0,
|
|
1609
|
+
output_retention_state TEXT NOT NULL DEFAULT 'retained',
|
|
1610
|
+
output_expired_at DATETIME,
|
|
1611
|
+
output_byte_count INTEGER,
|
|
1612
|
+
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE
|
|
1613
|
+
)
|
|
1614
|
+
`);
|
|
1615
|
+
db.exec(`
|
|
1616
|
+
CREATE TRIGGER IF NOT EXISTS validate_test_execution_details_target_insert
|
|
1617
|
+
BEFORE INSERT ON test_execution_details
|
|
1618
|
+
WHEN NEW.target_kind IS NULL
|
|
1619
|
+
OR NEW.target_kind NOT IN ('repo_root', 'bundle')
|
|
1620
|
+
OR (NEW.target_kind = 'repo_root' AND NEW.target_bundle_id IS NOT NULL)
|
|
1621
|
+
OR (NEW.target_kind = 'bundle' AND (NEW.target_bundle_id IS NULL OR length(trim(NEW.target_bundle_id)) = 0))
|
|
1622
|
+
BEGIN
|
|
1623
|
+
SELECT RAISE(ABORT, 'Invalid test execution target');
|
|
1624
|
+
END
|
|
1625
|
+
`);
|
|
1626
|
+
db.exec(`
|
|
1627
|
+
CREATE TRIGGER IF NOT EXISTS validate_test_execution_details_target_update
|
|
1628
|
+
BEFORE UPDATE OF target_kind, target_bundle_id ON test_execution_details
|
|
1629
|
+
WHEN NEW.target_kind IS NULL
|
|
1630
|
+
OR NEW.target_kind NOT IN ('repo_root', 'bundle')
|
|
1631
|
+
OR (NEW.target_kind = 'repo_root' AND NEW.target_bundle_id IS NOT NULL)
|
|
1632
|
+
OR (NEW.target_kind = 'bundle' AND (NEW.target_bundle_id IS NULL OR length(trim(NEW.target_bundle_id)) = 0))
|
|
1633
|
+
BEGIN
|
|
1634
|
+
SELECT RAISE(ABORT, 'Invalid test execution target');
|
|
1635
|
+
END
|
|
1636
|
+
`);
|
|
1637
|
+
ensureColumn('test_execution_details', 'command_snapshot', 'TEXT');
|
|
1638
|
+
ensureColumn('test_execution_details', 'active_command', 'TEXT');
|
|
1639
|
+
ensureColumn('test_execution_details', 'target_label', 'TEXT');
|
|
1640
|
+
ensureColumn('test_execution_details', 'output', "TEXT NOT NULL DEFAULT ''");
|
|
1641
|
+
ensureColumn('test_execution_details', 'output_truncated', 'INTEGER NOT NULL DEFAULT 0');
|
|
1642
|
+
ensureColumn('test_execution_details', 'output_retention_state', "TEXT NOT NULL DEFAULT 'retained'");
|
|
1643
|
+
ensureColumn('test_execution_details', 'output_expired_at', 'DATETIME');
|
|
1644
|
+
ensureColumn('test_execution_details', 'output_byte_count', 'INTEGER');
|
|
1645
|
+
db.prepare(`
|
|
1646
|
+
UPDATE test_execution_details
|
|
1647
|
+
SET output_byte_count = length(CAST(output AS BLOB))
|
|
1648
|
+
WHERE output_byte_count IS NULL AND output_retention_state = 'retained'
|
|
1649
|
+
`).run();
|
|
1650
|
+
db.exec(`
|
|
1651
|
+
CREATE TABLE IF NOT EXISTS github_actions_run_details (
|
|
1652
|
+
execution_run_id TEXT PRIMARY KEY,
|
|
1653
|
+
workflow_id INTEGER NOT NULL,
|
|
1654
|
+
workflow_name TEXT,
|
|
1655
|
+
ref TEXT,
|
|
1656
|
+
input_names_json TEXT,
|
|
1657
|
+
input_fingerprint TEXT,
|
|
1658
|
+
resolution_attempts INTEGER NOT NULL DEFAULT 0,
|
|
1659
|
+
provider_error_count INTEGER NOT NULL DEFAULT 0,
|
|
1660
|
+
provider_run_id INTEGER,
|
|
1661
|
+
provider_status TEXT,
|
|
1662
|
+
conclusion TEXT,
|
|
1663
|
+
html_url TEXT,
|
|
1664
|
+
head_sha TEXT,
|
|
1665
|
+
head_branch TEXT,
|
|
1666
|
+
provider_created_at DATETIME,
|
|
1667
|
+
provider_updated_at DATETIME,
|
|
1668
|
+
provider_started_at DATETIME,
|
|
1669
|
+
dispatched_at DATETIME,
|
|
1670
|
+
last_synced_at DATETIME,
|
|
1671
|
+
jobs_json TEXT,
|
|
1672
|
+
jobs_retention_state TEXT NOT NULL DEFAULT 'retained',
|
|
1673
|
+
jobs_expired_at DATETIME,
|
|
1674
|
+
jobs_count INTEGER,
|
|
1675
|
+
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE
|
|
1676
|
+
)
|
|
1677
|
+
`);
|
|
1678
|
+
ensureColumn('github_actions_run_details', 'ref', 'TEXT');
|
|
1679
|
+
ensureColumn('github_actions_run_details', 'input_names_json', 'TEXT');
|
|
1680
|
+
ensureColumn('github_actions_run_details', 'input_fingerprint', 'TEXT');
|
|
1681
|
+
ensureColumn('github_actions_run_details', 'resolution_attempts', 'INTEGER NOT NULL DEFAULT 0');
|
|
1682
|
+
ensureColumn('github_actions_run_details', 'provider_error_count', 'INTEGER NOT NULL DEFAULT 0');
|
|
1683
|
+
ensureColumn('github_actions_run_details', 'jobs_json', 'TEXT');
|
|
1684
|
+
ensureColumn('github_actions_run_details', 'provider_created_at', 'DATETIME');
|
|
1685
|
+
ensureColumn('github_actions_run_details', 'provider_updated_at', 'DATETIME');
|
|
1686
|
+
ensureColumn('github_actions_run_details', 'provider_started_at', 'DATETIME');
|
|
1687
|
+
ensureColumn('github_actions_run_details', 'jobs_retention_state', "TEXT NOT NULL DEFAULT 'retained'");
|
|
1688
|
+
ensureColumn('github_actions_run_details', 'jobs_expired_at', 'DATETIME');
|
|
1689
|
+
ensureColumn('github_actions_run_details', 'jobs_count', 'INTEGER');
|
|
1690
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_runs_project_created ON execution_runs(project_id, created_at DESC, id DESC)');
|
|
1691
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_runs_project_kind_status ON execution_runs(project_id, kind, status, created_at DESC, id DESC)');
|
|
1692
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_runs_parent ON execution_runs(parent_run_id)');
|
|
1693
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_runs_retry ON execution_runs(retry_of_run_id)');
|
|
1694
|
+
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_execution_runs_direct_retry ON execution_runs(retry_of_run_id) WHERE retry_of_run_id IS NOT NULL');
|
|
1695
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_runs_correlation ON execution_runs(project_id, correlation_id)');
|
|
1696
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_run_links_project_entity ON execution_run_links(project_id, entity_type, entity_id, created_at DESC)');
|
|
1697
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_run_links_run_relationship ON execution_run_links(execution_run_id, relationship, created_at ASC)');
|
|
1698
|
+
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_execution_run_links_primary ON execution_run_links(execution_run_id) WHERE relationship = 'primary'");
|
|
1699
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_lifecycle_events_run_sequence ON lifecycle_events(project_id, execution_run_id, sequence ASC)');
|
|
1700
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_lifecycle_events_project_created ON lifecycle_events(project_id, created_at DESC, id DESC)');
|
|
1701
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_github_actions_details_dispatch ON github_actions_run_details(workflow_id, ref, dispatched_at DESC)');
|
|
1259
1702
|
db.exec(`
|
|
1260
1703
|
CREATE TABLE IF NOT EXISTS project_memory_selections (
|
|
1261
1704
|
id TEXT PRIMARY KEY,
|
|
@@ -1374,6 +1817,9 @@ db.exec(`
|
|
|
1374
1817
|
worktree_bundle_id TEXT NOT NULL,
|
|
1375
1818
|
review_iteration_count INTEGER NOT NULL DEFAULT 0,
|
|
1376
1819
|
fix_loop_active INTEGER NOT NULL DEFAULT 0,
|
|
1820
|
+
automation_progression_run_id TEXT,
|
|
1821
|
+
automation_paused_stage_run_id TEXT,
|
|
1822
|
+
automation_pause_reason_code TEXT,
|
|
1377
1823
|
automation_paused_code TEXT,
|
|
1378
1824
|
automation_paused_reason TEXT,
|
|
1379
1825
|
automation_paused_at DATETIME,
|
|
@@ -1385,6 +1831,29 @@ db.exec(`
|
|
|
1385
1831
|
)
|
|
1386
1832
|
`);
|
|
1387
1833
|
ensureColumn('bundle_automation_state', 'automation_paused_code', 'TEXT');
|
|
1834
|
+
ensureColumn('bundle_automation_state', 'automation_progression_run_id', 'TEXT');
|
|
1835
|
+
ensureColumn('bundle_automation_state', 'automation_paused_stage_run_id', 'TEXT');
|
|
1836
|
+
ensureColumn('bundle_automation_state', 'automation_pause_reason_code', 'TEXT');
|
|
1837
|
+
db.exec(`
|
|
1838
|
+
CREATE TABLE IF NOT EXISTS automation_stage_details (
|
|
1839
|
+
execution_run_id TEXT PRIMARY KEY,
|
|
1840
|
+
project_id TEXT NOT NULL,
|
|
1841
|
+
worktree_bundle_id TEXT NOT NULL,
|
|
1842
|
+
stage_kind TEXT NOT NULL,
|
|
1843
|
+
schema_version INTEGER NOT NULL,
|
|
1844
|
+
intent_json TEXT NOT NULL,
|
|
1845
|
+
result_json TEXT,
|
|
1846
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1847
|
+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1848
|
+
FOREIGN KEY (execution_run_id, project_id) REFERENCES execution_runs(id, project_id) ON DELETE CASCADE,
|
|
1849
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
1850
|
+
FOREIGN KEY (worktree_bundle_id) REFERENCES worktree_bundles(id) ON DELETE CASCADE,
|
|
1851
|
+
CHECK (stage_kind IN ('automation_commit', 'automation_push', 'automation_pull_request')),
|
|
1852
|
+
CHECK (schema_version = 1),
|
|
1853
|
+
CHECK (length(CAST(intent_json AS BLOB)) BETWEEN 2 AND 16384),
|
|
1854
|
+
CHECK (result_json IS NULL OR length(CAST(result_json AS BLOB)) BETWEEN 2 AND 16384)
|
|
1855
|
+
)
|
|
1856
|
+
`);
|
|
1388
1857
|
db.exec(`
|
|
1389
1858
|
CREATE TABLE IF NOT EXISTS build_open_question_batches (
|
|
1390
1859
|
id TEXT PRIMARY KEY,
|
|
@@ -1447,47 +1916,11 @@ db.exec('CREATE INDEX IF NOT EXISTS idx_build_sequence_tickets_sequence_position
|
|
|
1447
1916
|
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_integration_connections_provider_project ON integration_connections(provider, project_id)');
|
|
1448
1917
|
db.exec('CREATE INDEX IF NOT EXISTS idx_tickets_external_key ON tickets(external_provider, external_key)');
|
|
1449
1918
|
db.exec('CREATE INDEX IF NOT EXISTS idx_bundle_automation_state_project_bundle ON bundle_automation_state(project_id, worktree_bundle_id)');
|
|
1919
|
+
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_bundle_automation_state_progression ON bundle_automation_state(automation_progression_run_id) WHERE automation_progression_run_id IS NOT NULL');
|
|
1920
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_automation_stage_details_bundle_stage ON automation_stage_details(project_id, worktree_bundle_id, stage_kind, created_at DESC)');
|
|
1450
1921
|
db.exec('CREATE INDEX IF NOT EXISTS idx_build_open_questions_ticket_status ON build_open_questions(ticket_id, status)');
|
|
1451
1922
|
db.exec('CREATE INDEX IF NOT EXISTS idx_build_open_questions_bundle_status ON build_open_questions(project_id, worktree_bundle_id, status)');
|
|
1452
1923
|
db.exec('CREATE INDEX IF NOT EXISTS idx_build_open_question_batches_bundle_status ON build_open_question_batches(project_id, worktree_bundle_id, status)');
|
|
1453
|
-
const recoverInterruptedBuildOpenQuestionBatches = () => {
|
|
1454
|
-
const interrupted = db.prepare(`
|
|
1455
|
-
SELECT id, project_id, worktree_bundle_id
|
|
1456
|
-
FROM build_open_question_batches
|
|
1457
|
-
WHERE status IN ('pending', 'running')
|
|
1458
|
-
`).all();
|
|
1459
|
-
if (interrupted.length === 0) {
|
|
1460
|
-
return;
|
|
1461
|
-
}
|
|
1462
|
-
const recover = db.transaction(() => {
|
|
1463
|
-
for (const batch of interrupted) {
|
|
1464
|
-
db.prepare(`
|
|
1465
|
-
UPDATE build_open_question_batches
|
|
1466
|
-
SET status = 'error', error_message = ?, completed_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP
|
|
1467
|
-
WHERE id = ? AND status IN ('pending', 'running')
|
|
1468
|
-
`).run('Server restarted before the Build open question follow-up completed', batch.id);
|
|
1469
|
-
db.prepare(`
|
|
1470
|
-
UPDATE build_open_questions
|
|
1471
|
-
SET status = 'open', answer_text = NULL, answered_at = NULL,
|
|
1472
|
-
dismissed_at = NULL, dismissed_by = NULL, dismissal_reason = NULL,
|
|
1473
|
-
resolution_batch_id = NULL, updated_at = CURRENT_TIMESTAMP
|
|
1474
|
-
WHERE resolution_batch_id = ? AND status IN ('answered', 'dismissed')
|
|
1475
|
-
`).run(batch.id);
|
|
1476
|
-
db.prepare(`
|
|
1477
|
-
INSERT INTO bundle_automation_state (
|
|
1478
|
-
project_id, worktree_bundle_id, automation_paused_code, automation_paused_reason, automation_paused_at
|
|
1479
|
-
) VALUES (?, ?, 'open_questions', ?, CURRENT_TIMESTAMP)
|
|
1480
|
-
ON CONFLICT(project_id, worktree_bundle_id) DO UPDATE SET
|
|
1481
|
-
automation_paused_code = 'open_questions',
|
|
1482
|
-
automation_paused_reason = excluded.automation_paused_reason,
|
|
1483
|
-
automation_paused_at = CURRENT_TIMESTAMP,
|
|
1484
|
-
updated_at = CURRENT_TIMESTAMP
|
|
1485
|
-
`).run(batch.project_id, batch.worktree_bundle_id, 'Build open question follow-up was interrupted by a server restart');
|
|
1486
|
-
}
|
|
1487
|
-
});
|
|
1488
|
-
recover();
|
|
1489
|
-
};
|
|
1490
|
-
recoverInterruptedBuildOpenQuestionBatches();
|
|
1491
1924
|
const migrateLegacyBuildOpenQuestions = () => {
|
|
1492
1925
|
const rows = db.prepare(`
|
|
1493
1926
|
SELECT id, project_id, worktree_bundle_id, planning_context_json
|