@dsh-enhanced/assistant-automations 0.1.7 → 0.1.14

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.
Files changed (55) hide show
  1. package/README.md +37 -7
  2. package/lib/coordinator.d.ts +45 -5
  3. package/lib/coordinator.d.ts.map +1 -1
  4. package/lib/coordinator.js +418 -86
  5. package/lib/coordinator.js.map +1 -1
  6. package/lib/growth.d.ts +120 -0
  7. package/lib/growth.d.ts.map +1 -0
  8. package/lib/growth.js +383 -0
  9. package/lib/growth.js.map +1 -0
  10. package/lib/host-executors.d.ts +25 -0
  11. package/lib/host-executors.d.ts.map +1 -0
  12. package/lib/host-executors.js +181 -0
  13. package/lib/host-executors.js.map +1 -0
  14. package/lib/index.d.ts +1 -1
  15. package/lib/index.d.ts.map +1 -1
  16. package/lib/index.js +1 -1
  17. package/lib/index.js.map +1 -1
  18. package/lib/operator.d.ts +2 -0
  19. package/lib/operator.d.ts.map +1 -1
  20. package/lib/operator.js +6 -2
  21. package/lib/operator.js.map +1 -1
  22. package/lib/proposals.d.ts +2 -2
  23. package/lib/proposals.d.ts.map +1 -1
  24. package/lib/proposals.js +34 -22
  25. package/lib/proposals.js.map +1 -1
  26. package/lib/runner.d.ts +28 -2
  27. package/lib/runner.d.ts.map +1 -1
  28. package/lib/runner.js +524 -73
  29. package/lib/runner.js.map +1 -1
  30. package/lib/schedule.d.ts.map +1 -1
  31. package/lib/schedule.js +37 -9
  32. package/lib/schedule.js.map +1 -1
  33. package/lib/service.d.ts +109 -4
  34. package/lib/service.d.ts.map +1 -1
  35. package/lib/service.js +987 -16
  36. package/lib/service.js.map +1 -1
  37. package/lib/sqlite.d.ts +1 -1
  38. package/lib/sqlite.d.ts.map +1 -1
  39. package/lib/sqlite.js +369 -41
  40. package/lib/sqlite.js.map +1 -1
  41. package/lib/store.d.ts +175 -1
  42. package/lib/store.d.ts.map +1 -1
  43. package/lib/store.js +1889 -71
  44. package/lib/store.js.map +1 -1
  45. package/lib/tools.js +1 -1
  46. package/lib/tools.js.map +1 -1
  47. package/lib/types.d.ts +354 -11
  48. package/lib/types.d.ts.map +1 -1
  49. package/lib/types.js +13 -1
  50. package/lib/types.js.map +1 -1
  51. package/lib/version.d.ts +1 -1
  52. package/lib/version.d.ts.map +1 -1
  53. package/lib/version.js +1 -1
  54. package/lib/version.js.map +1 -1
  55. package/package.json +10 -8
package/lib/sqlite.js CHANGED
@@ -1,7 +1,120 @@
1
1
  import { chmodSync, mkdirSync } from 'node:fs';
2
2
  import { dirname, isAbsolute } from 'node:path';
3
3
  import { DatabaseSync } from 'node:sqlite';
