@dsh-enhanced/assistant-evolution 0.1.6 → 0.1.12

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/lib/sqlite.js CHANGED
@@ -1,7 +1,7 @@
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 evolutionSchemaVersion = 3;
4
+ export const evolutionSchemaVersion = 12;
5
5
  export class EvolutionDatabaseError extends Error {
6
6
  code;
7
7
  constructor(code, message) {
@@ -87,6 +87,430 @@ function migrateV2ToV3(database) {
87
87
  PRAGMA user_version = 3;
88
88
  `);
89
89
  }
90
+ function migrateV3ToV4(database) {
91
+ database.exec(`
92
+ CREATE TABLE evolution_autonomous_rollbacks (
93
+ idempotency_key TEXT PRIMARY KEY,
94
+ scope_key TEXT NOT NULL,
95
+ rule_id TEXT NOT NULL,
96
+ expected_version INTEGER NOT NULL CHECK (expected_version >= 1),
97
+ result_version INTEGER NOT NULL CHECK (result_version = expected_version + 1),
98
+ risk TEXT NOT NULL CHECK (risk = 'low'),
99
+ reason TEXT NOT NULL,
100
+ evaluation_failures INTEGER NOT NULL CHECK (evaluation_failures >= 0),
101
+ evaluation_total INTEGER NOT NULL CHECK (
102
+ evaluation_total > 0 AND evaluation_failures <= evaluation_total),
103
+ baseline_failures INTEGER NOT NULL CHECK (baseline_failures >= 0),
104
+ baseline_total INTEGER NOT NULL CHECK (
105
+ baseline_total > 0 AND baseline_failures <= baseline_total),
106
+ evidence_digest TEXT NOT NULL CHECK (length(evidence_digest) = 64),
107
+ evidence_total INTEGER NOT NULL CHECK (evidence_total = evaluation_total),
108
+ sample_episode_ids_json TEXT NOT NULL CHECK (
109
+ json_valid(sample_episode_ids_json) AND json_type(sample_episode_ids_json) = 'array'),
110
+ occurred_at INTEGER NOT NULL,
111
+ UNIQUE(scope_key, rule_id, expected_version),
112
+ FOREIGN KEY(rule_id) REFERENCES evolution_rules(id)
113
+ ) STRICT;
114
+ CREATE INDEX evolution_autonomous_rollbacks_occurred
115
+ ON evolution_autonomous_rollbacks(occurred_at);
116
+
117
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '4')
118
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
119
+ PRAGMA user_version = 4;
120
+ `);
121
+ }
122
+ function migrateV4ToV5(database) {
123
+ database.exec(`
124
+ ALTER TABLE evolution_episodes ADD COLUMN evidence_kind TEXT NOT NULL
125
+ DEFAULT 'legacy-unknown'
126
+ CHECK (evidence_kind IN ('operational', 'objective', 'verification', 'legacy-unknown'));
127
+ ALTER TABLE evolution_episodes ADD COLUMN evidence_ref TEXT;
128
+ ALTER TABLE evolution_episodes ADD COLUMN learning_eligible INTEGER NOT NULL DEFAULT 0
129
+ CHECK (learning_eligible IN (0, 1))
130
+ CHECK (learning_eligible = 0 OR (
131
+ trust = 'trusted'
132
+ AND evidence_kind IN ('objective', 'verification')
133
+ AND evidence_ref IS NOT NULL));
134
+
135
+ -- A v4 trusted automation row proved only that execution stopped in a
136
+ -- binary state. It did not prove objective correctness. Keep every row for
137
+ -- audit, but quarantine it from all learning projections.
138
+ UPDATE evolution_episodes
139
+ SET evidence_kind = 'legacy-unknown', evidence_ref = NULL, learning_eligible = 0;
140
+
141
+ -- Every pre-v5 pending mutation was computed from evidence that did not
142
+ -- distinguish execution status from objective quality. A later approval
143
+ -- must not activate that stale conclusion after the evidence quarantine.
144
+ UPDATE evolution_proposals
145
+ SET status = 'conflicted', version = version + 1
146
+ WHERE status = 'pending';
147
+
148
+ DROP INDEX IF EXISTS evolution_episodes_adoption;
149
+ DROP INDEX IF EXISTS evolution_episodes_evaluation;
150
+ CREATE INDEX evolution_episodes_adoption
151
+ ON evolution_episodes(
152
+ scope_key, situation, learning_eligible, rule_id, occurred_at DESC, id DESC);
153
+ CREATE INDEX evolution_episodes_evaluation
154
+ ON evolution_episodes(
155
+ rule_id, guidance_version, learning_eligible, occurred_at DESC, id DESC);
156
+
157
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '5')
158
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
159
+ PRAGMA user_version = 5;
160
+ `);
161
+ }
162
+ function migrateV5ToV6(database) {
163
+ database.exec(`
164
+ -- v5 made immutable Evaluation references mandatory, but caller-owned
165
+ -- idempotency keys could still alias the same result into several rows.
166
+ -- Retain the earliest deterministic row and quarantine every duplicate so
167
+ -- historical ledgers migrate before the uniqueness constraint is created.
168
+ CREATE TEMP TABLE evolution_v6_duplicate_quality AS
169
+ WITH ranked AS (
170
+ SELECT id, scope_key,
171
+ row_number() OVER (
172
+ PARTITION BY scope_key, evidence_ref
173
+ ORDER BY occurred_at ASC, id ASC
174
+ ) AS duplicate_rank
175
+ FROM evolution_episodes
176
+ WHERE learning_eligible = 1
177
+ AND evidence_kind IN ('objective', 'verification')
178
+ AND evidence_ref IS NOT NULL
179
+ )
180
+ SELECT id, scope_key FROM ranked WHERE duplicate_rank > 1;
181
+
182
+ UPDATE evolution_episodes
183
+ SET evidence_kind = 'legacy-unknown', evidence_ref = NULL, learning_eligible = 0
184
+ WHERE id IN (SELECT id FROM evolution_v6_duplicate_quality);
185
+
186
+ -- A pending mutation in an affected scope may have been computed from an
187
+ -- inflated sample. Preserve it for audit but prevent delayed activation.
188
+ UPDATE evolution_proposals
189
+ SET status = 'conflicted', version = version + 1
190
+ WHERE status = 'pending'
191
+ AND scope_key IN (SELECT DISTINCT scope_key FROM evolution_v6_duplicate_quality);
192
+
193
+ DROP TABLE evolution_v6_duplicate_quality;
194
+
195
+ CREATE UNIQUE INDEX evolution_episodes_quality_evidence_identity
196
+ ON evolution_episodes(scope_key, evidence_ref)
197
+ WHERE learning_eligible = 1;
198
+
199
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '6')
200
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
201
+ PRAGMA user_version = 6;
202
+ `);
203
+ }
204
+ function migrateV6ToV7(database) {
205
+ database.exec(`
206
+ -- Every pre-v7 quality row came through the retired caller-controlled
207
+ -- projection seam and cannot be rebound to an authoritative Evaluation
208
+ -- receipt after the fact. Preserve it for audit, but revoke learning
209
+ -- eligibility and invalidate pending conclusions derived from it.
210
+ CREATE TEMP TABLE evolution_v7_legacy_quality_scopes AS
211
+ SELECT DISTINCT scope_key FROM evolution_episodes WHERE learning_eligible = 1;
212
+
213
+ UPDATE evolution_episodes
214
+ SET evidence_kind = 'legacy-unknown', evidence_ref = NULL, learning_eligible = 0
215
+ WHERE learning_eligible = 1;
216
+ UPDATE evolution_proposals
217
+ SET status = 'conflicted', version = version + 1
218
+ WHERE status = 'pending'
219
+ AND scope_key IN (SELECT scope_key FROM evolution_v7_legacy_quality_scopes);
220
+ DROP TABLE evolution_v7_legacy_quality_scopes;
221
+
222
+ -- Evaluation is an independent provenance source. Rebuild the table because
223
+ -- SQLite cannot widen an existing CHECK constraint in place.
224
+ ALTER TABLE evolution_episodes RENAME TO evolution_episodes_v6;
225
+ DROP INDEX IF EXISTS evolution_episodes_adoption;
226
+ DROP INDEX IF EXISTS evolution_episodes_evaluation;
227
+ DROP INDEX IF EXISTS evolution_episodes_quality_evidence_identity;
228
+
229
+ CREATE TABLE evolution_episodes (
230
+ id TEXT PRIMARY KEY,
231
+ idempotency_key TEXT NOT NULL UNIQUE,
232
+ situation TEXT NOT NULL,
233
+ outcome TEXT NOT NULL CHECK (outcome IN ('succeeded', 'failed')),
234
+ detail TEXT NOT NULL,
235
+ source TEXT NOT NULL CHECK (source IN ('automation', 'evaluation', 'foreground')),
236
+ scope_key TEXT NOT NULL,
237
+ trust TEXT NOT NULL CHECK (trust IN ('trusted', 'self-reported', 'legacy')),
238
+ evidence_kind TEXT NOT NULL CHECK (
239
+ evidence_kind IN ('operational', 'objective', 'verification', 'legacy-unknown')),
240
+ evidence_ref TEXT,
241
+ learning_eligible INTEGER NOT NULL CHECK (learning_eligible IN (0, 1)),
242
+ rule_id TEXT,
243
+ guidance_version INTEGER CHECK (guidance_version IS NULL OR guidance_version >= 1),
244
+ claimed_rule_id TEXT,
245
+ occurred_at INTEGER NOT NULL,
246
+ CHECK (learning_eligible = 0 OR (
247
+ source = 'evaluation'
248
+ AND
249
+ trust = 'trusted'
250
+ AND evidence_kind IN ('objective', 'verification')
251
+ AND evidence_ref IS NOT NULL))
252
+ ) STRICT;
253
+
254
+ INSERT INTO evolution_episodes(
255
+ id, idempotency_key, situation, outcome, detail, source, scope_key,
256
+ trust, evidence_kind, evidence_ref, learning_eligible,
257
+ rule_id, guidance_version, claimed_rule_id, occurred_at)
258
+ SELECT
259
+ id, idempotency_key, situation, outcome, detail, source, scope_key,
260
+ trust, evidence_kind, evidence_ref, learning_eligible,
261
+ rule_id, guidance_version, claimed_rule_id, occurred_at
262
+ FROM evolution_episodes_v6;
263
+ DROP TABLE evolution_episodes_v6;
264
+
265
+ CREATE INDEX evolution_episodes_adoption
266
+ ON evolution_episodes(
267
+ scope_key, situation, learning_eligible, rule_id, occurred_at DESC, id DESC);
268
+ CREATE INDEX evolution_episodes_evaluation
269
+ ON evolution_episodes(
270
+ rule_id, guidance_version, learning_eligible, occurred_at DESC, id DESC);
271
+ CREATE UNIQUE INDEX evolution_episodes_quality_evidence_identity
272
+ ON evolution_episodes(scope_key, evidence_ref)
273
+ WHERE learning_eligible = 1;
274
+
275
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '7')
276
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
277
+ PRAGMA user_version = 7;
278
+ `);
279
+ }
280
+ function migrateV7ToV8(database) {
281
+ database.exec(`
282
+ ALTER TABLE evolution_episodes ADD COLUMN learning_subject_ref TEXT;
283
+
284
+ -- v7 recorded only the Evaluation identity. For an Automation objective it
285
+ -- therefore cannot prove whether several Evaluation rows assessed one run.
286
+ -- Preserve those rows for audit, but quarantine every old learning row and
287
+ -- every pending conclusion that may have counted it more than once.
288
+ CREATE TEMP TABLE evolution_v8_legacy_learning_scopes AS
289
+ SELECT DISTINCT scope_key FROM evolution_episodes WHERE learning_eligible = 1;
290
+ UPDATE evolution_episodes
291
+ SET evidence_kind = 'legacy-unknown', evidence_ref = NULL,
292
+ learning_subject_ref = NULL, learning_eligible = 0
293
+ WHERE learning_eligible = 1;
294
+ UPDATE evolution_proposals
295
+ SET status = 'conflicted', version = version + 1
296
+ WHERE status = 'pending'
297
+ AND scope_key IN (SELECT scope_key FROM evolution_v8_legacy_learning_scopes);
298
+ DROP TABLE evolution_v8_legacy_learning_scopes;
299
+
300
+ CREATE UNIQUE INDEX evolution_episodes_learning_subject_identity
301
+ ON evolution_episodes(scope_key, learning_subject_ref)
302
+ WHERE learning_eligible = 1;
303
+
304
+ -- SQLite cannot extend the v7 table CHECK in place. These triggers make the
305
+ -- migrated schema enforce the same invariant as a fresh v8 database.
306
+ CREATE TRIGGER evolution_episodes_learning_subject_insert
307
+ BEFORE INSERT ON evolution_episodes
308
+ WHEN (NEW.learning_eligible = 1 AND NEW.learning_subject_ref IS NULL)
309
+ OR (NEW.learning_eligible = 0 AND NEW.learning_subject_ref IS NOT NULL)
310
+ BEGIN
311
+ SELECT RAISE(ABORT, 'learning subject eligibility mismatch');
312
+ END;
313
+ CREATE TRIGGER evolution_episodes_learning_subject_update
314
+ BEFORE UPDATE OF learning_eligible, learning_subject_ref ON evolution_episodes
315
+ WHEN (NEW.learning_eligible = 1 AND NEW.learning_subject_ref IS NULL)
316
+ OR (NEW.learning_eligible = 0 AND NEW.learning_subject_ref IS NOT NULL)
317
+ BEGIN
318
+ SELECT RAISE(ABORT, 'learning subject eligibility mismatch');
319
+ END;
320
+
321
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '8')
322
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
323
+ PRAGMA user_version = 8;
324
+ `);
325
+ }
326
+ const taskLearningProjectionSchema = `
327
+ CREATE TABLE evolution_task_learning_state (
328
+ scope_key TEXT NOT NULL,
329
+ scope_watermark INTEGER NOT NULL CHECK (scope_watermark >= 1),
330
+ subject_kind TEXT NOT NULL CHECK (subject_kind IN ('automation-run', 'outcome')),
331
+ subject_ref TEXT NOT NULL,
332
+ version INTEGER NOT NULL CHECK (version >= 1),
333
+ digest TEXT NOT NULL CHECK (length(digest) = 64),
334
+ disposition TEXT NOT NULL CHECK (disposition IN ('upsert', 'retract')),
335
+ situation TEXT NOT NULL,
336
+ episode_id TEXT,
337
+ updated_at INTEGER NOT NULL,
338
+ PRIMARY KEY(scope_key, subject_kind, subject_ref),
339
+ CHECK ((disposition = 'upsert' AND episode_id IS NOT NULL)
340
+ OR (disposition = 'retract' AND episode_id IS NULL)),
341
+ FOREIGN KEY(episode_id) REFERENCES evolution_episodes(id) ON DELETE RESTRICT
342
+ ) STRICT, WITHOUT ROWID;
343
+ CREATE INDEX evolution_task_learning_state_situation
344
+ ON evolution_task_learning_state(scope_key, situation, disposition, updated_at DESC);
345
+
346
+ CREATE TABLE evolution_task_learning_revisions (
347
+ scope_key TEXT NOT NULL,
348
+ scope_watermark INTEGER NOT NULL CHECK (scope_watermark >= 1),
349
+ subject_kind TEXT NOT NULL CHECK (subject_kind IN ('automation-run', 'outcome')),
350
+ subject_ref TEXT NOT NULL,
351
+ version INTEGER NOT NULL CHECK (version >= 1),
352
+ digest TEXT NOT NULL CHECK (length(digest) = 64),
353
+ disposition TEXT NOT NULL CHECK (disposition IN ('upsert', 'retract')),
354
+ situation TEXT NOT NULL,
355
+ episode_id TEXT,
356
+ applied_at INTEGER NOT NULL,
357
+ PRIMARY KEY(scope_key, subject_kind, subject_ref, version),
358
+ CHECK ((disposition = 'upsert' AND episode_id IS NOT NULL)
359
+ OR (disposition = 'retract' AND episode_id IS NULL)),
360
+ FOREIGN KEY(episode_id) REFERENCES evolution_episodes(id) ON DELETE RESTRICT
361
+ ) STRICT, WITHOUT ROWID;
362
+ CREATE INDEX evolution_task_learning_revisions_applied
363
+ ON evolution_task_learning_revisions(applied_at, scope_key, subject_kind, subject_ref);
364
+ `;
365
+ const supervisedGrowthAnalystSchema = `
366
+ CREATE TABLE evolution_supervised_analyst_reviews (
367
+ review_token TEXT PRIMARY KEY,
368
+ scope_key TEXT NOT NULL,
369
+ occurrence_id TEXT NOT NULL,
370
+ contract_version TEXT NOT NULL CHECK (contract_version = 'supervised-growth-analyst/v1'),
371
+ situation TEXT NOT NULL,
372
+ failures INTEGER NOT NULL CHECK (failures >= 0),
373
+ total INTEGER NOT NULL CHECK (total > 0 AND failures <= total),
374
+ evidence_digest TEXT NOT NULL CHECK (length(evidence_digest) = 64),
375
+ evidence_total INTEGER NOT NULL CHECK (evidence_total = total),
376
+ evidence_window INTEGER NOT NULL CHECK (evidence_window >= evidence_total),
377
+ sample_episode_ids_json TEXT NOT NULL CHECK (
378
+ json_valid(sample_episode_ids_json)
379
+ AND json_type(sample_episode_ids_json) = 'array'
380
+ AND json_array_length(sample_episode_ids_json) BETWEEN 1 AND 50
381
+ AND json_array_length(sample_episode_ids_json) <= evidence_total),
382
+ evidence_json TEXT NOT NULL CHECK (
383
+ json_valid(evidence_json) AND json_type(evidence_json) = 'array'),
384
+ scope_watermark INTEGER NOT NULL CHECK (scope_watermark >= 1),
385
+ task_revisions_json TEXT NOT NULL CHECK (
386
+ json_valid(task_revisions_json) AND json_type(task_revisions_json) = 'array'),
387
+ proposal_id TEXT,
388
+ created_at INTEGER NOT NULL,
389
+ proposed_at INTEGER,
390
+ UNIQUE(scope_key, occurrence_id),
391
+ FOREIGN KEY(proposal_id) REFERENCES evolution_proposals(id) ON DELETE RESTRICT
392
+ ) STRICT;
393
+ CREATE INDEX evolution_supervised_analyst_reviews_proposal
394
+ ON evolution_supervised_analyst_reviews(proposal_id)
395
+ WHERE proposal_id IS NOT NULL;
396
+ `;
397
+ const applicationReceiptSchema = `
398
+ CREATE TABLE evolution_application_receipts (
399
+ local_proposal_id TEXT PRIMARY KEY,
400
+ policy_proposal_id TEXT NOT NULL UNIQUE,
401
+ application_status TEXT NOT NULL CHECK (
402
+ application_status IN ('applied', 'conflicted', 'expired', 'rejected')),
403
+ operation TEXT NOT NULL CHECK (operation IN ('adopt', 'owner-undo', 'retire')),
404
+ terminal_at INTEGER NOT NULL,
405
+ receipt_digest TEXT NOT NULL UNIQUE CHECK (length(receipt_digest) = 64),
406
+ revision INTEGER NOT NULL CHECK (revision >= 2),
407
+ rule_id TEXT,
408
+ resulting_rule_version INTEGER CHECK (
409
+ resulting_rule_version IS NULL OR resulting_rule_version >= 1),
410
+ rule_status TEXT CHECK (rule_status IS NULL OR rule_status IN ('active', 'retired')),
411
+ CHECK (application_status <> 'applied' OR (
412
+ rule_id IS NOT NULL AND resulting_rule_version IS NOT NULL AND rule_status IS NOT NULL)),
413
+ FOREIGN KEY(local_proposal_id) REFERENCES evolution_proposals(id) ON DELETE RESTRICT
414
+ ) STRICT;
415
+
416
+ CREATE TABLE evolution_application_outbox (
417
+ local_proposal_id TEXT PRIMARY KEY,
418
+ state TEXT NOT NULL CHECK (state IN ('pending', 'published')),
419
+ attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
420
+ updated_at INTEGER NOT NULL,
421
+ published_at INTEGER,
422
+ last_error TEXT,
423
+ FOREIGN KEY(local_proposal_id)
424
+ REFERENCES evolution_application_receipts(local_proposal_id) ON DELETE RESTRICT
425
+ ) STRICT, WITHOUT ROWID;
426
+ CREATE INDEX evolution_application_outbox_pending
427
+ ON evolution_application_outbox(state, updated_at, local_proposal_id);
428
+ `;
429
+ function migrateV8ToV9(database) {
430
+ database.exec(`
431
+ -- v8 rows were projected from a raw immutable Evaluation outcome. They
432
+ -- cannot represent a later owner override or objective conflict, so they
433
+ -- must not remain votes once the canonical task projection becomes the
434
+ -- only source. Evaluation v5 requeues retained tasks and repopulates this
435
+ -- ledger through the versioned seam after startup.
436
+ CREATE TEMP TABLE evolution_v9_legacy_learning_scopes AS
437
+ SELECT DISTINCT scope_key FROM evolution_episodes WHERE learning_eligible = 1;
438
+ UPDATE evolution_episodes
439
+ SET evidence_kind = 'legacy-unknown', evidence_ref = NULL,
440
+ learning_subject_ref = NULL, learning_eligible = 0
441
+ WHERE learning_eligible = 1;
442
+ UPDATE evolution_proposals
443
+ SET status = 'conflicted', version = version + 1
444
+ WHERE status = 'pending'
445
+ AND scope_key IN (SELECT scope_key FROM evolution_v9_legacy_learning_scopes);
446
+ DROP TABLE evolution_v9_legacy_learning_scopes;
447
+
448
+ ${taskLearningProjectionSchema}
449
+
450
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '9')
451
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
452
+ PRAGMA user_version = 9;
453
+ `);
454
+ }
455
+ function migrateV9ToV10(database) {
456
+ database.exec(`
457
+ ${supervisedGrowthAnalystSchema}
458
+
459
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '10')
460
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
461
+ PRAGMA user_version = 10;
462
+ `);
463
+ }
464
+ function migrateV10ToV11(database) {
465
+ database.exec(`
466
+ ${applicationReceiptSchema}
467
+
468
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '11')
469
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
470
+ PRAGMA user_version = 11;
471
+ `);
472
+ }
473
+ function migrateV11ToV12(database) {
474
+ const hasColumn = (table, column) => database
475
+ .prepare(`SELECT name FROM pragma_table_info(?) WHERE name = ?`)
476
+ .get(table, column) !== undefined;
477
+ if (!hasColumn('evolution_task_learning_state', 'scope_watermark')) {
478
+ database.exec(`ALTER TABLE evolution_task_learning_state
479
+ ADD COLUMN scope_watermark INTEGER NOT NULL DEFAULT 0 CHECK (scope_watermark >= 0)`);
480
+ }
481
+ if (!hasColumn('evolution_task_learning_revisions', 'scope_watermark')) {
482
+ database.exec(`ALTER TABLE evolution_task_learning_revisions
483
+ ADD COLUMN scope_watermark INTEGER NOT NULL DEFAULT 0 CHECK (scope_watermark >= 0)`);
484
+ }
485
+ if (!hasColumn('evolution_supervised_analyst_reviews', 'scope_watermark')) {
486
+ database.exec(`ALTER TABLE evolution_supervised_analyst_reviews
487
+ ADD COLUMN scope_watermark INTEGER NOT NULL DEFAULT 0 CHECK (scope_watermark >= 0)`);
488
+ }
489
+ if (!hasColumn('evolution_supervised_analyst_reviews', 'task_revisions_json')) {
490
+ database.exec(`ALTER TABLE evolution_supervised_analyst_reviews
491
+ ADD COLUMN task_revisions_json TEXT NOT NULL DEFAULT '[]'
492
+ CHECK (json_valid(task_revisions_json) AND json_type(task_revisions_json) = 'array')`);
493
+ }
494
+ database.exec(`
495
+ CREATE TABLE IF NOT EXISTS evolution_scope_learning_watermarks (
496
+ scope_key TEXT PRIMARY KEY,
497
+ watermark INTEGER NOT NULL CHECK (watermark >= 1),
498
+ updated_at INTEGER NOT NULL
499
+ ) STRICT, WITHOUT ROWID;
500
+
501
+ -- No pre-v12 pending proposal froze the authoritative Evaluation scope
502
+ -- watermark and complete task tuple. Preserve it for audit, but never let a
503
+ -- later approval apply it. Attached rows receive terminal receipts during
504
+ -- the normal constructor backfill.
505
+ UPDATE evolution_proposals
506
+ SET status = 'conflicted', version = version + 1
507
+ WHERE status = 'pending';
508
+
509
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '12')
510
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value;
511
+ PRAGMA user_version = 12;
512
+ `);
513
+ }
90
514
  function createCurrentSchema(database) {
91
515
  database.exec(`
