@straiffi/archon 1.8.23 → 1.10.0
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-BaIZ8eHC.js → ActivityView-Y5IaJiim.js} +1 -1
- package/dist/client/assets/GitHubActionsDialog-GWVxWGPK.js +1 -0
- package/dist/client/assets/VerificationDialog-C4RMuI4y.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-Dl5UF67P.js → architectureDiagram-3BPJPVTR-CeM6gbLN.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DCcERfrZ.js → blockDiagram-GPEHLZMM-BP4hta96.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BGhbASFm.js → c4Diagram-AAUBKEIU-5aJScvhn.js} +1 -1
- package/dist/client/assets/channel-B3DjZXbm.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-C1ARozTV.js → chunk-2J33WTMH-BKc2IelV.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-BEovLizF.js → chunk-3OPIFGDE-DCc15la5.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-C5MmlLa_.js → chunk-5ZQYHXKU-DSD9HbTp.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-8y8jBk4n.js → chunk-727SXJPM-DrAjnKiA.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-q-mByAd3.js → chunk-AQP2D5EJ-DxKnpHfQ.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-BOx2mLSz.js → chunk-CSCIHK7Q-DLejrAB_.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-zEwQFq7q.js → chunk-KSCS5N6A-BWRNmF8S.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-C80z6rY_.js → chunk-L5ZTLDWV-D48i966f.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-BLaEsGPd.js → chunk-LZXEDZCA-DLhg6Bok.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-x26BZ95L.js → chunk-ND2GUHAM-B4-7cOEq.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-D2WAxr1p.js → chunk-NZK2D7GU-D2ttXA_d.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-DDPCrzKh.js → chunk-O5CBEL6O-BrWrOVCq.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-CE-JcvIc.js → chunk-WU5MYG2G-CLcPwxPe.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DproSkn2.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-JVMMzJxJ.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-Bf7wpUk_.js → dagre-BM42HDAG-DIXN8_VX.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BQoKmc3B.js → diagram-2AECGRRQ-D2wjdCij.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-D2jarPLn.js → diagram-5GNKFQAL-E1Og_PHE.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-Bcbbjvsl.js → diagram-KO2AKTUF-B6P1Ud8a.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-t862RRBQ.js → diagram-LMA3HP47-C3Jxq56v.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-CacbMcO0.js → diagram-OG6HWLK6-Do9LVhdL.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DRQ79baI.js → erDiagram-TEJ5UH35-DLb5E4-f.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-BfW4KEdc.js → flowDiagram-I6XJVG4X-CcTs_wU9.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-BPIl0TAj.js → ganttDiagram-6RSMTGT7-q9ez5fri.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CRIusBMV.js → gitGraphDiagram-PVQCEYII-BcaKiz4c.js} +1 -1
- package/dist/client/assets/index-1CokwSFm.css +2 -0
- package/dist/client/assets/index-CSOKbu3w.js +276 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-DTKzK8EJ.js → infoDiagram-5YYISTIA-Cu0w4frE.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DVIHZLvL.js → ishikawaDiagram-YF4QCWOH-CJ47Z-ak.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CQBZ4tCx.js → journeyDiagram-JHISSGLW-fAL_Zcvs.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-D7naegR0.js → kanban-definition-UN3LZRKU-BTNIybMC.js} +1 -1
- package/dist/client/assets/{line-CizZlaeV.js → line-BvsadeZR.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-NrDqgpZa.js → mermaid-parser.core-C0EkH2y_.js} +1 -1
- package/dist/client/assets/{mermaid.core-CwVO3oX0.js → mermaid.core-BU5QIIbY.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BWxy3Aa_.js → mindmap-definition-RKZ34NQL-CWbSYK8f.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-B3gXpmBn.js → pieDiagram-4H26LBE5-t4w2cB-y.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Dpp4g8Al.js → quadrantDiagram-W4KKPZXB-Cqasvrpa.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-lFKXnxml.js → requirementDiagram-4Y6WPE33-_l-mY-tb.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BBdtwqrS.js → sankeyDiagram-5OEKKPKP-Cr9YrZ-Y.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-ANpVZzqm.js → sequenceDiagram-3UESZ5HK-DvzZhQpb.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-D58ZxmKY.js → stateDiagram-AJRCARHV-cFjPpAO3.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-btHMH5Cg.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-B6FK8IQC.js → timeline-definition-PNZ67QCA-BjRNrEJY.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-lFWtZEEY.js → vennDiagram-CIIHVFJN-xs9afjrw.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DteAVp4l.js → wardleyDiagram-YWT4CUSO-DH68ZYti.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-CNcDlRLN.js → xychartDiagram-2RQKCTM6-DLW5ktTU.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +225 -12
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +80 -26
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +368 -143
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/agentProvider.js.map +1 -1
- package/dist/server/lib/approvalReconciliation.js +14 -2
- package/dist/server/lib/approvalReconciliation.js.map +1 -1
- package/dist/server/lib/buildExecutionEnvironment.js +251 -57
- package/dist/server/lib/buildExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/chatOperations.js +125 -3
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/chatPostBuildRuns.js +12 -6
- package/dist/server/lib/chatPostBuildRuns.js.map +1 -1
- package/dist/server/lib/chatTargets.js +2 -1
- package/dist/server/lib/chatTargets.js.map +1 -1
- package/dist/server/lib/checkDefinitionCwd.js +34 -0
- package/dist/server/lib/checkDefinitionCwd.js.map +1 -0
- package/dist/server/lib/checkExecutionEnvironment.js +95 -0
- package/dist/server/lib/checkExecutionEnvironment.js.map +1 -0
- package/dist/server/lib/checkPolicyDefinitionIds.js +41 -0
- package/dist/server/lib/checkPolicyDefinitionIds.js.map +1 -0
- package/dist/server/lib/checkRepairDispatch.js +2 -0
- package/dist/server/lib/checkRepairDispatch.js.map +1 -1
- package/dist/server/lib/checkRunner.js +371 -175
- package/dist/server/lib/checkRunner.js.map +1 -1
- package/dist/server/lib/checkRuns.js +99 -8
- package/dist/server/lib/checkRuns.js.map +1 -1
- package/dist/server/lib/claudeAgentProvider.js +3 -6
- package/dist/server/lib/claudeAgentProvider.js.map +1 -1
- package/dist/server/lib/claudeStdin.js +27 -0
- package/dist/server/lib/claudeStdin.js.map +1 -0
- package/dist/server/lib/completedAssistantOutput.js +38 -0
- package/dist/server/lib/completedAssistantOutput.js.map +1 -0
- package/dist/server/lib/consequentialActionAuthority.js +99 -8
- package/dist/server/lib/consequentialActionAuthority.js.map +1 -1
- package/dist/server/lib/consequentialActions.js +42 -2
- package/dist/server/lib/consequentialActions.js.map +1 -1
- package/dist/server/lib/dockerSandboxCredentials.js +10 -3
- package/dist/server/lib/dockerSandboxCredentials.js.map +1 -1
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js +9 -8
- package/dist/server/lib/dockerSandboxEnvironmentOperations.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js +149 -74
- package/dist/server/lib/dockerSandboxExecutionEnvironment.js.map +1 -1
- package/dist/server/lib/dockerSandboxExecutionProvider.js +22 -14
- package/dist/server/lib/dockerSandboxExecutionProvider.js.map +1 -1
- package/dist/server/lib/dockerSandboxNetworkPolicy.js +23 -14
- package/dist/server/lib/dockerSandboxNetworkPolicy.js.map +1 -1
- package/dist/server/lib/dockerSandboxReleaseProfiles.js +91 -0
- package/dist/server/lib/dockerSandboxReleaseProfiles.js.map +1 -0
- package/dist/server/lib/dockerSandboxRuntimeController.js +16 -1
- package/dist/server/lib/dockerSandboxRuntimeController.js.map +1 -1
- package/dist/server/lib/executionCredentialCapabilities.js +9 -6
- package/dist/server/lib/executionCredentialCapabilities.js.map +1 -1
- package/dist/server/lib/executionEnvironment.js.map +1 -1
- package/dist/server/lib/executionEnvironmentLifecycle.js +7 -0
- package/dist/server/lib/executionEnvironmentLifecycle.js.map +1 -1
- package/dist/server/lib/executionEnvironmentOperations.js +241 -0
- package/dist/server/lib/executionEnvironmentOperations.js.map +1 -0
- package/dist/server/lib/executionEnvironmentReconciliation.js +98 -3
- package/dist/server/lib/executionEnvironmentReconciliation.js.map +1 -1
- package/dist/server/lib/executionEnvironmentRoutes.js +66 -27
- package/dist/server/lib/executionEnvironmentRoutes.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidation.js +2 -2
- package/dist/server/lib/executionEnvironmentValidation.js.map +1 -1
- package/dist/server/lib/executionEnvironmentValidationOperations.js +58 -31
- package/dist/server/lib/executionEnvironmentValidationOperations.js.map +1 -1
- package/dist/server/lib/executionEnvironments.js +187 -9
- package/dist/server/lib/executionEnvironments.js.map +1 -1
- package/dist/server/lib/executionProfileCheckPolicy.js +14 -0
- package/dist/server/lib/executionProfileCheckPolicy.js.map +1 -0
- package/dist/server/lib/executionProfileRoutes.js +9 -1
- package/dist/server/lib/executionProfileRoutes.js.map +1 -1
- package/dist/server/lib/executionProfileStore.js +5 -3
- package/dist/server/lib/executionProfileStore.js.map +1 -1
- package/dist/server/lib/executionProfiles.js +97 -15
- package/dist/server/lib/executionProfiles.js.map +1 -1
- package/dist/server/lib/executionReconciliation.js +43 -6
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRunAuthority.js +115 -24
- package/dist/server/lib/executionRunAuthority.js.map +1 -1
- package/dist/server/lib/executionTargets.js +30 -4
- package/dist/server/lib/executionTargets.js.map +1 -1
- package/dist/server/lib/executionWorkloads.js +75 -0
- package/dist/server/lib/executionWorkloads.js.map +1 -0
- package/dist/server/lib/git.js +10 -1
- package/dist/server/lib/git.js.map +1 -1
- package/dist/server/lib/opencodeAgentProvider.js +3 -1
- package/dist/server/lib/opencodeAgentProvider.js.map +1 -1
- package/dist/server/lib/opencodeSessionOperations.js +5 -3
- package/dist/server/lib/opencodeSessionOperations.js.map +1 -1
- package/dist/server/lib/planQuestions.js +2 -1
- package/dist/server/lib/planQuestions.js.map +1 -1
- package/dist/server/lib/postBuildCheckRuns.js +9 -5
- package/dist/server/lib/postBuildCheckRuns.js.map +1 -1
- package/dist/server/lib/preview.js +47 -6
- package/dist/server/lib/preview.js.map +1 -1
- package/dist/server/lib/previewProxy.js +11 -3
- package/dist/server/lib/previewProxy.js.map +1 -1
- package/dist/server/lib/productionCheckApprovals.js +97 -35
- package/dist/server/lib/productionCheckApprovals.js.map +1 -1
- package/dist/server/lib/projectMemorySuggestions.js +29 -6
- package/dist/server/lib/projectMemorySuggestions.js.map +1 -1
- package/dist/server/lib/requiredCheckPolicy.js +3 -40
- package/dist/server/lib/requiredCheckPolicy.js.map +1 -1
- package/dist/server/lib/reviewAgentWatchdog.js +75 -0
- package/dist/server/lib/reviewAgentWatchdog.js.map +1 -0
- package/dist/server/lib/reviewFindingReconciliation.js +176 -0
- package/dist/server/lib/reviewFindingReconciliation.js.map +1 -0
- package/dist/server/lib/reviewFindings.js +33 -11
- package/dist/server/lib/reviewFindings.js.map +1 -1
- package/dist/server/lib/run.js +370 -80
- package/dist/server/lib/run.js.map +1 -1
- package/dist/server/lib/serviceRuns.js +196 -0
- package/dist/server/lib/serviceRuns.js.map +1 -0
- package/dist/server/lib/sessionTargets.js +34 -0
- package/dist/server/lib/sessionTargets.js.map +1 -1
- package/dist/server/lib/shell.js +20 -0
- package/dist/server/lib/shell.js.map +1 -1
- package/dist/server/lib/specArtifact.js +36 -15
- package/dist/server/lib/specArtifact.js.map +1 -1
- package/dist/server/lib/specBundleGroups.js +4 -4
- package/dist/server/lib/specBundleGroups.js.map +1 -1
- package/dist/server/lib/specOperations.js +2 -0
- package/dist/server/lib/specOperations.js.map +1 -1
- package/dist/server/lib/specReviewOperations.js +2 -0
- package/dist/server/lib/specReviewOperations.js.map +1 -1
- package/dist/server/lib/specTicketMaterialization.js +37 -24
- package/dist/server/lib/specTicketMaterialization.js.map +1 -1
- package/dist/server/lib/ticketFollowUpOperations.js +9 -4
- package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
- package/dist/server/lib/ticketRunOperations.js +1 -0
- package/dist/server/lib/ticketRunOperations.js.map +1 -1
- package/dist/server/lib/types.js +1 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/lib/workloadExecutionEnvironment.js +2 -0
- package/dist/server/lib/workloadExecutionEnvironment.js.map +1 -0
- package/dist/server/lib/workspaceIdentity.js +30 -6
- package/dist/server/lib/workspaceIdentity.js.map +1 -1
- package/dist/server/workers/build.js +39 -8
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +142 -15
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +77 -20
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/plan.js +295 -48
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/planFollowUp.js +77 -7
- package/dist/server/workers/planFollowUp.js.map +1 -1
- package/dist/server/workers/review.js +149 -38
- package/dist/server/workers/review.js.map +1 -1
- package/dist/server/workers/specReview.js +43 -5
- package/dist/server/workers/specReview.js.map +1 -1
- package/dist/server/workers/specSession.js +156 -31
- package/dist/server/workers/specSession.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/GitHubActionsDialog-BFCqikDY.js +0 -1
- package/dist/client/assets/VerificationDialog-B1_6HMdt.js +0 -4
- package/dist/client/assets/channel-BfskvH2B.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-D4HPfxL3.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DQQ_WqAU.js +0 -1
- package/dist/client/assets/index-CZ1z72fo.js +0 -276
- package/dist/client/assets/index-SMj5ZmMs.css +0 -2
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Cv8cmDfz.js +0 -1
package/dist/server/db.js
CHANGED
|
@@ -4,6 +4,7 @@ import { parseCheckDefinitionsJsonStrict, parseLegacyTestCommandsJsonStrict, pro
|
|
|
4
4
|
import { ensureParentDirectory, resolveArchonDbPath } from './lib/runtimePaths.js';
|
|
5
5
|
import { TRANSCRIPT_RUN_TEXT_LIMIT_BYTES, truncateUtf8 } from './lib/transcriptRuns.js';
|
|
6
6
|
import { createExecutionProfile, EXECUTION_PROFILE_SCHEMA_VERSION, fingerprintExecutionProfile, normalizeExecutionProfile, serializeExecutionProfile, } from './lib/executionProfiles.js';
|
|
7
|
+
import { hasConfiguredCheckPolicy } from './lib/executionProfileCheckPolicy.js';
|
|
7
8
|
const dbPath = ensureParentDirectory(resolveArchonDbPath());
|
|
8
9
|
const db = new Database(dbPath);
|
|
9
10
|
db.pragma('foreign_keys = ON');
|
|
@@ -181,7 +182,7 @@ db.exec(`
|
|
|
181
182
|
id TEXT PRIMARY KEY,
|
|
182
183
|
project_id TEXT NOT NULL,
|
|
183
184
|
revision INTEGER NOT NULL CHECK (revision > 0),
|
|
184
|
-
schema_version INTEGER NOT NULL CHECK (schema_version IN (1, 2)),
|
|
185
|
+
schema_version INTEGER NOT NULL CHECK (schema_version IN (1, 2, 3)),
|
|
185
186
|
fingerprint TEXT NOT NULL CHECK (length(fingerprint) = 64),
|
|
186
187
|
profile_json TEXT NOT NULL CHECK (
|
|
187
188
|
json_valid(profile_json)
|
|
@@ -221,7 +222,7 @@ db.exec(`
|
|
|
221
222
|
ON execution_profile_audit_events(project_id, created_at DESC, id DESC);
|
|
222
223
|
`);
|
|
223
224
|
const executionProfileRevisionsTableSql = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'execution_profile_revisions'").get()?.sql ?? '';
|
|
224
|
-
if (!executionProfileRevisionsTableSql.includes('schema_version IN (1, 2)')) {
|
|
225
|
+
if (!executionProfileRevisionsTableSql.includes('schema_version IN (1, 2, 3)')) {
|
|
225
226
|
db.pragma('foreign_keys = OFF');
|
|
226
227
|
db.transaction(() => {
|
|
227
228
|
const referencingTriggers = db.prepare(`
|
|
@@ -236,7 +237,7 @@ if (!executionProfileRevisionsTableSql.includes('schema_version IN (1, 2)')) {
|
|
|
236
237
|
id TEXT PRIMARY KEY,
|
|
237
238
|
project_id TEXT NOT NULL,
|
|
238
239
|
revision INTEGER NOT NULL CHECK (revision > 0),
|
|
239
|
-
schema_version INTEGER NOT NULL CHECK (schema_version IN (1, 2)),
|
|
240
|
+
schema_version INTEGER NOT NULL CHECK (schema_version IN (1, 2, 3)),
|
|
240
241
|
fingerprint TEXT NOT NULL CHECK (length(fingerprint) = 64),
|
|
241
242
|
profile_json TEXT NOT NULL CHECK (
|
|
242
243
|
json_valid(profile_json)
|
|
@@ -297,7 +298,7 @@ const backfillExecutionProfiles = () => {
|
|
|
297
298
|
}
|
|
298
299
|
})();
|
|
299
300
|
};
|
|
300
|
-
const
|
|
301
|
+
const backfillExecutionProfilesToCurrentSchema = () => {
|
|
301
302
|
const legacyRows = db.prepare(`
|
|
302
303
|
SELECT projects.id AS project_id,
|
|
303
304
|
revisions.id AS revision_id,
|
|
@@ -306,7 +307,7 @@ const backfillExecutionProfilesToSchemaV2 = () => {
|
|
|
306
307
|
INNER JOIN execution_profile_revisions revisions
|
|
307
308
|
ON revisions.id = projects.active_execution_profile_revision_id
|
|
308
309
|
AND revisions.project_id = projects.id
|
|
309
|
-
WHERE revisions.schema_version
|
|
310
|
+
WHERE revisions.schema_version IN (1, 2) AND projects.deletion_started_at IS NULL
|
|
310
311
|
`).all();
|
|
311
312
|
const nextRevisionNumber = db.prepare(`
|
|
312
313
|
SELECT COALESCE(MAX(revision), 0) + 1 AS revision
|
|
@@ -348,19 +349,118 @@ const backfillExecutionProfilesToSchemaV2 = () => {
|
|
|
348
349
|
revisionId = existing.id;
|
|
349
350
|
}
|
|
350
351
|
else {
|
|
351
|
-
revisionId = `${row.project_id}:execution-profile:
|
|
352
|
+
revisionId = `${row.project_id}:execution-profile:v${EXECUTION_PROFILE_SCHEMA_VERSION}`;
|
|
352
353
|
const revisionNumber = nextRevisionNumber.get(row.project_id).revision;
|
|
353
354
|
insertRevision.run(revisionId, row.project_id, revisionNumber, fingerprint, serializeExecutionProfile(normalized.profile));
|
|
354
355
|
}
|
|
355
356
|
const activated = activateRevision.run(revisionId, row.project_id, row.revision_id);
|
|
356
357
|
if (activated.changes > 0) {
|
|
357
|
-
insertEvent.run(`${revisionId}:
|
|
358
|
+
insertEvent.run(`${revisionId}:schema-backfill`, row.project_id, revisionId, row.revision_id);
|
|
358
359
|
}
|
|
359
360
|
}
|
|
360
361
|
})();
|
|
361
362
|
};
|
|
363
|
+
const backfillExecutionProfileWorkloadEligibility = () => {
|
|
364
|
+
const listActiveRows = db.prepare(`
|
|
365
|
+
SELECT projects.id AS project_id,
|
|
366
|
+
revisions.id AS revision_id,
|
|
367
|
+
revisions.profile_json,
|
|
368
|
+
projects.required_check_definition_ids,
|
|
369
|
+
projects.pre_review_check_definition_ids,
|
|
370
|
+
projects.post_build_check_definition_ids,
|
|
371
|
+
projects.auto_fix_check_definition_ids
|
|
372
|
+
FROM projects
|
|
373
|
+
INNER JOIN execution_profile_revisions revisions
|
|
374
|
+
ON revisions.id = projects.active_execution_profile_revision_id
|
|
375
|
+
AND revisions.project_id = projects.id
|
|
376
|
+
WHERE revisions.schema_version = ${EXECUTION_PROFILE_SCHEMA_VERSION}
|
|
377
|
+
AND projects.deletion_started_at IS NULL
|
|
378
|
+
`);
|
|
379
|
+
const nextRevisionNumber = db.prepare(`
|
|
380
|
+
SELECT COALESCE(MAX(revision), 0) + 1 AS revision
|
|
381
|
+
FROM execution_profile_revisions WHERE project_id = ?
|
|
382
|
+
`);
|
|
383
|
+
const findRevisionByFingerprint = db.prepare(`
|
|
384
|
+
SELECT id FROM execution_profile_revisions WHERE project_id = ? AND fingerprint = ?
|
|
385
|
+
`);
|
|
386
|
+
const insertRevision = db.prepare(`
|
|
387
|
+
INSERT OR IGNORE INTO execution_profile_revisions (
|
|
388
|
+
id, project_id, revision, schema_version, fingerprint, profile_json
|
|
389
|
+
) VALUES (?, ?, ?, ${EXECUTION_PROFILE_SCHEMA_VERSION}, ?, ?)
|
|
390
|
+
`);
|
|
391
|
+
const activateRevision = db.prepare(`
|
|
392
|
+
UPDATE projects SET active_execution_profile_revision_id = ?
|
|
393
|
+
WHERE id = ? AND active_execution_profile_revision_id = ?
|
|
394
|
+
`);
|
|
395
|
+
const insertEvent = db.prepare(`
|
|
396
|
+
INSERT OR IGNORE INTO execution_profile_audit_events (
|
|
397
|
+
id, project_id, event_type, profile_revision_id, previous_profile_revision_id
|
|
398
|
+
) VALUES (?, ?, ?, ?, ?)
|
|
399
|
+
`);
|
|
400
|
+
db.transaction(() => {
|
|
401
|
+
const activeRows = listActiveRows.all();
|
|
402
|
+
for (const row of activeRows) {
|
|
403
|
+
let normalized;
|
|
404
|
+
try {
|
|
405
|
+
normalized = normalizeExecutionProfile(JSON.parse(row.profile_json));
|
|
406
|
+
}
|
|
407
|
+
catch {
|
|
408
|
+
normalized = null;
|
|
409
|
+
}
|
|
410
|
+
if (!normalized?.ok) {
|
|
411
|
+
throw new Error(`Stored execution profile revision ${row.revision_id} is invalid`);
|
|
412
|
+
}
|
|
413
|
+
const buildEligible = normalized.profile.eligible_workloads.includes('build');
|
|
414
|
+
const needsChatBuild = buildEligible && !normalized.profile.eligible_workloads.includes('chat_build');
|
|
415
|
+
const needsCheckTemplate = buildEligible
|
|
416
|
+
&& hasConfiguredCheckPolicy(row)
|
|
417
|
+
&& normalized.profile.check_template_policy.mode !== 'agent_template';
|
|
418
|
+
if (!needsChatBuild && !needsCheckTemplate) {
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
const repaired = normalizeExecutionProfile({
|
|
422
|
+
...normalized.profile,
|
|
423
|
+
eligible_workloads: [
|
|
424
|
+
...normalized.profile.eligible_workloads,
|
|
425
|
+
...(needsChatBuild ? ['chat_build'] : []),
|
|
426
|
+
...(needsCheckTemplate ? ['check'] : []),
|
|
427
|
+
],
|
|
428
|
+
check_template_policy: needsCheckTemplate
|
|
429
|
+
? { mode: 'agent_template', agent: 'opencode' }
|
|
430
|
+
: normalized.profile.check_template_policy,
|
|
431
|
+
});
|
|
432
|
+
if (!repaired.ok) {
|
|
433
|
+
throw new Error(`Stored execution profile revision ${row.revision_id} is invalid`);
|
|
434
|
+
}
|
|
435
|
+
const fingerprint = fingerprintExecutionProfile(repaired.profile);
|
|
436
|
+
let target = findRevisionByFingerprint.get(row.project_id, fingerprint);
|
|
437
|
+
const repairKey = needsChatBuild && needsCheckTemplate
|
|
438
|
+
? 'chat-build-check'
|
|
439
|
+
: needsChatBuild
|
|
440
|
+
? 'chat-build'
|
|
441
|
+
: 'configured-check';
|
|
442
|
+
if (!target) {
|
|
443
|
+
const revisionId = `${row.project_id}:execution-profile:${repairKey}-v${EXECUTION_PROFILE_SCHEMA_VERSION}`;
|
|
444
|
+
const revisionNumber = nextRevisionNumber.get(row.project_id).revision;
|
|
445
|
+
const inserted = insertRevision.run(revisionId, row.project_id, revisionNumber, fingerprint, serializeExecutionProfile(repaired.profile));
|
|
446
|
+
target = findRevisionByFingerprint.get(row.project_id, fingerprint);
|
|
447
|
+
if (!target) {
|
|
448
|
+
throw new Error(`Failed to migrate stored execution profile revision ${row.revision_id}`);
|
|
449
|
+
}
|
|
450
|
+
if (inserted.changes > 0) {
|
|
451
|
+
insertEvent.run(`${target.id}:${repairKey}-backfill-created`, row.project_id, 'revision_created', target.id, row.revision_id);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
const activated = activateRevision.run(target.id, row.project_id, row.revision_id);
|
|
455
|
+
if (activated.changes > 0) {
|
|
456
|
+
insertEvent.run(`${target.id}:${repairKey}-backfill-activated`, row.project_id, 'revision_activated', target.id, row.revision_id);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}).immediate();
|
|
460
|
+
};
|
|
362
461
|
backfillExecutionProfiles();
|
|
363
|
-
|
|
462
|
+
backfillExecutionProfilesToCurrentSchema();
|
|
463
|
+
backfillExecutionProfileWorkloadEligibility();
|
|
364
464
|
const hostCompatibilityProfile = createExecutionProfile('host');
|
|
365
465
|
const hostCompatibilityProfileJson = serializeExecutionProfile(hostCompatibilityProfile).replaceAll("'", "''");
|
|
366
466
|
const hostCompatibilityFingerprint = fingerprintExecutionProfile(hostCompatibilityProfile);
|
|
@@ -2501,6 +2601,49 @@ const migrateExecutionLifecycleSchema = () => {
|
|
|
2501
2601
|
}
|
|
2502
2602
|
};
|
|
2503
2603
|
migrateExecutionLifecycleSchema();
|
|
2604
|
+
db.exec(`
|
|
2605
|
+
CREATE TABLE IF NOT EXISTS service_run_details (
|
|
2606
|
+
execution_run_id TEXT PRIMARY KEY,
|
|
2607
|
+
project_id TEXT NOT NULL,
|
|
2608
|
+
context_key TEXT NOT NULL,
|
|
2609
|
+
target_kind TEXT NOT NULL,
|
|
2610
|
+
target_key TEXT NOT NULL,
|
|
2611
|
+
target_workspace_path TEXT NOT NULL,
|
|
2612
|
+
execution_profile_revision_id TEXT NOT NULL,
|
|
2613
|
+
execution_profile_fingerprint TEXT NOT NULL,
|
|
2614
|
+
provider_kind TEXT,
|
|
2615
|
+
environment_id TEXT,
|
|
2616
|
+
environment_revision INTEGER,
|
|
2617
|
+
service_snapshot_json TEXT NOT NULL,
|
|
2618
|
+
placement_json TEXT,
|
|
2619
|
+
interruption_scope TEXT,
|
|
2620
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2621
|
+
started_at DATETIME,
|
|
2622
|
+
completed_at DATETIME,
|
|
2623
|
+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2624
|
+
FOREIGN KEY (execution_run_id, project_id) REFERENCES execution_runs(id, project_id) ON DELETE CASCADE,
|
|
2625
|
+
FOREIGN KEY (project_id, execution_profile_revision_id)
|
|
2626
|
+
REFERENCES execution_profile_revisions(project_id, id) ON DELETE RESTRICT,
|
|
2627
|
+
CHECK (length(CAST(context_key AS BLOB)) BETWEEN 1 AND 1000),
|
|
2628
|
+
CHECK (length(CAST(target_kind AS BLOB)) BETWEEN 1 AND 100),
|
|
2629
|
+
CHECK (length(CAST(target_key AS BLOB)) BETWEEN 1 AND 1000),
|
|
2630
|
+
CHECK (length(CAST(target_workspace_path AS BLOB)) BETWEEN 1 AND 4096),
|
|
2631
|
+
CHECK (length(execution_profile_fingerprint) = 64 AND execution_profile_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
2632
|
+
CHECK (provider_kind IS NULL OR provider_kind IN ('host', 'docker_sandbox')),
|
|
2633
|
+
CHECK ((environment_id IS NULL) = (environment_revision IS NULL)),
|
|
2634
|
+
CHECK (environment_revision IS NULL OR environment_revision >= 1),
|
|
2635
|
+
CHECK (length(CAST(service_snapshot_json AS BLOB)) BETWEEN 2 AND 16384),
|
|
2636
|
+
CHECK (placement_json IS NULL OR length(CAST(placement_json AS BLOB)) BETWEEN 2 AND 16384),
|
|
2637
|
+
CHECK (interruption_scope IS NULL OR interruption_scope IN ('local_processes', 'whole_environment'))
|
|
2638
|
+
);
|
|
2639
|
+
|
|
2640
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_active_service_run_context
|
|
2641
|
+
ON service_run_details(project_id, context_key)
|
|
2642
|
+
WHERE completed_at IS NULL;
|
|
2643
|
+
|
|
2644
|
+
CREATE INDEX IF NOT EXISTS idx_service_run_profile
|
|
2645
|
+
ON service_run_details(project_id, execution_profile_revision_id, created_at);
|
|
2646
|
+
`);
|
|
2504
2647
|
const executionEnvironmentStates = "'queued', 'preparing', 'ready', 'running', 'stopped', 'retiring', 'cleanup_pending', 'retired', 'failed', 'unavailable'";
|
|
2505
2648
|
db.exec(`
|
|
2506
2649
|
CREATE TABLE IF NOT EXISTS execution_environments (
|
|
@@ -2530,6 +2673,11 @@ db.exec(`
|
|
|
2530
2673
|
cleanup_claim_id TEXT,
|
|
2531
2674
|
cleanup_claimed_at DATETIME,
|
|
2532
2675
|
cleanup_attempts INTEGER NOT NULL DEFAULT 0,
|
|
2676
|
+
cleanup_retry_at DATETIME,
|
|
2677
|
+
idle_stop_at DATETIME,
|
|
2678
|
+
operation_claim_id TEXT,
|
|
2679
|
+
operation_kind TEXT,
|
|
2680
|
+
operation_claimed_at DATETIME,
|
|
2533
2681
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2534
2682
|
preparation_started_at DATETIME,
|
|
2535
2683
|
ready_at DATETIME,
|
|
@@ -2571,7 +2719,10 @@ db.exec(`
|
|
|
2571
2719
|
CHECK (failure_message IS NULL OR length(failure_message) <= 4000),
|
|
2572
2720
|
CHECK (failure_details_json IS NULL OR length(CAST(failure_details_json AS BLOB)) <= 16384),
|
|
2573
2721
|
CHECK ((cleanup_claim_id IS NULL) = (cleanup_claimed_at IS NULL)),
|
|
2574
|
-
CHECK (cleanup_attempts >= 0)
|
|
2722
|
+
CHECK (cleanup_attempts >= 0),
|
|
2723
|
+
CHECK ((operation_claim_id IS NULL) = (operation_kind IS NULL)),
|
|
2724
|
+
CHECK ((operation_claim_id IS NULL) = (operation_claimed_at IS NULL)),
|
|
2725
|
+
CHECK (operation_kind IS NULL OR operation_kind IN ('stop', 'retire', 'reset', 'cleanup_retry'))
|
|
2575
2726
|
);
|
|
2576
2727
|
|
|
2577
2728
|
CREATE TABLE IF NOT EXISTS execution_environment_events (
|
|
@@ -2695,6 +2846,11 @@ ensureColumn('execution_environments', 'execution_profile_revision_id', 'TEXT');
|
|
|
2695
2846
|
ensureColumn('execution_environments', 'execution_profile_fingerprint', 'TEXT');
|
|
2696
2847
|
ensureColumn('execution_environments', 'credential_requirements_fingerprint', 'TEXT');
|
|
2697
2848
|
ensureColumn('execution_environments', 'retirement_requested_at', 'DATETIME');
|
|
2849
|
+
ensureColumn('execution_environments', 'cleanup_retry_at', 'DATETIME');
|
|
2850
|
+
ensureColumn('execution_environments', 'idle_stop_at', 'DATETIME');
|
|
2851
|
+
ensureColumn('execution_environments', 'operation_claim_id', 'TEXT');
|
|
2852
|
+
ensureColumn('execution_environments', 'operation_kind', 'TEXT');
|
|
2853
|
+
ensureColumn('execution_environments', 'operation_claimed_at', 'DATETIME');
|
|
2698
2854
|
ensureColumn('execution_environment_run_bindings', 'execution_profile_fingerprint', 'TEXT');
|
|
2699
2855
|
ensureColumn('execution_environment_run_bindings', 'authority_json', 'TEXT');
|
|
2700
2856
|
ensureColumn('execution_environment_run_bindings', 'placement_json', 'TEXT');
|
|
@@ -3090,9 +3246,41 @@ db.exec('DROP INDEX IF EXISTS idx_execution_environments_reuse');
|
|
|
3090
3246
|
db.exec('CREATE INDEX idx_execution_environments_reuse ON execution_environments(project_id, provider_kind, target_key, target_workspace_path, environment_revision, workspace_mode, environment_validation_fingerprint, execution_profile_fingerprint, credential_requirements_fingerprint, retirement_requested_at, lifecycle_state)');
|
|
3091
3247
|
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_execution_environments_external_id ON execution_environments(provider_kind, external_id) WHERE external_id IS NOT NULL');
|
|
3092
3248
|
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_environments_cleanup ON execution_environments(lifecycle_state, cleanup_claim_id, updated_at, cleanup_attempts)');
|
|
3249
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_environments_cleanup_retry ON execution_environments(lifecycle_state, cleanup_retry_at, cleanup_claim_id)');
|
|
3250
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_environments_idle_stop ON execution_environments(idle_stop_at, lifecycle_state) WHERE idle_stop_at IS NOT NULL');
|
|
3251
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_environments_operation_claim ON execution_environments(operation_claim_id, operation_claimed_at) WHERE operation_claim_id IS NOT NULL');
|
|
3093
3252
|
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_environment_events_sequence ON execution_environment_events(project_id, environment_id, sequence)');
|
|
3094
3253
|
db.exec('CREATE INDEX IF NOT EXISTS idx_execution_environment_bindings_run ON execution_environment_run_bindings(project_id, execution_run_id, bound_at)');
|
|
3095
3254
|
db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_execution_environment_active_execution_lease ON execution_environment_run_bindings(environment_id) WHERE relationship = 'execution' AND released_at IS NULL");
|
|
3255
|
+
db.exec(`
|
|
3256
|
+
CREATE TRIGGER IF NOT EXISTS validate_execution_environment_operation_claim
|
|
3257
|
+
BEFORE UPDATE OF operation_claim_id, operation_kind, operation_claimed_at ON execution_environments
|
|
3258
|
+
WHEN NOT (
|
|
3259
|
+
(NEW.operation_claim_id IS NULL AND NEW.operation_kind IS NULL AND NEW.operation_claimed_at IS NULL)
|
|
3260
|
+
OR (
|
|
3261
|
+
length(NEW.operation_claim_id) BETWEEN 1 AND 128
|
|
3262
|
+
AND NEW.operation_kind IN ('stop', 'retire', 'reset', 'cleanup_retry')
|
|
3263
|
+
AND NEW.operation_claimed_at IS NOT NULL
|
|
3264
|
+
)
|
|
3265
|
+
)
|
|
3266
|
+
BEGIN
|
|
3267
|
+
SELECT RAISE(ABORT, 'Invalid execution environment operation claim');
|
|
3268
|
+
END;
|
|
3269
|
+
|
|
3270
|
+
CREATE TRIGGER IF NOT EXISTS validate_execution_environment_lease_admission
|
|
3271
|
+
BEFORE INSERT ON execution_environment_run_bindings
|
|
3272
|
+
WHEN NEW.relationship = 'execution' AND NOT EXISTS (
|
|
3273
|
+
SELECT 1 FROM execution_environments
|
|
3274
|
+
WHERE id = NEW.environment_id
|
|
3275
|
+
AND project_id = NEW.project_id
|
|
3276
|
+
AND lifecycle_state IN ('ready', 'running', 'stopped')
|
|
3277
|
+
AND retirement_requested_at IS NULL
|
|
3278
|
+
AND operation_claim_id IS NULL
|
|
3279
|
+
)
|
|
3280
|
+
BEGIN
|
|
3281
|
+
SELECT RAISE(ABORT, 'Execution environment is not admitting leases');
|
|
3282
|
+
END;
|
|
3283
|
+
`);
|
|
3096
3284
|
db.exec(`
|
|
3097
3285
|
CREATE TRIGGER IF NOT EXISTS validate_repository_graph_execution_run_binding
|
|
3098
3286
|
BEFORE UPDATE OF execution_run_id ON repository_graph_scans
|
|
@@ -3364,6 +3552,8 @@ db.exec(`
|
|
|
3364
3552
|
automation_boundary_purpose TEXT,
|
|
3365
3553
|
purpose TEXT NOT NULL DEFAULT 'manual',
|
|
3366
3554
|
causal_source_run_id TEXT,
|
|
3555
|
+
runtime_compatibility_json TEXT,
|
|
3556
|
+
batch_environment_json TEXT,
|
|
3367
3557
|
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE,
|
|
3368
3558
|
FOREIGN KEY (rerun_of_batch_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
3369
3559
|
FOREIGN KEY (causal_source_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
@@ -3413,6 +3603,7 @@ db.exec(`
|
|
|
3413
3603
|
total_persisted_bytes INTEGER NOT NULL DEFAULT 0,
|
|
3414
3604
|
retained_output TEXT NOT NULL DEFAULT '',
|
|
3415
3605
|
output_retention_state TEXT NOT NULL DEFAULT 'retained',
|
|
3606
|
+
placement_json TEXT,
|
|
3416
3607
|
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE,
|
|
3417
3608
|
FOREIGN KEY (batch_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
3418
3609
|
FOREIGN KEY (rerun_of_attempt_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
@@ -3420,7 +3611,7 @@ db.exec(`
|
|
|
3420
3611
|
CHECK (length(definition_fingerprint) = 64 AND definition_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
3421
3612
|
CHECK (outcome IS NULL OR outcome IN ('passed', 'command_failure', 'spawn_failure',
|
|
3422
3613
|
'infrastructure_failure', 'evidence_persistence_failure', 'timeout',
|
|
3423
|
-
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss', 'ambiguous_process_loss')),
|
|
3614
|
+
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss', 'ambiguous_process_loss', 'environment_loss')),
|
|
3424
3615
|
CHECK (output_revision >= 0 AND retained_start_offset >= 0 AND retained_end_offset >= retained_start_offset
|
|
3425
3616
|
AND total_persisted_bytes >= retained_end_offset),
|
|
3426
3617
|
CHECK (output_retention_state IN ('retained', 'expired'))
|
|
@@ -3428,11 +3619,15 @@ db.exec(`
|
|
|
3428
3619
|
`);
|
|
3429
3620
|
ensureColumn('check_attempt_details', 'retained_end_offset', 'INTEGER NOT NULL DEFAULT 0');
|
|
3430
3621
|
ensureColumn('check_attempt_details', 'retained_output', "TEXT NOT NULL DEFAULT ''");
|
|
3622
|
+
ensureColumn('check_attempt_details', 'placement_json', 'TEXT');
|
|
3623
|
+
ensureColumn('check_batch_details', 'runtime_compatibility_json', 'TEXT');
|
|
3624
|
+
ensureColumn('check_batch_details', 'batch_environment_json', 'TEXT');
|
|
3431
3625
|
const checkAttemptSchema = db.prepare(`
|
|
3432
3626
|
SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'check_attempt_details'
|
|
3433
3627
|
`).get();
|
|
3434
3628
|
if (checkAttemptSchema && (!checkAttemptSchema.sql.includes('evidence_persistence_failure')
|
|
3435
|
-
|| !checkAttemptSchema.sql.includes('ambiguous_process_loss')
|
|
3629
|
+
|| !checkAttemptSchema.sql.includes('ambiguous_process_loss')
|
|
3630
|
+
|| !checkAttemptSchema.sql.includes('environment_loss'))) {
|
|
3436
3631
|
const foreignKeysEnabled = db.pragma('foreign_keys', { simple: true }) === 1;
|
|
3437
3632
|
if (foreignKeysEnabled) {
|
|
3438
3633
|
db.pragma('foreign_keys = OFF');
|
|
@@ -3473,7 +3668,7 @@ if (checkAttemptSchema && (!checkAttemptSchema.sql.includes('evidence_persistenc
|
|
|
3473
3668
|
CHECK (length(definition_fingerprint) = 64 AND definition_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
3474
3669
|
CHECK (outcome IS NULL OR outcome IN ('passed', 'command_failure', 'spawn_failure',
|
|
3475
3670
|
'infrastructure_failure', 'evidence_persistence_failure', 'timeout',
|
|
3476
|
-
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss', 'ambiguous_process_loss')),
|
|
3671
|
+
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss', 'ambiguous_process_loss', 'environment_loss')),
|
|
3477
3672
|
CHECK (output_revision >= 0 AND retained_start_offset >= 0 AND retained_end_offset >= retained_start_offset
|
|
3478
3673
|
AND total_persisted_bytes >= retained_end_offset),
|
|
3479
3674
|
CHECK (output_retention_state IN ('retained', 'expired'))
|
|
@@ -3507,6 +3702,7 @@ if (checkAttemptSchema && (!checkAttemptSchema.sql.includes('evidence_persistenc
|
|
|
3507
3702
|
throw new Error(`Check attempt migration left an invalid foreign key: ${JSON.stringify(foreignKeyViolation)}`);
|
|
3508
3703
|
}
|
|
3509
3704
|
}
|
|
3705
|
+
ensureColumn('check_attempt_details', 'placement_json', 'TEXT');
|
|
3510
3706
|
db.exec(`
|
|
3511
3707
|
CREATE TABLE IF NOT EXISTS check_attempt_diagnostic_parsers (
|
|
3512
3708
|
attempt_run_id TEXT PRIMARY KEY,
|
|
@@ -4420,6 +4616,8 @@ db.prepare(`
|
|
|
4420
4616
|
db.exec('DROP TRIGGER IF EXISTS validate_check_batch_details_insert');
|
|
4421
4617
|
db.exec('DROP TRIGGER IF EXISTS preserve_check_batch_snapshots');
|
|
4422
4618
|
db.exec('DROP TRIGGER IF EXISTS preserve_completed_check_batch_details');
|
|
4619
|
+
db.exec('DROP TRIGGER IF EXISTS preserve_check_batch_environment_binding');
|
|
4620
|
+
db.exec('DROP TRIGGER IF EXISTS preserve_check_attempt_placement');
|
|
4423
4621
|
db.exec(`
|
|
4424
4622
|
CREATE TRIGGER IF NOT EXISTS preserve_check_batch_snapshots
|
|
4425
4623
|
BEFORE UPDATE OF execution_run_id, target_kind, target_bundle_id, target_label,
|
|
@@ -4436,6 +4634,14 @@ db.exec(`
|
|
|
4436
4634
|
SELECT RAISE(ABORT, 'Completed check batch details are immutable');
|
|
4437
4635
|
END;
|
|
4438
4636
|
|
|
4637
|
+
CREATE TRIGGER IF NOT EXISTS preserve_check_batch_environment_binding
|
|
4638
|
+
BEFORE UPDATE OF runtime_compatibility_json, batch_environment_json ON check_batch_details
|
|
4639
|
+
WHEN OLD.runtime_compatibility_json IS NOT NULL OR OLD.batch_environment_json IS NOT NULL
|
|
4640
|
+
OR NEW.runtime_compatibility_json IS NULL OR NEW.batch_environment_json IS NULL
|
|
4641
|
+
BEGIN
|
|
4642
|
+
SELECT RAISE(ABORT, 'Check batch environment binding is immutable');
|
|
4643
|
+
END;
|
|
4644
|
+
|
|
4439
4645
|
CREATE TRIGGER IF NOT EXISTS preserve_check_attempt_snapshots
|
|
4440
4646
|
BEFORE UPDATE OF execution_run_id, batch_run_id, definition_id, command_snapshot_json,
|
|
4441
4647
|
definition_fingerprint, initial_workspace_identity_json, rerun_of_attempt_run_id
|
|
@@ -4452,6 +4658,13 @@ db.exec(`
|
|
|
4452
4658
|
SELECT RAISE(ABORT, 'Completed check attempt details are immutable');
|
|
4453
4659
|
END;
|
|
4454
4660
|
|
|
4661
|
+
CREATE TRIGGER IF NOT EXISTS preserve_check_attempt_placement
|
|
4662
|
+
BEFORE UPDATE OF placement_json ON check_attempt_details
|
|
4663
|
+
WHEN OLD.placement_json IS NOT NULL OR NEW.placement_json IS NULL
|
|
4664
|
+
BEGIN
|
|
4665
|
+
SELECT RAISE(ABORT, 'Check attempt placement is immutable');
|
|
4666
|
+
END;
|
|
4667
|
+
|
|
4455
4668
|
CREATE TRIGGER IF NOT EXISTS validate_check_batch_details_insert
|
|
4456
4669
|
BEFORE INSERT ON check_batch_details
|
|
4457
4670
|
WHEN NOT EXISTS (
|