4
- export const automationSchemaVersion = 6;
4
+ export const automationSchemaVersion = 10;
5
+ const growthTablesV10 = `
6
+ CREATE TABLE automation_growth_operations (
7
+ operation_id TEXT PRIMARY KEY,
8
+ operation_kind TEXT NOT NULL CHECK (operation_kind IN (
9
+ 'approval-proposal', 'approval-settlement', 'replay', 'shadow',
10
+ 'canary', 'canary-inspection', 'promotion', 'rollback'
11
+ )),
12
+ payload_digest TEXT NOT NULL CHECK (length(payload_digest) = 64),
13
+ status TEXT NOT NULL CHECK (status IN ('pending', 'completed')),
14
+ receipt_json TEXT CHECK (receipt_json IS NULL OR json_valid(receipt_json)),
15
+ created_at INTEGER NOT NULL CHECK (created_at >= 0),
16
+ updated_at INTEGER NOT NULL CHECK (updated_at >= created_at),
17
+ CHECK ((status = 'completed') = (receipt_json IS NOT NULL))
18
+ ) STRICT;
19
+
20
+ CREATE TABLE automation_growth_artifacts (
21
+ artifact_id TEXT PRIMARY KEY,
22
+ experiment_id TEXT NOT NULL UNIQUE,
23
+ candidate_id TEXT NOT NULL,
24
+ candidate_revision INTEGER NOT NULL CHECK (candidate_revision >= 1),
25
+ candidate_digest TEXT NOT NULL CHECK (length(candidate_digest) = 64),
26
+ workspace TEXT NOT NULL,
27
+ preset TEXT NOT NULL,
28
+ owner_binding_id TEXT NOT NULL,
29
+ principal_id TEXT NOT NULL,
30
+ template_ref TEXT NOT NULL,
31
+ template_digest TEXT NOT NULL CHECK (length(template_digest) = 64),
32
+ privacy_attestation_json TEXT NOT NULL CHECK (
33
+ json_valid(privacy_attestation_json) AND json_type(privacy_attestation_json) = 'object'
34
+ ),
35
+ evidence_digest TEXT NOT NULL CHECK (length(evidence_digest) = 64),
36
+ evidence_count INTEGER NOT NULL CHECK (evidence_count >= 1),
37
+ steps_json TEXT NOT NULL CHECK (json_valid(steps_json) AND json_type(steps_json) = 'array'),
38
+ automation_id TEXT NOT NULL UNIQUE,
39
+ definition_hash TEXT NOT NULL CHECK (length(definition_hash) = 64),
40
+ definition_version INTEGER NOT NULL CHECK (definition_version >= 1),
41
+ proposal_id TEXT UNIQUE,
42
+ approval_diff_hash TEXT NOT NULL CHECK (length(approval_diff_hash) = 64),
43
+ deadline_at INTEGER NOT NULL CHECK (deadline_at >= 0),
44
+ state TEXT NOT NULL CHECK (state IN (
45
+ 'approval-pending', 'paused', 'canary-pending', 'promoted', 'rejected', 'rolled-back'
46
+ )),
47
+ shadow_task_id TEXT UNIQUE,
48
+ canary_task_id TEXT UNIQUE,
49
+ canary_run_id TEXT UNIQUE,
50
+ canary_evaluation_id TEXT UNIQUE,
51
+ canary_evaluation_digest TEXT CHECK (
52
+ canary_evaluation_digest IS NULL OR length(canary_evaluation_digest) = 64
53
+ ),
54
+ created_at INTEGER NOT NULL CHECK (created_at >= 0),
55
+ updated_at INTEGER NOT NULL CHECK (updated_at >= created_at),
56
+ FOREIGN KEY (automation_id) REFERENCES automation_definitions(id) ON DELETE RESTRICT,
57
+ FOREIGN KEY (shadow_task_id) REFERENCES automation_tasks(id) ON DELETE RESTRICT,
58
+ FOREIGN KEY (canary_task_id) REFERENCES automation_tasks(id) ON DELETE RESTRICT,
59
+ FOREIGN KEY (canary_run_id) REFERENCES automation_runs(id) ON DELETE RESTRICT
60
+ ) STRICT;
61
+ CREATE INDEX automation_growth_artifact_state
62
+ ON automation_growth_artifacts(state, updated_at, artifact_id);
63
+ `;
64
+ const incidentTableV9 = `
65
+ CREATE TABLE automation_incidents (
66
+ id TEXT PRIMARY KEY,
67
+ automation_id TEXT NOT NULL,
68
+ definition_hash TEXT NOT NULL,
69
+ stage TEXT NOT NULL CHECK (stage IN ('materialize', 'claim', 'terminal')),
70
+ state TEXT NOT NULL CHECK (state IN ('open', 'recovering', 'resolved')),
71
+ failure_class TEXT NOT NULL CHECK (failure_class IN (
72
+ 'budget', 'cancelled', 'configuration', 'execution', 'infrastructure',
73
+ 'policy', 'provider', 'timeout', 'unknown'
74
+ )),
75
+ failure_phase TEXT NOT NULL,
76
+ failure_code TEXT NOT NULL,
77
+ side_effect_state TEXT NOT NULL CHECK (side_effect_state IN ('none', 'possible', 'unknown')),
78
+ retryability TEXT NOT NULL CHECK (retryability IN ('safe', 'unsafe', 'after-intervention', 'unknown')),
79
+ notification_route_id TEXT NOT NULL,
80
+ lifecycle_generation INTEGER NOT NULL CHECK (lifecycle_generation >= 1),
81
+ presentation_revision INTEGER NOT NULL CHECK (presentation_revision >= 1),
82
+ alert_status TEXT NOT NULL CHECK (alert_status IN ('pending', 'enqueued', 'suppressed')),
83
+ alert_ref TEXT,
84
+ run_id TEXT,
85
+ opened_at INTEGER NOT NULL,
86
+ updated_at INTEGER NOT NULL,
87
+ resolved_at INTEGER,
88
+ version INTEGER NOT NULL CHECK (version >= 1),
89
+ UNIQUE (automation_id, definition_hash, stage),
90
+ CHECK (
91
+ (state IN ('open', 'recovering') AND resolved_at IS NULL)
92
+ OR (state = 'resolved' AND resolved_at IS NOT NULL)
93
+ ),
94
+ CHECK (
95
+ (alert_status = 'enqueued' AND alert_ref IS NOT NULL)
96
+ OR alert_status IN ('pending', 'suppressed')
97
+ )
98
+ ) STRICT;
99
+ CREATE INDEX automation_open_incidents
100
+ ON automation_incidents(state, updated_at, automation_id);
101
+ CREATE INDEX automation_incident_alert_outbox
102
+ ON automation_incidents(alert_status, opened_at, id);
103
+
104
+ CREATE TABLE IF NOT EXISTS automation_circuit_operations (
105
+ operation_id TEXT PRIMARY KEY,
106
+ system_owner TEXT NOT NULL,
107
+ automation_id TEXT NOT NULL,
108
+ definition_hash TEXT NOT NULL,
109
+ expected_circuit_version INTEGER NOT NULL CHECK (expected_circuit_version >= 1),
110
+ lease_ms INTEGER NOT NULL CHECK (lease_ms > 0),
111
+ input_hash TEXT NOT NULL,
112
+ result_json TEXT NOT NULL CHECK (json_valid(result_json)),
113
+ created_at INTEGER NOT NULL
114
+ ) STRICT;
115
+ CREATE INDEX IF NOT EXISTS automation_circuit_operation_scope
116
+ ON automation_circuit_operations(system_owner, automation_id, definition_hash, created_at);
117
+ `;
5
118
  export class AutomationDatabaseError extends Error {
6
119
  code;
7
120
  constructor(code, message) {
@@ -10,6 +123,65 @@ export class AutomationDatabaseError extends Error {
10
123
  this.name = 'AutomationDatabaseError';
11
124
  }
12
125
  }
126
+ function repairCircuitPreviewV7(database) {
127
+ const table = database.prepare(`
128
+ SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'automation_circuits'
129
+ `).get();
130
+ const columns = table === undefined
131
+ ? []
132
+ : database.prepare(`PRAGMA table_info('automation_circuits')`).all();
133
+ if (['probe_token', 'probe_lease_until', 'probe_task_id'].every(name => columns.some(column => column.name === name)) && table?.sql.includes("'half-open'") === true && table.sql.includes("'probing'") === true)
134
+ return;
135
+ const create = `
136
+ CREATE TABLE automation_circuits (
137
+ automation_id TEXT NOT NULL,
138
+ definition_hash TEXT NOT NULL,
139
+ state TEXT NOT NULL CHECK (state IN ('open', 'half-open', 'probing', 'closed')),
140
+ failure_class TEXT NOT NULL CHECK (failure_class IN ('configuration', 'policy', 'budget')),
141
+ failure_phase TEXT NOT NULL,
142
+ failure_code TEXT NOT NULL,
143
+ opened_at INTEGER NOT NULL,
144
+ updated_at INTEGER NOT NULL,
145
+ probe_token TEXT,
146
+ probe_lease_until INTEGER,
147
+ probe_task_id TEXT,
148
+ version INTEGER NOT NULL CHECK (version >= 1),
149
+ CHECK (
150
+ (state IN ('open', 'closed') AND probe_token IS NULL AND probe_lease_until IS NULL AND probe_task_id IS NULL)
151
+ OR (state = 'half-open' AND probe_token IS NOT NULL AND probe_lease_until IS NOT NULL AND probe_task_id IS NULL)
152
+ OR (state = 'probing' AND probe_token IS NOT NULL AND probe_lease_until IS NOT NULL AND probe_task_id IS NOT NULL)
153
+ ),
154
+ PRIMARY KEY (automation_id, definition_hash)
155
+ ) STRICT;
156
+ `;
157
+ if (table === undefined) {
158
+ database.exec(`
159
+ BEGIN IMMEDIATE;
160
+ ${create}
161
+ CREATE INDEX automation_open_circuits ON automation_circuits(state, updated_at, automation_id);
162
+ COMMIT;
163
+ `);
164
+ return;
165
+ }
166
+ // v7 existed briefly as a preview with a binary open/closed table. Rebuild
167
+ // it in-place while preserving every exact-definition circuit and version.
168
+ database.exec(`
169
+ BEGIN IMMEDIATE;
170
+ DROP INDEX IF EXISTS automation_open_circuits;
171
+ ALTER TABLE automation_circuits RENAME TO automation_circuits_preview_v7;
172
+ ${create}
173
+ INSERT INTO automation_circuits(
174
+ automation_id, definition_hash, state, failure_class, failure_phase,
175
+ failure_code, opened_at, updated_at, version
176
+ )
177
+ SELECT automation_id, definition_hash, state, failure_class, failure_phase,
178
+ failure_code, opened_at, updated_at, version
179
+ FROM automation_circuits_preview_v7;
180
+ DROP TABLE automation_circuits_preview_v7;
181
+ CREATE INDEX automation_open_circuits ON automation_circuits(state, updated_at, automation_id);
182
+ COMMIT;
183
+ `);
184
+ }
13
185
  function migrate(database) {
14
186
  let version = database.prepare('PRAGMA user_version').get().user_version;
15
187
  if (version > automationSchemaVersion) {
@@ -108,6 +280,9 @@ function migrate(database) {
108
280
  artifact_ref TEXT,
109
281
  output_preview TEXT NOT NULL,
110
282
  usage_json TEXT NOT NULL,
283
+ execution_mode TEXT NOT NULL CHECK (execution_mode IN ('production', 'preview', 'unknown')),
284
+ definition_hash TEXT,
285
+ diagnostic_json TEXT NOT NULL CHECK (json_valid(diagnostic_json)),
111
286
  delivery_status TEXT,
112
287
  delivery_ref TEXT,
113
288
  evidence_status TEXT NOT NULL CHECK (evidence_status IN ('pending', 'recorded', 'suppressed')),
@@ -141,6 +316,30 @@ function migrate(database) {
141
316
  CREATE INDEX automation_evaluation_dispatch
142
317
  ON automation_evaluation_outbox(status, next_attempt_at, id);
143
318
 
319
+ CREATE TABLE automation_circuits (
320
+ automation_id TEXT NOT NULL,
321
+ definition_hash TEXT NOT NULL,
322
+ state TEXT NOT NULL CHECK (state IN ('open', 'half-open', 'probing', 'closed')),
323
+ failure_class TEXT NOT NULL CHECK (failure_class IN ('configuration', 'policy', 'budget')),
324
+ failure_phase TEXT NOT NULL,
325
+ failure_code TEXT NOT NULL,
326
+ opened_at INTEGER NOT NULL,
327
+ updated_at INTEGER NOT NULL,
328
+ probe_token TEXT,
329
+ probe_lease_until INTEGER,
330
+ probe_task_id TEXT,
331
+ version INTEGER NOT NULL CHECK (version >= 1),
332
+ CHECK (
333
+ (state IN ('open', 'closed') AND probe_token IS NULL AND probe_lease_until IS NULL AND probe_task_id IS NULL)
334
+ OR (state = 'half-open' AND probe_token IS NOT NULL AND probe_lease_until IS NOT NULL AND probe_task_id IS NULL)
335
+ OR (state = 'probing' AND probe_token IS NOT NULL AND probe_lease_until IS NOT NULL AND probe_task_id IS NOT NULL)
336
+ ),
337
+ PRIMARY KEY (automation_id, definition_hash)
338
+ ) STRICT;
339
+ CREATE INDEX automation_open_circuits ON automation_circuits(state, updated_at, automation_id);
340
+
341
+ ${incidentTableV9}
342
+
144
343
  CREATE TABLE duty_lease (
145
344
  singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
146
345
  owner_id TEXT NOT NULL,
@@ -177,7 +376,8 @@ function migrate(database) {
177
376
  FOREIGN KEY (automation_id) REFERENCES automation_definitions(id)
178
377
  ) STRICT;
179
378
 
180
- PRAGMA user_version = 6;
379
+ ${growthTablesV10}
380
+ PRAGMA user_version = 10;
181
381
  COMMIT;
182
382
  `);
183
383
  return;
@@ -322,52 +522,180 @@ function migrate(database) {
322
522
  PRAGMA user_version = 6;
323
523
  COMMIT;
324
524
  `);
325
- return;
525
+ version = 6;
326
526
  }
527
+ else {
528
+ database.exec(`
529
+ BEGIN IMMEDIATE;
530
+ ${hasAttempts ? `
531
+ ALTER TABLE automation_attempts ADD COLUMN automation_snapshot_hash TEXT;
532
+ ALTER TABLE automation_attempts ADD COLUMN automation_snapshot_json TEXT
533
+ CHECK (automation_snapshot_json IS NULL OR json_valid(automation_snapshot_json));
534
+ ` : ''}
535
+ ${hasOutbox ? `
536
+ ALTER TABLE automation_evaluation_outbox RENAME TO automation_evaluation_outbox_v5;
537
+ DROP INDEX IF EXISTS automation_evaluation_dispatch;
538
+ ` : ''}
539
+ CREATE TABLE automation_evaluation_outbox (
540
+ id TEXT PRIMARY KEY,
541
+ run_id TEXT NOT NULL,
542
+ observation_kind TEXT NOT NULL CHECK (observation_kind IN ('terminal')),
543
+ status TEXT NOT NULL CHECK (status IN ('pending', 'recorded', 'dead-letter')),
544
+ payload_json TEXT NOT NULL CHECK (json_valid(payload_json)),
545
+ attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
546
+ next_attempt_at INTEGER NOT NULL,
547
+ last_failure_at INTEGER,
548
+ last_error_code TEXT,
549
+ created_at INTEGER NOT NULL,
550
+ updated_at INTEGER NOT NULL,
551
+ FOREIGN KEY (run_id) REFERENCES automation_runs(id)
552
+ ) STRICT;
553
+ ${hasOutbox ? `
554
+ INSERT INTO automation_evaluation_outbox(
555
+ id, run_id, observation_kind, status, payload_json, attempt_count,
556
+ next_attempt_at, last_failure_at, last_error_code, created_at, updated_at
557
+ )
558
+ SELECT id, run_id, observation_kind,
559
+ CASE WHEN status = 'pending' THEN 'dead-letter' ELSE status END,
560
+ payload_json,
561
+ CASE WHEN status = 'pending' THEN 1 ELSE 0 END,
562
+ updated_at,
563
+ CASE WHEN status = 'pending' THEN updated_at ELSE NULL END,
564
+ CASE WHEN status = 'pending' THEN 'legacy-unverifiable-provenance' ELSE NULL END,
565
+ created_at, updated_at
566
+ FROM automation_evaluation_outbox_v5;
567
+ DROP TABLE automation_evaluation_outbox_v5;
568
+ ` : ''}
569
+ CREATE INDEX automation_evaluation_dispatch
570
+ ON automation_evaluation_outbox(status, next_attempt_at, id);
571
+ PRAGMA user_version = 6;
572
+ COMMIT;
573
+ `);
574
+ version = 6;
575
+ }
576
+ }
577
+ if (version === 6) {
578
+ const hasRuns = database.prepare(`
579
+ SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'automation_runs'
580
+ `).get() !== undefined;
581
+ const hasOccurrences = database.prepare(`
582
+ SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'automation_occurrences'
583
+ `).get() !== undefined;
584
+ const legacyDiagnostic = JSON.stringify({
585
+ schemaVersion: 1,
586
+ failureClass: 'unknown',
587
+ failurePhase: 'unknown',
588
+ failureCode: 'legacy-runner-unclassified',
589
+ promptSubmissionState: 'unknown',
590
+ sideEffectState: 'unknown',
591
+ retryability: 'unknown',
592
+ budgetSettlementState: 'unknown',
593
+ }).replaceAll("'", "''");
327
594
  database.exec(`
328
595
  BEGIN IMMEDIATE;
329
- ${hasAttempts ? `
330
- ALTER TABLE automation_attempts ADD COLUMN automation_snapshot_hash TEXT;
331
- ALTER TABLE automation_attempts ADD COLUMN automation_snapshot_json TEXT
332
- CHECK (automation_snapshot_json IS NULL OR json_valid(automation_snapshot_json));
596
+ ${hasRuns ? `
597
+ ALTER TABLE automation_runs ADD COLUMN execution_mode TEXT NOT NULL DEFAULT 'unknown'
598
+ CHECK (execution_mode IN ('production', 'preview', 'unknown'));
599
+ ALTER TABLE automation_runs ADD COLUMN definition_hash TEXT;
600
+ ALTER TABLE automation_runs ADD COLUMN diagnostic_json TEXT NOT NULL DEFAULT '${legacyDiagnostic}'
601
+ CHECK (json_valid(diagnostic_json));
602
+ ${hasOccurrences ? `
603
+ UPDATE automation_runs AS run
604
+ SET execution_mode = 'preview'
605
+ WHERE EXISTS (
606
+ SELECT 1 FROM automation_occurrences AS occurrence
607
+ WHERE occurrence.id = run.occurrence_id AND occurrence.dry_run = 1
608
+ );
609
+ UPDATE automation_runs AS run
610
+ SET evidence_status = 'suppressed', evidence_json = NULL,
611
+ delivery_ref = CASE WHEN delivery_status = 'pending' THEN NULL ELSE delivery_ref END,
612
+ delivery_status = CASE WHEN delivery_status = 'pending' THEN 'suppressed' ELSE delivery_status END
613
+ WHERE EXISTS (
614
+ SELECT 1 FROM automation_occurrences AS occurrence
615
+ WHERE occurrence.id = run.occurrence_id AND occurrence.dry_run = 1
616
+ );
333
617
  ` : ''}
334
- ${hasOutbox ? `
335
- ALTER TABLE automation_evaluation_outbox RENAME TO automation_evaluation_outbox_v5;
336
- DROP INDEX IF EXISTS automation_evaluation_dispatch;
337
618
  ` : ''}
338
- CREATE TABLE automation_evaluation_outbox (
339
- id TEXT PRIMARY KEY,
340
- run_id TEXT NOT NULL,
341
- observation_kind TEXT NOT NULL CHECK (observation_kind IN ('terminal')),
342
- status TEXT NOT NULL CHECK (status IN ('pending', 'recorded', 'dead-letter')),
343
- payload_json TEXT NOT NULL CHECK (json_valid(payload_json)),
344
- attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
345
- next_attempt_at INTEGER NOT NULL,
346
- last_failure_at INTEGER,
347
- last_error_code TEXT,
348
- created_at INTEGER NOT NULL,
619
+ CREATE TABLE automation_circuits (
620
+ automation_id TEXT NOT NULL,
621
+ definition_hash TEXT NOT NULL,
622
+ state TEXT NOT NULL CHECK (state IN ('open', 'half-open', 'probing', 'closed')),
623
+ failure_class TEXT NOT NULL CHECK (failure_class IN ('configuration', 'policy', 'budget')),
624
+ failure_phase TEXT NOT NULL,
625
+ failure_code TEXT NOT NULL,
626
+ opened_at INTEGER NOT NULL,
349
627
  updated_at INTEGER NOT NULL,
350
- FOREIGN KEY (run_id) REFERENCES automation_runs(id)
628
+ probe_token TEXT,
629
+ probe_lease_until INTEGER,
630
+ probe_task_id TEXT,
631
+ version INTEGER NOT NULL CHECK (version >= 1),
632
+ CHECK (
633
+ (state IN ('open', 'closed') AND probe_token IS NULL AND probe_lease_until IS NULL AND probe_task_id IS NULL)
634
+ OR (state = 'half-open' AND probe_token IS NOT NULL AND probe_lease_until IS NOT NULL AND probe_task_id IS NULL)
635
+ OR (state = 'probing' AND probe_token IS NOT NULL AND probe_lease_until IS NOT NULL AND probe_task_id IS NOT NULL)
636
+ ),
637
+ PRIMARY KEY (automation_id, definition_hash)
351
638
  ) STRICT;
352
- ${hasOutbox ? `
353
- INSERT INTO automation_evaluation_outbox(
354
- id, run_id, observation_kind, status, payload_json, attempt_count,
355
- next_attempt_at, last_failure_at, last_error_code, created_at, updated_at
356
- )
357
- SELECT id, run_id, observation_kind,
358
- CASE WHEN status = 'pending' THEN 'dead-letter' ELSE status END,
359
- payload_json,
360
- CASE WHEN status = 'pending' THEN 1 ELSE 0 END,
361
- updated_at,
362
- CASE WHEN status = 'pending' THEN updated_at ELSE NULL END,
363
- CASE WHEN status = 'pending' THEN 'legacy-unverifiable-provenance' ELSE NULL END,
364
- created_at, updated_at
365
- FROM automation_evaluation_outbox_v5;
366
- DROP TABLE automation_evaluation_outbox_v5;
367
- ` : ''}
368
- CREATE INDEX automation_evaluation_dispatch
369
- ON automation_evaluation_outbox(status, next_attempt_at, id);
370
- PRAGMA user_version = 6;
639
+ CREATE INDEX automation_open_circuits ON automation_circuits(state, updated_at, automation_id);
640
+ PRAGMA user_version = 7;
641
+ COMMIT;
642
+ `);
643
+ version = 7;
644
+ }
645
+ if (version === 7) {
646
+ repairCircuitPreviewV7(database);
647
+ database.exec(`
648
+ BEGIN IMMEDIATE;
649
+ ${incidentTableV9}
650
+ PRAGMA user_version = 9;
651
+ COMMIT;
652
+ `);
653
+ version = 9;
654
+ }
655
+ if (version === 8) {
656
+ const hasIncidents = database.prepare(`
657
+ SELECT 1 AS present FROM sqlite_master WHERE type = 'table' AND name = 'automation_incidents'
658
+ `).get() !== undefined;
659
+ if (!hasIncidents) {
660
+ database.exec(`
661
+ BEGIN IMMEDIATE;
662
+ ${incidentTableV9}
663
+ PRAGMA user_version = 9;
664
+ COMMIT;
665
+ `);
666
+ version = 9;
667
+ }
668
+ else {
669
+ database.exec(`
670
+ BEGIN IMMEDIATE;
671
+ DROP INDEX IF EXISTS automation_open_incidents;
672
+ DROP INDEX IF EXISTS automation_incident_alert_outbox;
673
+ ALTER TABLE automation_incidents RENAME TO automation_incidents_v8;
674
+ ${incidentTableV9}
675
+ INSERT INTO automation_incidents(
676
+ id, automation_id, definition_hash, stage, state, failure_class,
677
+ failure_phase, failure_code, side_effect_state, retryability,
678
+ notification_route_id, lifecycle_generation, presentation_revision,
679
+ alert_status, alert_ref, run_id, opened_at, updated_at, resolved_at, version
680
+ )
681
+ SELECT id, automation_id, definition_hash, stage, state, failure_class,
682
+ failure_phase, failure_code, side_effect_state, retryability,
683
+ notification_route_id, 1, version,
684
+ CASE WHEN state = 'open' THEN 'pending' ELSE 'suppressed' END,
685
+ NULL, run_id, opened_at, updated_at, resolved_at, version
686
+ FROM automation_incidents_v8;
687
+ DROP TABLE automation_incidents_v8;
688
+ PRAGMA user_version = 9;
689
+ COMMIT;
690
+ `);
691
+ version = 9;
692
+ }
693
+ }
694
+ if (version === 9) {
695
+ database.exec(`
696
+ BEGIN IMMEDIATE;
697
+ ${growthTablesV10}
698
+ PRAGMA user_version = 10;
371
699
  COMMIT;
372
700
  `);
373
701
  }
package/lib/sqlite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"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"}