@straiffi/archon 1.7.7 → 1.7.8
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-DwfDSF4q.js +1 -0
- package/dist/client/assets/GitHubActionsDialog-3dMCYCSZ.js +1 -0
- package/dist/client/assets/VerificationDialog-CoTfXMyb.js +4 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DVbmGv0b.js → architectureDiagram-3BPJPVTR-Bdnc97XK.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-BsxPuJKK.js → blockDiagram-GPEHLZMM-boxM3She.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-9Jjpu2R1.js → c4Diagram-AAUBKEIU-CJDdF7xd.js} +1 -1
- package/dist/client/assets/channel-BGqdAcIT.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-Dzljq_5a.js → chunk-2J33WTMH-ClpcO-Om.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-CiBHaLdV.js → chunk-3OPIFGDE-CcuL_65J.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-DZFrI-_H.js → chunk-5ZQYHXKU-CUGYZXkH.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-u519MeJ7.js → chunk-727SXJPM-CApeLDyK.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DC91Nw9K.js → chunk-AQP2D5EJ-8FdSvF2D.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-CR7cwH-D.js → chunk-CSCIHK7Q-CZoIOF3a.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-DJwQEfa_.js → chunk-KSCS5N6A-BigFQI5y.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-w6TWSOTT.js → chunk-L5ZTLDWV-DIi3SHaT.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-Dfw_jEjR.js → chunk-LZXEDZCA-B-Z0BcQy.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-DHdJgCA7.js → chunk-ND2GUHAM-EBeba0mg.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-GvOuUiUy.js → chunk-NZK2D7GU-DJBI2y53.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O--r1VQgDc.js → chunk-O5CBEL6O-BqxdXhMd.js} +1 -1
- package/dist/client/assets/{chunk-WU5MYG2G-Xgc6shf5.js → chunk-WU5MYG2G-Coe1_Cbb.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-D5VuKRcj.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B9GNqpRr.js +1 -0
- package/dist/client/assets/{dagre-BM42HDAG-IcfTsQ6f.js → dagre-BM42HDAG-tuTmeA0Y.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-D8Z4_NSQ.js → diagram-2AECGRRQ-ILGCpG2F.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CIjC8QzH.js → diagram-5GNKFQAL-C8qBZsgK.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BBbYFygn.js → diagram-KO2AKTUF-BXlcm_Zo.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-lZstJdXv.js → diagram-LMA3HP47-B8V5EVbD.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-Cnqij60i.js → diagram-OG6HWLK6-CWsdOqcP.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-1DAJwSbR.js → erDiagram-TEJ5UH35-DW8pgly2.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-DIQkR95e.js → flowDiagram-I6XJVG4X-Djn7fOVR.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-mDGbRM53.js → ganttDiagram-6RSMTGT7-DZ421MEy.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BQirGZuE.js → gitGraphDiagram-PVQCEYII-CCNzLPuP.js} +1 -1
- package/dist/client/assets/index-BRc02lbW.js +273 -0
- package/dist/client/assets/index-CZO9HL1Z.css +2 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-CljoXByt.js → infoDiagram-5YYISTIA-Bd1gYgMp.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-ouY7AiSo.js → ishikawaDiagram-YF4QCWOH-txyMoatJ.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BiI9xI0r.js → journeyDiagram-JHISSGLW-DhT3bmX6.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CvuW7aYT.js → kanban-definition-UN3LZRKU-BBHt2hfC.js} +1 -1
- package/dist/client/assets/{line-CoE97hT8.js → line-KGRcT7Qz.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-BHswQsmF.js → mermaid-parser.core-CDzt4_zR.js} +1 -1
- package/dist/client/assets/{mermaid.core-a9PzZlL1.js → mermaid.core-DD_-k1aB.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-CIkEQqLV.js → mindmap-definition-RKZ34NQL-DoctVTDl.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BIvcv2M5.js → pieDiagram-4H26LBE5-DFlLEi70.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BWCVll7J.js → quadrantDiagram-W4KKPZXB-3YHOQgl7.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-w5l0CZn2.js → requirementDiagram-4Y6WPE33-X4fZVL9M.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-BuKReL9w.js → sankeyDiagram-5OEKKPKP-BUPnMXeG.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Br5KpukA.js → sequenceDiagram-3UESZ5HK-D6QU3M64.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-BfFCsPCI.js → stateDiagram-AJRCARHV-c35bu4qZ.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Ymy1_EHr.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-BrDP2iO0.js → timeline-definition-PNZ67QCA-CX2y6e_b.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-C7lGYnr9.js → vennDiagram-CIIHVFJN-BDaWltjF.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BRKJRuEF.js → wardleyDiagram-YWT4CUSO-BpBRL2sb.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-BjaB0hQ8.js → xychartDiagram-2RQKCTM6-Bqw7X0UT.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +458 -2
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +324 -25
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/activeAutomationChild.js +31 -0
- package/dist/server/lib/activeAutomationChild.js.map +1 -0
- package/dist/server/lib/automationCheckGate.js +266 -0
- package/dist/server/lib/automationCheckGate.js.map +1 -0
- package/dist/server/lib/automationProgression.js +20 -21
- package/dist/server/lib/automationProgression.js.map +1 -1
- package/dist/server/lib/automationReconciliation.js +16 -2
- package/dist/server/lib/automationReconciliation.js.map +1 -1
- package/dist/server/lib/automationResumeDecision.js +4 -1
- package/dist/server/lib/automationResumeDecision.js.map +1 -1
- package/dist/server/lib/automationStageDetails.js +173 -41
- package/dist/server/lib/automationStageDetails.js.map +1 -1
- package/dist/server/lib/checkDefinitions.js +278 -0
- package/dist/server/lib/checkDefinitions.js.map +1 -0
- package/dist/server/lib/checkGateEvaluations.js +294 -0
- package/dist/server/lib/checkGateEvaluations.js.map +1 -0
- package/dist/server/lib/checkRunner.js +674 -0
- package/dist/server/lib/checkRunner.js.map +1 -0
- package/dist/server/lib/checkRuns.js +736 -0
- package/dist/server/lib/checkRuns.js.map +1 -0
- package/dist/server/lib/checkWorkspaceIdentity.js +207 -0
- package/dist/server/lib/checkWorkspaceIdentity.js.map +1 -0
- package/dist/server/lib/executionReconciliation.js +79 -2
- package/dist/server/lib/executionReconciliation.js.map +1 -1
- package/dist/server/lib/executionRetry.js +14 -6
- package/dist/server/lib/executionRetry.js.map +1 -1
- package/dist/server/lib/executionRetryContext.js +3 -3
- package/dist/server/lib/executionRetryContext.js.map +1 -1
- package/dist/server/lib/executionRunRetention.js +41 -3
- package/dist/server/lib/executionRunRetention.js.map +1 -1
- package/dist/server/lib/executionRuns.js +135 -2
- package/dist/server/lib/executionRuns.js.map +1 -1
- package/dist/server/lib/executionTimeline.js +52 -1
- package/dist/server/lib/executionTimeline.js.map +1 -1
- package/dist/server/lib/projectAutoConfig.js +47 -65
- package/dist/server/lib/projectAutoConfig.js.map +1 -1
- package/dist/server/lib/projects.js +87 -7
- package/dist/server/lib/projects.js.map +1 -1
- package/dist/server/lib/requiredCheckPolicy.js +68 -0
- package/dist/server/lib/requiredCheckPolicy.js.map +1 -0
- package/dist/server/lib/shutdown.js +4 -4
- package/dist/server/lib/shutdown.js.map +1 -1
- package/dist/server/lib/testCommandRunner.js +3 -2
- package/dist/server/lib/testCommandRunner.js.map +1 -1
- package/dist/server/lib/testSessions.js +2 -6
- package/dist/server/lib/testSessions.js.map +1 -1
- package/dist/server/lib/ticketAutomationCommit.js +185 -22
- package/dist/server/lib/ticketAutomationCommit.js.map +1 -1
- package/dist/server/lib/tickets.js +21 -1
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/lib/types.js +2 -0
- package/dist/server/lib/types.js.map +1 -1
- package/dist/server/workers/review.js +2 -10
- package/dist/server/workers/review.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/ActivityView-Btpsv-5U.js +0 -1
- package/dist/client/assets/GitHubActionsDialog-DRlIMgSB.js +0 -1
- package/dist/client/assets/TestsDialog-DSWDkKPV.js +0 -4
- package/dist/client/assets/channel-Lic13vb5.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DACLwQIJ.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CKi6c1d9.js +0 -1
- package/dist/client/assets/index-DQt4dcwc.css +0 -2
- package/dist/client/assets/index-W9OCqkMU.js +0 -273
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-lhIQ8FTe.js +0 -1
package/dist/server/db.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
|
+
import { parseCheckDefinitionsJsonStrict, parseLegacyTestCommandsJsonStrict, projectCheckDefinitionsToTestCommands, } from './lib/checkDefinitions.js';
|
|
3
4
|
import { ensureParentDirectory, resolveArchonDbPath } from './lib/runtimePaths.js';
|
|
4
5
|
import { TRANSCRIPT_RUN_TEXT_LIMIT_BYTES, truncateUtf8 } from './lib/transcriptRuns.js';
|
|
5
6
|
const dbPath = ensureParentDirectory(resolveArchonDbPath());
|
|
@@ -55,6 +56,8 @@ db.exec(`
|
|
|
55
56
|
worktree_cmd TEXT,
|
|
56
57
|
run_setup TEXT,
|
|
57
58
|
run_services TEXT,
|
|
59
|
+
check_definitions TEXT,
|
|
60
|
+
required_check_definition_ids TEXT NOT NULL DEFAULT '[]',
|
|
58
61
|
test_commands TEXT,
|
|
59
62
|
run_ide TEXT,
|
|
60
63
|
preview_service_name TEXT,
|
|
@@ -129,6 +132,8 @@ ensureColumn('worktree_bundles', 'automation_pause_on_open_questions', 'INTEGER'
|
|
|
129
132
|
ensureColumn('projects', 'worktree_sync', 'TEXT');
|
|
130
133
|
ensureColumn('projects', 'active_target_kind', "TEXT NOT NULL DEFAULT 'repo_root'");
|
|
131
134
|
ensureColumn('projects', 'active_target_bundle_id', 'TEXT');
|
|
135
|
+
ensureColumn('projects', 'check_definitions', 'TEXT');
|
|
136
|
+
ensureColumn('projects', 'required_check_definition_ids', "TEXT NOT NULL DEFAULT '[]'");
|
|
132
137
|
ensureColumn('projects', 'test_commands', 'TEXT');
|
|
133
138
|
ensureColumn('projects', 'helper_model', 'TEXT');
|
|
134
139
|
ensureColumn('projects', 'helper_variant', 'TEXT');
|
|
@@ -144,6 +149,38 @@ ensureColumn('projects', 'spec_aware_code_review_enabled', 'INTEGER NOT NULL DEF
|
|
|
144
149
|
ensureColumn('projects', 'deletion_started_at', 'DATETIME');
|
|
145
150
|
ensureColumn('projects', 'deletion_claim_id', 'TEXT');
|
|
146
151
|
ensureColumn('projects', 'deletion_cleanup_started_at', 'DATETIME');
|
|
152
|
+
const backfillProjectCheckDefinitions = () => {
|
|
153
|
+
const rows = db.prepare(`
|
|
154
|
+
SELECT id, check_definitions, test_commands
|
|
155
|
+
FROM projects
|
|
156
|
+
`).all();
|
|
157
|
+
const update = db.prepare(`
|
|
158
|
+
UPDATE projects
|
|
159
|
+
SET check_definitions = ?, test_commands = ?
|
|
160
|
+
WHERE id = ?
|
|
161
|
+
`);
|
|
162
|
+
const migrate = db.transaction(() => {
|
|
163
|
+
for (const row of rows) {
|
|
164
|
+
if (row.check_definitions == null && row.test_commands == null) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const result = row.check_definitions == null
|
|
168
|
+
? parseLegacyTestCommandsJsonStrict(row.test_commands)
|
|
169
|
+
: parseCheckDefinitionsJsonStrict(row.check_definitions);
|
|
170
|
+
if ('error' in result) {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const definitions = result.value;
|
|
174
|
+
const canonicalJson = JSON.stringify(definitions);
|
|
175
|
+
const projectionJson = JSON.stringify(projectCheckDefinitionsToTestCommands(definitions));
|
|
176
|
+
if (row.check_definitions !== canonicalJson || row.test_commands !== projectionJson) {
|
|
177
|
+
update.run(canonicalJson, projectionJson, row.id);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
migrate();
|
|
182
|
+
};
|
|
183
|
+
backfillProjectCheckDefinitions();
|
|
147
184
|
db.exec(`
|
|
148
185
|
CREATE TRIGGER IF NOT EXISTS reject_ticket_insert_for_deleting_project
|
|
149
186
|
BEFORE INSERT ON tickets
|
|
@@ -1516,7 +1553,14 @@ const migrateExecutionLifecycleSchema = () => {
|
|
|
1516
1553
|
db.exec('ALTER TABLE lifecycle_events_v2 RENAME TO lifecycle_events');
|
|
1517
1554
|
db.exec('DROP TABLE execution_run_correlations');
|
|
1518
1555
|
const violations = db.prepare('PRAGMA foreign_key_check').all();
|
|
1519
|
-
if (violations.some(violation => [
|
|
1556
|
+
if (violations.some(violation => [
|
|
1557
|
+
'execution_runs',
|
|
1558
|
+
'lifecycle_events',
|
|
1559
|
+
'test_execution_details',
|
|
1560
|
+
'github_actions_run_details',
|
|
1561
|
+
'check_batch_details',
|
|
1562
|
+
'check_attempt_details',
|
|
1563
|
+
].includes(violation.table))) {
|
|
1520
1564
|
throw new Error('Execution lifecycle migration produced foreign key violations');
|
|
1521
1565
|
}
|
|
1522
1566
|
db.exec('COMMIT');
|
|
@@ -1755,6 +1799,377 @@ db.exec(`
|
|
|
1755
1799
|
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE
|
|
1756
1800
|
)
|
|
1757
1801
|
`);
|
|
1802
|
+
db.exec(`
|
|
1803
|
+
CREATE TABLE IF NOT EXISTS check_batch_details (
|
|
1804
|
+
execution_run_id TEXT PRIMARY KEY,
|
|
1805
|
+
target_kind TEXT NOT NULL,
|
|
1806
|
+
target_bundle_id TEXT,
|
|
1807
|
+
target_label TEXT,
|
|
1808
|
+
selected_definition_snapshots_json TEXT NOT NULL,
|
|
1809
|
+
initial_workspace_identity_json TEXT NOT NULL,
|
|
1810
|
+
configuration_fingerprint TEXT NOT NULL,
|
|
1811
|
+
stop_requested INTEGER NOT NULL DEFAULT 0,
|
|
1812
|
+
queued_count INTEGER NOT NULL DEFAULT 0,
|
|
1813
|
+
running_count INTEGER NOT NULL DEFAULT 0,
|
|
1814
|
+
passed_count INTEGER NOT NULL DEFAULT 0,
|
|
1815
|
+
failed_count INTEGER NOT NULL DEFAULT 0,
|
|
1816
|
+
cancelled_count INTEGER NOT NULL DEFAULT 0,
|
|
1817
|
+
interrupted_count INTEGER NOT NULL DEFAULT 0,
|
|
1818
|
+
rerun_of_batch_run_id TEXT,
|
|
1819
|
+
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE,
|
|
1820
|
+
FOREIGN KEY (rerun_of_batch_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
1821
|
+
CHECK (target_kind IN ('repo_root', 'bundle')),
|
|
1822
|
+
CHECK ((target_kind = 'repo_root' AND target_bundle_id IS NULL)
|
|
1823
|
+
OR (target_kind = 'bundle' AND target_bundle_id IS NOT NULL AND length(trim(target_bundle_id)) > 0)),
|
|
1824
|
+
CHECK (length(configuration_fingerprint) = 64 AND configuration_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
1825
|
+
CHECK (stop_requested IN (0, 1)),
|
|
1826
|
+
CHECK (queued_count >= 0 AND running_count >= 0 AND passed_count >= 0 AND failed_count >= 0
|
|
1827
|
+
AND cancelled_count >= 0 AND interrupted_count >= 0)
|
|
1828
|
+
)
|
|
1829
|
+
`);
|
|
1830
|
+
db.exec(`
|
|
1831
|
+
CREATE TABLE IF NOT EXISTS check_attempt_details (
|
|
1832
|
+
execution_run_id TEXT PRIMARY KEY,
|
|
1833
|
+
batch_run_id TEXT NOT NULL,
|
|
1834
|
+
definition_id TEXT NOT NULL,
|
|
1835
|
+
command_snapshot_json TEXT NOT NULL,
|
|
1836
|
+
definition_fingerprint TEXT NOT NULL,
|
|
1837
|
+
initial_workspace_identity_json TEXT NOT NULL,
|
|
1838
|
+
final_workspace_identity_json TEXT,
|
|
1839
|
+
outcome TEXT,
|
|
1840
|
+
rerun_of_attempt_run_id TEXT,
|
|
1841
|
+
exit_code INTEGER,
|
|
1842
|
+
exit_signal TEXT,
|
|
1843
|
+
exit_error TEXT,
|
|
1844
|
+
output_revision INTEGER NOT NULL DEFAULT 0,
|
|
1845
|
+
retained_start_offset INTEGER NOT NULL DEFAULT 0,
|
|
1846
|
+
retained_end_offset INTEGER NOT NULL DEFAULT 0,
|
|
1847
|
+
total_persisted_bytes INTEGER NOT NULL DEFAULT 0,
|
|
1848
|
+
retained_output TEXT NOT NULL DEFAULT '',
|
|
1849
|
+
output_retention_state TEXT NOT NULL DEFAULT 'retained',
|
|
1850
|
+
FOREIGN KEY (execution_run_id) REFERENCES execution_runs(id) ON DELETE CASCADE,
|
|
1851
|
+
FOREIGN KEY (batch_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
1852
|
+
FOREIGN KEY (rerun_of_attempt_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
1853
|
+
CHECK (length(definition_id) BETWEEN 1 AND 500),
|
|
1854
|
+
CHECK (length(definition_fingerprint) = 64 AND definition_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
1855
|
+
CHECK (outcome IS NULL OR outcome IN ('passed', 'command_failure', 'spawn_failure', 'timeout',
|
|
1856
|
+
'workspace_changed_before_start', 'user_stop', 'restart_loss', 'shutdown_loss')),
|
|
1857
|
+
CHECK (output_revision >= 0 AND retained_start_offset >= 0 AND retained_end_offset >= retained_start_offset
|
|
1858
|
+
AND total_persisted_bytes >= retained_end_offset),
|
|
1859
|
+
CHECK (output_retention_state IN ('retained', 'expired'))
|
|
1860
|
+
)
|
|
1861
|
+
`);
|
|
1862
|
+
db.exec(`
|
|
1863
|
+
CREATE TABLE IF NOT EXISTS check_gate_evaluations (
|
|
1864
|
+
id TEXT PRIMARY KEY,
|
|
1865
|
+
project_id TEXT NOT NULL,
|
|
1866
|
+
target_kind TEXT NOT NULL,
|
|
1867
|
+
target_bundle_id TEXT,
|
|
1868
|
+
automation_progression_run_id TEXT,
|
|
1869
|
+
boundary_kind TEXT NOT NULL,
|
|
1870
|
+
effective_policy_fingerprint TEXT NOT NULL,
|
|
1871
|
+
source_batch_run_id TEXT,
|
|
1872
|
+
decision TEXT NOT NULL,
|
|
1873
|
+
reason_codes_json TEXT NOT NULL,
|
|
1874
|
+
snapshot_json TEXT NOT NULL,
|
|
1875
|
+
expected_attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
1876
|
+
attempts_sealed INTEGER NOT NULL DEFAULT 1,
|
|
1877
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
1878
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
1879
|
+
FOREIGN KEY (source_batch_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
1880
|
+
CHECK (target_kind IN ('repo_root', 'bundle')),
|
|
1881
|
+
CHECK ((target_kind = 'repo_root' AND target_bundle_id IS NULL)
|
|
1882
|
+
OR (target_kind = 'bundle' AND target_bundle_id IS NOT NULL AND length(trim(target_bundle_id)) > 0)),
|
|
1883
|
+
CHECK (length(boundary_kind) BETWEEN 1 AND 100),
|
|
1884
|
+
CHECK (length(effective_policy_fingerprint) = 64 AND effective_policy_fingerprint NOT GLOB '*[^0-9a-f]*'),
|
|
1885
|
+
CHECK (decision IN ('passed', 'blocked')),
|
|
1886
|
+
CHECK (expected_attempt_count >= 0),
|
|
1887
|
+
CHECK (attempts_sealed IN (0, 1)),
|
|
1888
|
+
CHECK (length(CAST(reason_codes_json AS BLOB)) <= 16384),
|
|
1889
|
+
CHECK (length(CAST(snapshot_json AS BLOB)) <= 262144)
|
|
1890
|
+
);
|
|
1891
|
+
|
|
1892
|
+
CREATE TABLE IF NOT EXISTS check_gate_evaluation_attempts (
|
|
1893
|
+
evaluation_id TEXT NOT NULL,
|
|
1894
|
+
ordinal INTEGER NOT NULL,
|
|
1895
|
+
attempt_run_id TEXT NOT NULL,
|
|
1896
|
+
attempt_snapshot_json TEXT NOT NULL,
|
|
1897
|
+
PRIMARY KEY (evaluation_id, ordinal),
|
|
1898
|
+
UNIQUE (evaluation_id, attempt_run_id),
|
|
1899
|
+
FOREIGN KEY (evaluation_id) REFERENCES check_gate_evaluations(id) ON DELETE CASCADE,
|
|
1900
|
+
FOREIGN KEY (attempt_run_id) REFERENCES execution_runs(id) ON DELETE RESTRICT,
|
|
1901
|
+
CHECK (ordinal >= 0),
|
|
1902
|
+
CHECK (length(CAST(attempt_snapshot_json AS BLOB)) <= 65536)
|
|
1903
|
+
);
|
|
1904
|
+
|
|
1905
|
+
CREATE TRIGGER IF NOT EXISTS preserve_check_gate_evaluations
|
|
1906
|
+
BEFORE UPDATE OF id, project_id, target_kind, target_bundle_id, automation_progression_run_id,
|
|
1907
|
+
boundary_kind, effective_policy_fingerprint, source_batch_run_id, decision, reason_codes_json,
|
|
1908
|
+
snapshot_json, expected_attempt_count, created_at ON check_gate_evaluations
|
|
1909
|
+
BEGIN
|
|
1910
|
+
SELECT RAISE(ABORT, 'Check gate evaluations are immutable');
|
|
1911
|
+
END;
|
|
1912
|
+
|
|
1913
|
+
CREATE TRIGGER IF NOT EXISTS preserve_check_gate_evaluation_attempts
|
|
1914
|
+
BEFORE UPDATE ON check_gate_evaluation_attempts
|
|
1915
|
+
BEGIN
|
|
1916
|
+
SELECT RAISE(ABORT, 'Check gate evaluation attempts are immutable');
|
|
1917
|
+
END;
|
|
1918
|
+
|
|
1919
|
+
CREATE TRIGGER IF NOT EXISTS prevent_check_gate_evaluation_delete
|
|
1920
|
+
BEFORE DELETE ON check_gate_evaluations
|
|
1921
|
+
WHEN EXISTS (
|
|
1922
|
+
SELECT 1 FROM projects WHERE id = OLD.project_id AND deletion_started_at IS NULL
|
|
1923
|
+
)
|
|
1924
|
+
BEGIN
|
|
1925
|
+
SELECT RAISE(ABORT, 'Check gate evaluations are immutable');
|
|
1926
|
+
END;
|
|
1927
|
+
|
|
1928
|
+
|
|
1929
|
+
CREATE TRIGGER IF NOT EXISTS prevent_check_gate_evaluation_attempt_delete
|
|
1930
|
+
BEFORE DELETE ON check_gate_evaluation_attempts
|
|
1931
|
+
WHEN EXISTS (
|
|
1932
|
+
SELECT 1
|
|
1933
|
+
FROM check_gate_evaluations evaluation
|
|
1934
|
+
JOIN projects project ON project.id = evaluation.project_id
|
|
1935
|
+
WHERE evaluation.id = OLD.evaluation_id AND project.deletion_started_at IS NULL
|
|
1936
|
+
)
|
|
1937
|
+
BEGIN
|
|
1938
|
+
SELECT RAISE(ABORT, 'Check gate evaluation attempts are immutable');
|
|
1939
|
+
END;
|
|
1940
|
+
|
|
1941
|
+
CREATE TRIGGER IF NOT EXISTS validate_check_gate_evaluation_insert
|
|
1942
|
+
BEFORE INSERT ON check_gate_evaluations
|
|
1943
|
+
WHEN (
|
|
1944
|
+
NEW.source_batch_run_id IS NOT NULL
|
|
1945
|
+
AND NOT EXISTS (
|
|
1946
|
+
SELECT 1 FROM execution_runs
|
|
1947
|
+
WHERE id = NEW.source_batch_run_id AND project_id = NEW.project_id AND kind = 'check_batch'
|
|
1948
|
+
)
|
|
1949
|
+
) OR (
|
|
1950
|
+
NEW.automation_progression_run_id IS NOT NULL
|
|
1951
|
+
AND NOT EXISTS (
|
|
1952
|
+
SELECT 1 FROM execution_runs
|
|
1953
|
+
WHERE id = NEW.automation_progression_run_id
|
|
1954
|
+
AND project_id = NEW.project_id AND kind = 'automation_progression'
|
|
1955
|
+
)
|
|
1956
|
+
) OR (
|
|
1957
|
+
NEW.source_batch_run_id IS NOT NULL
|
|
1958
|
+
AND NOT EXISTS (
|
|
1959
|
+
SELECT 1 FROM execution_runs batch
|
|
1960
|
+
WHERE batch.id = NEW.source_batch_run_id
|
|
1961
|
+
AND (
|
|
1962
|
+
(batch.parent_run_id IS NULL AND NEW.automation_progression_run_id IS NULL)
|
|
1963
|
+
OR batch.parent_run_id = NEW.automation_progression_run_id
|
|
1964
|
+
)
|
|
1965
|
+
)
|
|
1966
|
+
)
|
|
1967
|
+
BEGIN
|
|
1968
|
+
SELECT RAISE(ABORT, 'Invalid check gate evaluation lineage');
|
|
1969
|
+
END;
|
|
1970
|
+
|
|
1971
|
+
CREATE TRIGGER IF NOT EXISTS validate_check_gate_evaluation_attempt_insert
|
|
1972
|
+
BEFORE INSERT ON check_gate_evaluation_attempts
|
|
1973
|
+
WHEN NOT EXISTS (
|
|
1974
|
+
SELECT 1
|
|
1975
|
+
FROM check_gate_evaluations evaluation
|
|
1976
|
+
JOIN execution_runs attempt ON attempt.id = NEW.attempt_run_id
|
|
1977
|
+
WHERE evaluation.id = NEW.evaluation_id
|
|
1978
|
+
AND attempt.project_id = evaluation.project_id
|
|
1979
|
+
AND attempt.kind = 'check_attempt'
|
|
1980
|
+
)
|
|
1981
|
+
BEGIN
|
|
1982
|
+
SELECT RAISE(ABORT, 'Invalid check gate evaluation attempt lineage');
|
|
1983
|
+
END;
|
|
1984
|
+
`);
|
|
1985
|
+
ensureColumn('check_gate_evaluations', 'expected_attempt_count', 'INTEGER NOT NULL DEFAULT 0');
|
|
1986
|
+
ensureColumn('check_gate_evaluations', 'attempts_sealed', 'INTEGER NOT NULL DEFAULT 1');
|
|
1987
|
+
db.exec(`
|
|
1988
|
+
DROP TRIGGER IF EXISTS preserve_check_gate_evaluations;
|
|
1989
|
+
DROP TRIGGER IF EXISTS seal_check_gate_evaluation_attempts;
|
|
1990
|
+
DROP TRIGGER IF EXISTS validate_check_gate_evaluation_insert;
|
|
1991
|
+
DROP TRIGGER IF EXISTS validate_check_gate_evaluation_attempt_insert;
|
|
1992
|
+
|
|
1993
|
+
CREATE TRIGGER preserve_check_gate_evaluations
|
|
1994
|
+
BEFORE UPDATE OF id, project_id, target_kind, target_bundle_id, automation_progression_run_id,
|
|
1995
|
+
boundary_kind, effective_policy_fingerprint, source_batch_run_id, decision, reason_codes_json,
|
|
1996
|
+
snapshot_json, expected_attempt_count, created_at ON check_gate_evaluations
|
|
1997
|
+
BEGIN
|
|
1998
|
+
SELECT RAISE(ABORT, 'Check gate evaluations are immutable');
|
|
1999
|
+
END;
|
|
2000
|
+
|
|
2001
|
+
CREATE TRIGGER seal_check_gate_evaluation_attempts
|
|
2002
|
+
BEFORE UPDATE OF attempts_sealed ON check_gate_evaluations
|
|
2003
|
+
WHEN OLD.attempts_sealed <> 0 OR NEW.attempts_sealed <> 1 OR (
|
|
2004
|
+
SELECT COUNT(*) FROM check_gate_evaluation_attempts WHERE evaluation_id = OLD.id
|
|
2005
|
+
) <> OLD.expected_attempt_count
|
|
2006
|
+
BEGIN
|
|
2007
|
+
SELECT RAISE(ABORT, 'Invalid check gate evaluation seal');
|
|
2008
|
+
END;
|
|
2009
|
+
|
|
2010
|
+
CREATE TRIGGER validate_check_gate_evaluation_insert
|
|
2011
|
+
BEFORE INSERT ON check_gate_evaluations
|
|
2012
|
+
WHEN (
|
|
2013
|
+
NEW.source_batch_run_id IS NOT NULL
|
|
2014
|
+
AND NOT EXISTS (
|
|
2015
|
+
SELECT 1 FROM execution_runs
|
|
2016
|
+
WHERE id = NEW.source_batch_run_id AND project_id = NEW.project_id AND kind = 'check_batch'
|
|
2017
|
+
)
|
|
2018
|
+
) OR (
|
|
2019
|
+
NEW.automation_progression_run_id IS NOT NULL
|
|
2020
|
+
AND NOT EXISTS (
|
|
2021
|
+
SELECT 1 FROM execution_runs
|
|
2022
|
+
WHERE id = NEW.automation_progression_run_id
|
|
2023
|
+
AND project_id = NEW.project_id AND kind = 'automation_progression'
|
|
2024
|
+
)
|
|
2025
|
+
) OR (
|
|
2026
|
+
NEW.source_batch_run_id IS NOT NULL
|
|
2027
|
+
AND NOT EXISTS (
|
|
2028
|
+
SELECT 1 FROM execution_runs batch
|
|
2029
|
+
WHERE batch.id = NEW.source_batch_run_id
|
|
2030
|
+
AND (
|
|
2031
|
+
(batch.initiated_by <> 'automation' AND batch.parent_run_id IS NULL)
|
|
2032
|
+
OR (batch.initiated_by = 'automation' AND batch.parent_run_id = NEW.automation_progression_run_id)
|
|
2033
|
+
)
|
|
2034
|
+
)
|
|
2035
|
+
)
|
|
2036
|
+
BEGIN
|
|
2037
|
+
SELECT RAISE(ABORT, 'Invalid check gate evaluation lineage');
|
|
2038
|
+
END;
|
|
2039
|
+
|
|
2040
|
+
CREATE TRIGGER validate_check_gate_evaluation_attempt_insert
|
|
2041
|
+
BEFORE INSERT ON check_gate_evaluation_attempts
|
|
2042
|
+
WHEN NOT EXISTS (
|
|
2043
|
+
SELECT 1
|
|
2044
|
+
FROM check_gate_evaluations evaluation
|
|
2045
|
+
JOIN execution_runs attempt ON attempt.id = NEW.attempt_run_id
|
|
2046
|
+
JOIN check_attempt_details details ON details.execution_run_id = attempt.id
|
|
2047
|
+
WHERE evaluation.id = NEW.evaluation_id
|
|
2048
|
+
AND evaluation.attempts_sealed = 0
|
|
2049
|
+
AND NEW.ordinal < evaluation.expected_attempt_count
|
|
2050
|
+
AND evaluation.source_batch_run_id IS NOT NULL
|
|
2051
|
+
AND details.batch_run_id = evaluation.source_batch_run_id
|
|
2052
|
+
AND attempt.project_id = evaluation.project_id
|
|
2053
|
+
AND attempt.kind = 'check_attempt'
|
|
2054
|
+
)
|
|
2055
|
+
BEGIN
|
|
2056
|
+
SELECT RAISE(ABORT, 'Invalid check gate evaluation attempt lineage');
|
|
2057
|
+
END;
|
|
2058
|
+
`);
|
|
2059
|
+
ensureColumn('check_attempt_details', 'retained_end_offset', 'INTEGER NOT NULL DEFAULT 0');
|
|
2060
|
+
ensureColumn('check_attempt_details', 'retained_output', "TEXT NOT NULL DEFAULT ''");
|
|
2061
|
+
db.prepare(`
|
|
2062
|
+
UPDATE check_attempt_details
|
|
2063
|
+
SET retained_end_offset = total_persisted_bytes
|
|
2064
|
+
WHERE retained_end_offset = 0 AND total_persisted_bytes > 0
|
|
2065
|
+
`).run();
|
|
2066
|
+
db.exec('DROP TRIGGER IF EXISTS validate_check_batch_details_insert');
|
|
2067
|
+
db.exec(`
|
|
2068
|
+
CREATE TRIGGER IF NOT EXISTS preserve_check_batch_snapshots
|
|
2069
|
+
BEFORE UPDATE OF execution_run_id, target_kind, target_bundle_id, target_label,
|
|
2070
|
+
selected_definition_snapshots_json, initial_workspace_identity_json, configuration_fingerprint,
|
|
2071
|
+
rerun_of_batch_run_id ON check_batch_details
|
|
2072
|
+
BEGIN
|
|
2073
|
+
SELECT RAISE(ABORT, 'Check batch snapshots are immutable');
|
|
2074
|
+
END;
|
|
2075
|
+
|
|
2076
|
+
CREATE TRIGGER IF NOT EXISTS preserve_check_attempt_snapshots
|
|
2077
|
+
BEFORE UPDATE OF execution_run_id, batch_run_id, definition_id, command_snapshot_json,
|
|
2078
|
+
definition_fingerprint, initial_workspace_identity_json, rerun_of_attempt_run_id
|
|
2079
|
+
ON check_attempt_details
|
|
2080
|
+
BEGIN
|
|
2081
|
+
SELECT RAISE(ABORT, 'Check attempt snapshots are immutable');
|
|
2082
|
+
END;
|
|
2083
|
+
|
|
2084
|
+
CREATE TRIGGER IF NOT EXISTS preserve_completed_check_attempt_details
|
|
2085
|
+
BEFORE UPDATE OF final_workspace_identity_json, outcome, exit_code, exit_signal, exit_error
|
|
2086
|
+
ON check_attempt_details
|
|
2087
|
+
WHEN OLD.outcome IS NOT NULL
|
|
2088
|
+
BEGIN
|
|
2089
|
+
SELECT RAISE(ABORT, 'Completed check attempt details are immutable');
|
|
2090
|
+
END;
|
|
2091
|
+
|
|
2092
|
+
CREATE TRIGGER IF NOT EXISTS validate_check_batch_details_insert
|
|
2093
|
+
BEFORE INSERT ON check_batch_details
|
|
2094
|
+
WHEN NOT EXISTS (
|
|
2095
|
+
SELECT 1
|
|
2096
|
+
FROM execution_runs run
|
|
2097
|
+
WHERE run.id = NEW.execution_run_id
|
|
2098
|
+
AND run.kind = 'check_batch'
|
|
2099
|
+
AND (
|
|
2100
|
+
(run.parent_run_id IS NULL AND run.initiated_by <> 'automation')
|
|
2101
|
+
OR (
|
|
2102
|
+
run.initiated_by = 'automation'
|
|
2103
|
+
AND EXISTS (
|
|
2104
|
+
SELECT 1
|
|
2105
|
+
FROM execution_runs progression
|
|
2106
|
+
JOIN execution_run_links owner
|
|
2107
|
+
ON owner.execution_run_id = progression.id
|
|
2108
|
+
AND owner.project_id = progression.project_id
|
|
2109
|
+
AND owner.entity_type = 'bundle'
|
|
2110
|
+
AND owner.relationship = 'primary'
|
|
2111
|
+
JOIN worktree_bundles bundle
|
|
2112
|
+
ON bundle.id = owner.entity_id
|
|
2113
|
+
AND bundle.project_id = owner.project_id
|
|
2114
|
+
JOIN bundle_automation_state state
|
|
2115
|
+
ON state.project_id = progression.project_id
|
|
2116
|
+
AND state.worktree_bundle_id = owner.entity_id
|
|
2117
|
+
AND state.automation_progression_run_id = progression.id
|
|
2118
|
+
WHERE progression.id = run.parent_run_id
|
|
2119
|
+
AND progression.project_id = run.project_id
|
|
2120
|
+
AND progression.kind = 'automation_progression'
|
|
2121
|
+
AND progression.status IN ('queued', 'running', 'waiting')
|
|
2122
|
+
AND (
|
|
2123
|
+
(NEW.target_kind = 'bundle' AND owner.entity_id = NEW.target_bundle_id
|
|
2124
|
+
AND COALESCE(bundle.kind, 'worktree') <> 'project_root')
|
|
2125
|
+
OR (NEW.target_kind = 'repo_root' AND NEW.target_bundle_id IS NULL
|
|
2126
|
+
AND bundle.kind = 'project_root')
|
|
2127
|
+
)
|
|
2128
|
+
AND NOT EXISTS (
|
|
2129
|
+
SELECT 1 FROM execution_runs sibling
|
|
2130
|
+
WHERE sibling.project_id = run.project_id
|
|
2131
|
+
AND sibling.parent_run_id = progression.id
|
|
2132
|
+
AND sibling.id <> run.id
|
|
2133
|
+
AND sibling.kind IN ('check_batch', 'review', 'automation_review_fix', 'automation_commit', 'automation_push', 'automation_pull_request')
|
|
2134
|
+
AND sibling.status IN ('queued', 'running', 'waiting')
|
|
2135
|
+
)
|
|
2136
|
+
)
|
|
2137
|
+
)
|
|
2138
|
+
)
|
|
2139
|
+
) OR (
|
|
2140
|
+
NEW.rerun_of_batch_run_id IS NOT NULL AND NOT EXISTS (
|
|
2141
|
+
SELECT 1 FROM execution_runs source, execution_runs current
|
|
2142
|
+
WHERE source.id = NEW.rerun_of_batch_run_id AND source.kind = 'check_batch'
|
|
2143
|
+
AND current.id = NEW.execution_run_id AND source.project_id = current.project_id
|
|
2144
|
+
)
|
|
2145
|
+
)
|
|
2146
|
+
BEGIN
|
|
2147
|
+
SELECT RAISE(ABORT, 'Invalid check batch execution details');
|
|
2148
|
+
END;
|
|
2149
|
+
|
|
2150
|
+
CREATE TRIGGER IF NOT EXISTS validate_check_attempt_details_insert
|
|
2151
|
+
BEFORE INSERT ON check_attempt_details
|
|
2152
|
+
WHEN NOT EXISTS (
|
|
2153
|
+
SELECT 1
|
|
2154
|
+
FROM execution_runs attempt
|
|
2155
|
+
JOIN execution_runs batch ON batch.id = NEW.batch_run_id
|
|
2156
|
+
WHERE attempt.id = NEW.execution_run_id AND attempt.kind = 'check_attempt'
|
|
2157
|
+
AND attempt.parent_run_id = batch.id AND batch.kind = 'check_batch'
|
|
2158
|
+
AND attempt.project_id = batch.project_id AND attempt.correlation_id = batch.correlation_id
|
|
2159
|
+
) OR (
|
|
2160
|
+
NEW.rerun_of_attempt_run_id IS NOT NULL AND NOT EXISTS (
|
|
2161
|
+
SELECT 1
|
|
2162
|
+
FROM check_attempt_details source
|
|
2163
|
+
JOIN check_batch_details current_batch ON current_batch.execution_run_id = NEW.batch_run_id
|
|
2164
|
+
WHERE source.execution_run_id = NEW.rerun_of_attempt_run_id
|
|
2165
|
+
AND source.batch_run_id = current_batch.rerun_of_batch_run_id
|
|
2166
|
+
AND source.definition_id = NEW.definition_id
|
|
2167
|
+
)
|
|
2168
|
+
)
|
|
2169
|
+
BEGIN
|
|
2170
|
+
SELECT RAISE(ABORT, 'Invalid check attempt execution details');
|
|
2171
|
+
END;
|
|
2172
|
+
`);
|
|
1758
2173
|
ensureColumn('github_actions_run_details', 'ref', 'TEXT');
|
|
1759
2174
|
ensureColumn('github_actions_run_details', 'input_names_json', 'TEXT');
|
|
1760
2175
|
ensureColumn('github_actions_run_details', 'input_fingerprint', 'TEXT');
|
|
@@ -1983,6 +2398,12 @@ db.exec("CREATE UNIQUE INDEX IF NOT EXISTS idx_execution_run_links_primary ON ex
|
|
|
1983
2398
|
db.exec('CREATE INDEX IF NOT EXISTS idx_lifecycle_events_run_sequence ON lifecycle_events(project_id, execution_run_id, sequence ASC)');
|
|
1984
2399
|
db.exec('CREATE INDEX IF NOT EXISTS idx_lifecycle_events_project_created ON lifecycle_events(project_id, created_at DESC, id DESC)');
|
|
1985
2400
|
db.exec('CREATE INDEX IF NOT EXISTS idx_github_actions_details_dispatch ON github_actions_run_details(workflow_id, ref, dispatched_at DESC)');
|
|
2401
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_check_batches_rerun ON check_batch_details(rerun_of_batch_run_id)');
|
|
2402
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_check_attempts_batch ON check_attempt_details(batch_run_id, definition_id)');
|
|
2403
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_check_attempts_rerun ON check_attempt_details(rerun_of_attempt_run_id)');
|
|
2404
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_check_gate_evaluations_target ON check_gate_evaluations(project_id, target_kind, target_bundle_id, created_at DESC, id DESC)');
|
|
2405
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_check_gate_evaluations_batch ON check_gate_evaluations(source_batch_run_id)');
|
|
2406
|
+
db.exec('CREATE INDEX IF NOT EXISTS idx_check_gate_evaluation_attempts_run ON check_gate_evaluation_attempts(attempt_run_id)');
|
|
1986
2407
|
db.exec(`
|
|
1987
2408
|
CREATE TABLE IF NOT EXISTS project_memory_selections (
|
|
1988
2409
|
id TEXT PRIMARY KEY,
|
|
@@ -2133,11 +2554,46 @@ db.exec(`
|
|
|
2133
2554
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
2134
2555
|
FOREIGN KEY (worktree_bundle_id) REFERENCES worktree_bundles(id) ON DELETE CASCADE,
|
|
2135
2556
|
CHECK (stage_kind IN ('automation_commit', 'automation_push', 'automation_pull_request')),
|
|
2136
|
-
CHECK (schema_version
|
|
2557
|
+
CHECK (schema_version IN (1, 2)),
|
|
2137
2558
|
CHECK (length(CAST(intent_json AS BLOB)) BETWEEN 2 AND 16384),
|
|
2138
2559
|
CHECK (result_json IS NULL OR length(CAST(result_json AS BLOB)) BETWEEN 2 AND 16384)
|
|
2139
2560
|
)
|
|
2140
2561
|
`);
|
|
2562
|
+
const automationStageDetailsTableSql = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'automation_stage_details'").get()?.sql ?? '';
|
|
2563
|
+
if (!automationStageDetailsTableSql.includes('schema_version IN (1, 2)')) {
|
|
2564
|
+
db.transaction(() => {
|
|
2565
|
+
db.exec(`
|
|
2566
|
+
CREATE TABLE automation_stage_details_v2 (
|
|
2567
|
+
execution_run_id TEXT PRIMARY KEY,
|
|
2568
|
+
project_id TEXT NOT NULL,
|
|
2569
|
+
worktree_bundle_id TEXT NOT NULL,
|
|
2570
|
+
stage_kind TEXT NOT NULL,
|
|
2571
|
+
schema_version INTEGER NOT NULL,
|
|
2572
|
+
intent_json TEXT NOT NULL,
|
|
2573
|
+
result_json TEXT,
|
|
2574
|
+
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2575
|
+
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
2576
|
+
FOREIGN KEY (execution_run_id, project_id) REFERENCES execution_runs(id, project_id) ON DELETE CASCADE,
|
|
2577
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
2578
|
+
FOREIGN KEY (worktree_bundle_id) REFERENCES worktree_bundles(id) ON DELETE CASCADE,
|
|
2579
|
+
CHECK (stage_kind IN ('automation_commit', 'automation_push', 'automation_pull_request')),
|
|
2580
|
+
CHECK (schema_version IN (1, 2)),
|
|
2581
|
+
CHECK (length(CAST(intent_json AS BLOB)) BETWEEN 2 AND 16384),
|
|
2582
|
+
CHECK (result_json IS NULL OR length(CAST(result_json AS BLOB)) BETWEEN 2 AND 16384)
|
|
2583
|
+
);
|
|
2584
|
+
INSERT INTO automation_stage_details_v2 (
|
|
2585
|
+
execution_run_id, project_id, worktree_bundle_id, stage_kind, schema_version,
|
|
2586
|
+
intent_json, result_json, created_at, updated_at
|
|
2587
|
+
)
|
|
2588
|
+
SELECT
|
|
2589
|
+
execution_run_id, project_id, worktree_bundle_id, stage_kind, schema_version,
|
|
2590
|
+
intent_json, result_json, created_at, updated_at
|
|
2591
|
+
FROM automation_stage_details;
|
|
2592
|
+
DROP TABLE automation_stage_details;
|
|
2593
|
+
ALTER TABLE automation_stage_details_v2 RENAME TO automation_stage_details;
|
|
2594
|
+
`);
|
|
2595
|
+
})();
|
|
2596
|
+
}
|
|
2141
2597
|
db.exec(`
|
|
2142
2598
|
CREATE TABLE IF NOT EXISTS build_open_question_batches (
|
|
2143
2599
|
id TEXT PRIMARY KEY,
|