92
516
  CREATE TABLE schema_meta (
@@ -102,19 +526,41 @@ function createCurrentSchema(database) {
102
526
  situation TEXT NOT NULL,
103
527
  outcome TEXT NOT NULL CHECK (outcome IN ('succeeded', 'failed')),
104
528
  detail TEXT NOT NULL,
105
- source TEXT NOT NULL CHECK (source IN ('automation', 'foreground')),
529
+ source TEXT NOT NULL CHECK (source IN ('automation', 'evaluation', 'foreground')),
106
530
  scope_key TEXT NOT NULL,
107
531
  trust TEXT NOT NULL CHECK (trust IN ('trusted', 'self-reported', 'legacy')),
532
+ evidence_kind TEXT NOT NULL CHECK (
533
+ evidence_kind IN ('operational', 'objective', 'verification', 'legacy-unknown')),
534
+ evidence_ref TEXT,
535
+ learning_subject_ref TEXT,
536
+ learning_eligible INTEGER NOT NULL CHECK (learning_eligible IN (0, 1)),
108
537
  rule_id TEXT,
109
538
  guidance_version INTEGER CHECK (guidance_version IS NULL OR guidance_version >= 1),
110
539
  claimed_rule_id TEXT,
111
- occurred_at INTEGER NOT NULL
540
+ occurred_at INTEGER NOT NULL,
541
+ CHECK ((learning_eligible = 0 AND learning_subject_ref IS NULL) OR (
542
+ learning_eligible = 1
543
+ AND learning_subject_ref IS NOT NULL
544
+ AND
545
+ source = 'evaluation'
546
+ AND
547
+ trust = 'trusted'
548
+ AND evidence_kind IN ('objective', 'verification')
549
+ AND evidence_ref IS NOT NULL))
112
550
  ) STRICT;
113
551
 
114
552
  CREATE INDEX evolution_episodes_adoption
115
- ON evolution_episodes(scope_key, situation, trust, rule_id, occurred_at DESC, id DESC);
553
+ ON evolution_episodes(
554
+ scope_key, situation, learning_eligible, rule_id, occurred_at DESC, id DESC);
116
555
  CREATE INDEX evolution_episodes_evaluation
117
- ON evolution_episodes(rule_id, trust, occurred_at DESC, id DESC);
556
+ ON evolution_episodes(
557
+ rule_id, guidance_version, learning_eligible, occurred_at DESC, id DESC);
558
+ CREATE UNIQUE INDEX evolution_episodes_quality_evidence_identity
559
+ ON evolution_episodes(scope_key, evidence_ref)
560
+ WHERE learning_eligible = 1;
561
+ CREATE UNIQUE INDEX evolution_episodes_learning_subject_identity
562
+ ON evolution_episodes(scope_key, learning_subject_ref)
563
+ WHERE learning_eligible = 1;
118
564
 
119
565
  CREATE TABLE evolution_rules (
120
566
  id TEXT PRIMARY KEY,
@@ -176,8 +622,45 @@ function createCurrentSchema(database) {
176
622
  CREATE INDEX evolution_guidance_exposures_lookup
177
623
  ON evolution_guidance_exposures(session_id, scope_key, situation, exposed_at, rule_id);
178
624
 
179
- INSERT INTO schema_meta(key, value) VALUES ('schema-version', '3');
180
- PRAGMA user_version = 3;
625
+ CREATE TABLE evolution_autonomous_rollbacks (
626
+ idempotency_key TEXT PRIMARY KEY,
627
+ scope_key TEXT NOT NULL,
628
+ rule_id TEXT NOT NULL,
629
+ expected_version INTEGER NOT NULL CHECK (expected_version >= 1),
630
+ result_version INTEGER NOT NULL CHECK (result_version = expected_version + 1),
631
+ risk TEXT NOT NULL CHECK (risk = 'low'),
632
+ reason TEXT NOT NULL,
633
+ evaluation_failures INTEGER NOT NULL CHECK (evaluation_failures >= 0),
634
+ evaluation_total INTEGER NOT NULL CHECK (
635
+ evaluation_total > 0 AND evaluation_failures <= evaluation_total),
636
+ baseline_failures INTEGER NOT NULL CHECK (baseline_failures >= 0),
637
+ baseline_total INTEGER NOT NULL CHECK (
638
+ baseline_total > 0 AND baseline_failures <= baseline_total),
639
+ evidence_digest TEXT NOT NULL CHECK (length(evidence_digest) = 64),
640
+ evidence_total INTEGER NOT NULL CHECK (evidence_total = evaluation_total),
641
+ sample_episode_ids_json TEXT NOT NULL CHECK (
642
+ json_valid(sample_episode_ids_json) AND json_type(sample_episode_ids_json) = 'array'),
643
+ occurred_at INTEGER NOT NULL,
644
+ UNIQUE(scope_key, rule_id, expected_version),
645
+ FOREIGN KEY(rule_id) REFERENCES evolution_rules(id)
646
+ ) STRICT;
647
+ CREATE INDEX evolution_autonomous_rollbacks_occurred
648
+ ON evolution_autonomous_rollbacks(occurred_at);
649
+
650
+ ${taskLearningProjectionSchema}
651
+
652
+ CREATE TABLE evolution_scope_learning_watermarks (
653
+ scope_key TEXT PRIMARY KEY,
654
+ watermark INTEGER NOT NULL CHECK (watermark >= 1),
655
+ updated_at INTEGER NOT NULL
656
+ ) STRICT, WITHOUT ROWID;
657
+
658
+ ${supervisedGrowthAnalystSchema}
659
+
660
+ ${applicationReceiptSchema}
661
+
662
+ INSERT INTO schema_meta(key, value) VALUES ('schema-version', '12');
663
+ PRAGMA user_version = 12;
181
664
  `);
182
665
  }
183
666
  /** Serialize every schema transition and re-read the version after the lock. */
@@ -199,6 +682,24 @@ function migrate(database) {
199
682
  migrateV1ToV2(database);
200
683
  else if (version === 2)
201
684
  migrateV2ToV3(database);
685
+ else if (version === 3)
686
+ migrateV3ToV4(database);
687
+ else if (version === 4)
688
+ migrateV4ToV5(database);
689
+ else if (version === 5)
690
+ migrateV5ToV6(database);
691
+ else if (version === 6)
692
+ migrateV6ToV7(database);
693
+ else if (version === 7)
694
+ migrateV7ToV8(database);
695
+ else if (version === 8)
696
+ migrateV8ToV9(database);
697
+ else if (version === 9)
698
+ migrateV9ToV10(database);
699
+ else if (version === 10)
700
+ migrateV10ToV11(database);
701
+ else if (version === 11)
702
+ migrateV11ToV12(database);
202
703
  version = schemaVersion(database);
203
704
  }
204
705
  database.exec('COMMIT');
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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"}