ai_co_discuss 0.3.46 → 0.3.49
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/.agents/skills/discuss-host/SKILL.md +1 -0
- package/.agents/skills/discuss-host/references/discussion.md +113 -113
- package/.agents/skills/discuss-host/references/free.md +36 -34
- package/.agents/skills/discuss-host/references/goal.md +35 -0
- package/.agents/skills/discuss-participant/SKILL.md +1 -0
- package/.agents/skills/workflow-creator/SKILL.md +2 -2
- package/README.md +3 -1
- package/backend/admin.py +104 -35
- package/backend/free_room.py +2170 -2136
- package/backend/goal_room.py +358 -0
- package/backend/mode_room.py +105 -0
- package/backend/schema.sql +1593 -1510
- package/backend/server.py +2636 -2555
- package/backend/session_room.py +1180 -1148
- package/docs/THIRD_PARTY_NOTICES.md +1293 -1264
- package/docs/deployment.md +5 -1
- package/docs/en/workflow.md +15 -1
- package/docs/runner.md +28 -7
- package/docs/workflow.md +15 -1
- package/package.json +3 -2
- package/runner/adapters/api.mjs +333 -313
- package/runner/adapters/claude.mjs +12 -16
- package/runner/admin_account.mjs +12 -19
- package/runner/device_auth.mjs +369 -0
- package/runner/discuss.py +1208 -1125
- package/runner/discussion_launch.mjs +107 -12
- package/runner/discussion_service.mjs +25 -1
- package/runner/expert_prompts.mjs +132 -132
- package/runner/free_runner.mjs +982 -910
- package/runner/pinyin_table.mjs +406 -0
- package/runner/project_files.mjs +52 -3
- package/runner/relay_channel.mjs +51 -7
- package/runner/remote_launch.mjs +221 -235
- package/runner/remote_policy.mjs +156 -0
- package/runner/scheduler.mjs +459 -429
- package/runner/stt.mjs +2 -2
- package/runner/tts.mjs +74 -113
- package/runner/tts_providers.mjs +205 -0
- package/runner/webauthn.mjs +155 -0
- package/runner/workflows.mjs +371 -348
- package/web/app.js +355 -51
- package/web/modern.css +1 -1
- package/web/modern.js +5764 -3816
package/backend/schema.sql
CHANGED
|
@@ -1,1510 +1,1593 @@
|
|
|
1
|
-
CREATE TABLE IF NOT EXISTS rooms (
|
|
2
|
-
id TEXT PRIMARY KEY, title TEXT NOT NULL, goal TEXT NOT NULL,
|
|
3
|
-
state_text TEXT NOT NULL DEFAULT '', state_until INTEGER NOT NULL DEFAULT 0,
|
|
4
|
-
created_at TEXT NOT NULL
|
|
5
|
-
);
|
|
6
|
-
CREATE TABLE IF NOT EXISTS room_directory (
|
|
7
|
-
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
8
|
-
position INTEGER NOT NULL DEFAULT 0,
|
|
9
|
-
archived INTEGER NOT NULL DEFAULT 0 CHECK (archived IN (0,1))
|
|
10
|
-
);
|
|
11
|
-
INSERT OR IGNORE INTO room_directory (room_id,position)
|
|
12
|
-
SELECT id,ROW_NUMBER() OVER (ORDER BY created_at,id) FROM rooms;
|
|
13
|
-
CREATE TRIGGER IF NOT EXISTS add_room_to_directory AFTER INSERT ON rooms
|
|
14
|
-
BEGIN
|
|
15
|
-
INSERT INTO room_directory (room_id,position)
|
|
16
|
-
VALUES (NEW.id,(SELECT COALESCE(MAX(position),0)+1 FROM room_directory));
|
|
17
|
-
END;
|
|
18
|
-
CREATE TABLE IF NOT EXISTS topic_folders (
|
|
19
|
-
id TEXT PRIMARY KEY, name TEXT NOT NULL, position INTEGER NOT NULL DEFAULT 0
|
|
20
|
-
);
|
|
21
|
-
-- Site-wide preferences of the person managing the site; `last_room` is the room they last opened on any device.
|
|
22
|
-
CREATE TABLE IF NOT EXISTS site_preferences (
|
|
23
|
-
key TEXT PRIMARY KEY,
|
|
24
|
-
value TEXT NOT NULL
|
|
25
|
-
);
|
|
26
|
-
CREATE TABLE IF NOT EXISTS directory_settings (
|
|
27
|
-
id INTEGER PRIMARY KEY CHECK (id=1),
|
|
28
|
-
uncategorized_position INTEGER CHECK (uncategorized_position>=0)
|
|
29
|
-
);
|
|
30
|
-
CREATE TABLE IF NOT EXISTS room_folder_assignments (
|
|
31
|
-
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
32
|
-
folder_id TEXT REFERENCES topic_folders(id) ON DELETE SET NULL
|
|
33
|
-
);
|
|
34
|
-
INSERT OR IGNORE INTO room_folder_assignments (room_id,folder_id)
|
|
35
|
-
SELECT id,NULL FROM rooms;
|
|
36
|
-
CREATE TRIGGER IF NOT EXISTS add_room_to_folder_assignments AFTER INSERT ON rooms
|
|
37
|
-
BEGIN
|
|
38
|
-
INSERT INTO room_folder_assignments (room_id,folder_id) VALUES (NEW.id,NULL);
|
|
39
|
-
END;
|
|
40
|
-
CREATE TABLE IF NOT EXISTS room_creations (
|
|
41
|
-
submission_id TEXT PRIMARY KEY,
|
|
42
|
-
room_id TEXT NOT NULL UNIQUE REFERENCES rooms(id),
|
|
43
|
-
request_text TEXT NOT NULL
|
|
44
|
-
);
|
|
45
|
-
CREATE TABLE IF NOT EXISTS room_user_requests (
|
|
46
|
-
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
47
|
-
text TEXT NOT NULL DEFAULT ''
|
|
48
|
-
);
|
|
49
|
-
CREATE TABLE IF NOT EXISTS room_briefs (
|
|
50
|
-
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
51
|
-
text TEXT NOT NULL, until INTEGER NOT NULL, updated_at TEXT NOT NULL
|
|
52
|
-
);
|
|
53
|
-
CREATE TABLE IF NOT EXISTS messages (
|
|
54
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT, room_id TEXT NOT NULL REFERENCES rooms(id),
|
|
55
|
-
author TEXT NOT NULL, text TEXT NOT NULL, reply_to INTEGER REFERENCES messages(id),
|
|
56
|
-
source TEXT NOT NULL, submission_id TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
57
|
-
UNIQUE(room_id, submission_id)
|
|
58
|
-
);
|
|
59
|
-
CREATE INDEX IF NOT EXISTS messages_room ON messages(room_id, id);
|
|
60
|
-
CREATE TABLE IF NOT EXISTS attachments (
|
|
61
|
-
id TEXT PRIMARY KEY, room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
62
|
-
message_id INTEGER REFERENCES messages(id) ON DELETE CASCADE,
|
|
63
|
-
position INTEGER NOT NULL DEFAULT 0,
|
|
64
|
-
file_name TEXT NOT NULL, content_type TEXT NOT NULL,
|
|
65
|
-
size INTEGER NOT NULL, sha256 TEXT NOT NULL,
|
|
66
|
-
actor TEXT NOT NULL, submission_id TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
67
|
-
UNIQUE(room_id, submission_id)
|
|
68
|
-
);
|
|
69
|
-
CREATE INDEX IF NOT EXISTS attachments_message ON attachments(message_id, position);
|
|
70
|
-
CREATE TRIGGER IF NOT EXISTS validate_attachment_link BEFORE UPDATE OF message_id ON attachments
|
|
71
|
-
WHEN NEW.message_id IS NOT NULL AND (
|
|
72
|
-
(OLD.message_id IS NOT NULL AND OLD.message_id != NEW.message_id)
|
|
73
|
-
OR NOT EXISTS (
|
|
74
|
-
SELECT 1 FROM messages m JOIN message_details d ON d.message_id=m.id
|
|
75
|
-
WHERE m.id=NEW.message_id AND m.room_id=NEW.room_id AND d.submitted_by=NEW.actor
|
|
76
|
-
)
|
|
77
|
-
)
|
|
78
|
-
BEGIN
|
|
79
|
-
SELECT RAISE(ABORT, 'attachment_unavailable');
|
|
80
|
-
END;
|
|
81
|
-
CREATE TABLE IF NOT EXISTS message_summaries (
|
|
82
|
-
message_id INTEGER PRIMARY KEY REFERENCES messages(id),
|
|
83
|
-
text TEXT NOT NULL DEFAULT '', author TEXT NOT NULL DEFAULT ''
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
CREATE TABLE IF NOT EXISTS topic_settings (
|
|
87
|
-
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
88
|
-
host TEXT NOT NULL, background TEXT NOT NULL DEFAULT '', boundaries TEXT NOT NULL DEFAULT '',
|
|
89
|
-
experts TEXT NOT NULL, focus TEXT NOT NULL DEFAULT ''
|
|
90
|
-
);
|
|
91
|
-
CREATE TABLE IF NOT EXISTS message_details (
|
|
92
|
-
message_id INTEGER PRIMARY KEY REFERENCES messages(id),
|
|
93
|
-
kind TEXT NOT NULL DEFAULT 'opinion', submitted_by TEXT NOT NULL
|
|
94
|
-
);
|
|
95
|
-
-- Site administrator account (single user) and its login sessions. Raw tokens and passwords are never stored.
|
|
96
|
-
CREATE TABLE IF NOT EXISTS site_admin (
|
|
97
|
-
id INTEGER PRIMARY KEY CHECK(id=1),
|
|
98
|
-
username TEXT NOT NULL,
|
|
99
|
-
password_hash TEXT NOT NULL,
|
|
100
|
-
avatar TEXT NOT NULL DEFAULT '',
|
|
101
|
-
failed_attempts INTEGER NOT NULL DEFAULT 0,
|
|
102
|
-
locked_until INTEGER NOT NULL DEFAULT 0,
|
|
103
|
-
created_at INTEGER NOT NULL
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
--
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
DROP TRIGGER IF EXISTS
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
DROP TRIGGER IF EXISTS
|
|
184
|
-
DROP TRIGGER IF EXISTS
|
|
185
|
-
DROP TRIGGER IF EXISTS
|
|
186
|
-
DROP TRIGGER IF EXISTS
|
|
187
|
-
DROP TRIGGER IF EXISTS
|
|
188
|
-
DROP TRIGGER IF EXISTS
|
|
189
|
-
DROP TRIGGER IF EXISTS
|
|
190
|
-
DROP TRIGGER IF EXISTS
|
|
191
|
-
DROP TRIGGER IF EXISTS
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
PRIMARY KEY(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
);
|
|
313
|
-
--
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
--
|
|
332
|
-
CREATE
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
CREATE
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
);
|
|
389
|
-
|
|
390
|
-
--
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
--
|
|
399
|
-
CREATE TABLE IF NOT EXISTS
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
);
|
|
405
|
-
--
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
);
|
|
423
|
-
--
|
|
424
|
-
--
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
created_at
|
|
431
|
-
);
|
|
432
|
-
--
|
|
433
|
-
CREATE TABLE IF NOT EXISTS
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
)
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
)
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
)
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
)
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
);
|
|
537
|
-
CREATE INDEX IF NOT EXISTS
|
|
538
|
-
CREATE INDEX IF NOT EXISTS
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
room_id TEXT
|
|
559
|
-
)
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
CREATE
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
CREATE
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
CREATE
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
)
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
)
|
|
648
|
-
CREATE
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
)
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
CREATE TABLE IF NOT EXISTS
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
)
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
status TEXT NOT NULL DEFAULT '
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
CREATE
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
WHERE room_id=
|
|
821
|
-
END;
|
|
822
|
-
CREATE TRIGGER IF NOT EXISTS
|
|
823
|
-
WHEN
|
|
824
|
-
BEGIN
|
|
825
|
-
UPDATE room_message_stats SET message_count=message_count-1,
|
|
826
|
-
latest_id=CASE WHEN latest_id=
|
|
827
|
-
WHERE m.room_id=room_message_stats.room_id AND m.id<>
|
|
828
|
-
WHERE room_id=
|
|
829
|
-
END;
|
|
830
|
-
CREATE TRIGGER IF NOT EXISTS
|
|
831
|
-
WHEN
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
WHEN
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
)
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
);
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
--
|
|
916
|
-
--
|
|
917
|
-
CREATE TABLE IF NOT EXISTS
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
CREATE
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
CREATE TRIGGER
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
CREATE TRIGGER
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
CREATE TRIGGER
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
UPDATE
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
UPDATE
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
END;
|
|
1403
|
-
DROP TRIGGER IF EXISTS
|
|
1404
|
-
CREATE TRIGGER
|
|
1405
|
-
BEGIN
|
|
1406
|
-
INSERT INTO room_events (room_id,at,kind,data)
|
|
1407
|
-
json_object('
|
|
1408
|
-
END;
|
|
1409
|
-
DROP TRIGGER IF EXISTS
|
|
1410
|
-
CREATE TRIGGER
|
|
1411
|
-
BEGIN
|
|
1412
|
-
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'
|
|
1413
|
-
json_object('
|
|
1414
|
-
END;
|
|
1415
|
-
DROP TRIGGER IF EXISTS
|
|
1416
|
-
CREATE TRIGGER
|
|
1417
|
-
WHEN OLD.status IS NOT NEW.status
|
|
1418
|
-
BEGIN
|
|
1419
|
-
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'
|
|
1420
|
-
json_object('
|
|
1421
|
-
END;
|
|
1422
|
-
DROP TRIGGER IF EXISTS
|
|
1423
|
-
CREATE TRIGGER
|
|
1424
|
-
BEGIN
|
|
1425
|
-
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'
|
|
1426
|
-
json_object('
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1
|
+
CREATE TABLE IF NOT EXISTS rooms (
|
|
2
|
+
id TEXT PRIMARY KEY, title TEXT NOT NULL, goal TEXT NOT NULL,
|
|
3
|
+
state_text TEXT NOT NULL DEFAULT '', state_until INTEGER NOT NULL DEFAULT 0,
|
|
4
|
+
created_at TEXT NOT NULL
|
|
5
|
+
);
|
|
6
|
+
CREATE TABLE IF NOT EXISTS room_directory (
|
|
7
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
8
|
+
position INTEGER NOT NULL DEFAULT 0,
|
|
9
|
+
archived INTEGER NOT NULL DEFAULT 0 CHECK (archived IN (0,1))
|
|
10
|
+
);
|
|
11
|
+
INSERT OR IGNORE INTO room_directory (room_id,position)
|
|
12
|
+
SELECT id,ROW_NUMBER() OVER (ORDER BY created_at,id) FROM rooms;
|
|
13
|
+
CREATE TRIGGER IF NOT EXISTS add_room_to_directory AFTER INSERT ON rooms
|
|
14
|
+
BEGIN
|
|
15
|
+
INSERT INTO room_directory (room_id,position)
|
|
16
|
+
VALUES (NEW.id,(SELECT COALESCE(MAX(position),0)+1 FROM room_directory));
|
|
17
|
+
END;
|
|
18
|
+
CREATE TABLE IF NOT EXISTS topic_folders (
|
|
19
|
+
id TEXT PRIMARY KEY, name TEXT NOT NULL, position INTEGER NOT NULL DEFAULT 0
|
|
20
|
+
);
|
|
21
|
+
-- Site-wide preferences of the person managing the site; `last_room` is the room they last opened on any device.
|
|
22
|
+
CREATE TABLE IF NOT EXISTS site_preferences (
|
|
23
|
+
key TEXT PRIMARY KEY,
|
|
24
|
+
value TEXT NOT NULL
|
|
25
|
+
);
|
|
26
|
+
CREATE TABLE IF NOT EXISTS directory_settings (
|
|
27
|
+
id INTEGER PRIMARY KEY CHECK (id=1),
|
|
28
|
+
uncategorized_position INTEGER CHECK (uncategorized_position>=0)
|
|
29
|
+
);
|
|
30
|
+
CREATE TABLE IF NOT EXISTS room_folder_assignments (
|
|
31
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
32
|
+
folder_id TEXT REFERENCES topic_folders(id) ON DELETE SET NULL
|
|
33
|
+
);
|
|
34
|
+
INSERT OR IGNORE INTO room_folder_assignments (room_id,folder_id)
|
|
35
|
+
SELECT id,NULL FROM rooms;
|
|
36
|
+
CREATE TRIGGER IF NOT EXISTS add_room_to_folder_assignments AFTER INSERT ON rooms
|
|
37
|
+
BEGIN
|
|
38
|
+
INSERT INTO room_folder_assignments (room_id,folder_id) VALUES (NEW.id,NULL);
|
|
39
|
+
END;
|
|
40
|
+
CREATE TABLE IF NOT EXISTS room_creations (
|
|
41
|
+
submission_id TEXT PRIMARY KEY,
|
|
42
|
+
room_id TEXT NOT NULL UNIQUE REFERENCES rooms(id),
|
|
43
|
+
request_text TEXT NOT NULL
|
|
44
|
+
);
|
|
45
|
+
CREATE TABLE IF NOT EXISTS room_user_requests (
|
|
46
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
47
|
+
text TEXT NOT NULL DEFAULT ''
|
|
48
|
+
);
|
|
49
|
+
CREATE TABLE IF NOT EXISTS room_briefs (
|
|
50
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
51
|
+
text TEXT NOT NULL, until INTEGER NOT NULL, updated_at TEXT NOT NULL
|
|
52
|
+
);
|
|
53
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
54
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT, room_id TEXT NOT NULL REFERENCES rooms(id),
|
|
55
|
+
author TEXT NOT NULL, text TEXT NOT NULL, reply_to INTEGER REFERENCES messages(id),
|
|
56
|
+
source TEXT NOT NULL, submission_id TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
57
|
+
UNIQUE(room_id, submission_id)
|
|
58
|
+
);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS messages_room ON messages(room_id, id);
|
|
60
|
+
CREATE TABLE IF NOT EXISTS attachments (
|
|
61
|
+
id TEXT PRIMARY KEY, room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
62
|
+
message_id INTEGER REFERENCES messages(id) ON DELETE CASCADE,
|
|
63
|
+
position INTEGER NOT NULL DEFAULT 0,
|
|
64
|
+
file_name TEXT NOT NULL, content_type TEXT NOT NULL,
|
|
65
|
+
size INTEGER NOT NULL, sha256 TEXT NOT NULL,
|
|
66
|
+
actor TEXT NOT NULL, submission_id TEXT NOT NULL, created_at TEXT NOT NULL,
|
|
67
|
+
UNIQUE(room_id, submission_id)
|
|
68
|
+
);
|
|
69
|
+
CREATE INDEX IF NOT EXISTS attachments_message ON attachments(message_id, position);
|
|
70
|
+
CREATE TRIGGER IF NOT EXISTS validate_attachment_link BEFORE UPDATE OF message_id ON attachments
|
|
71
|
+
WHEN NEW.message_id IS NOT NULL AND (
|
|
72
|
+
(OLD.message_id IS NOT NULL AND OLD.message_id != NEW.message_id)
|
|
73
|
+
OR NOT EXISTS (
|
|
74
|
+
SELECT 1 FROM messages m JOIN message_details d ON d.message_id=m.id
|
|
75
|
+
WHERE m.id=NEW.message_id AND m.room_id=NEW.room_id AND d.submitted_by=NEW.actor
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
BEGIN
|
|
79
|
+
SELECT RAISE(ABORT, 'attachment_unavailable');
|
|
80
|
+
END;
|
|
81
|
+
CREATE TABLE IF NOT EXISTS message_summaries (
|
|
82
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id),
|
|
83
|
+
text TEXT NOT NULL DEFAULT '', author TEXT NOT NULL DEFAULT ''
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
CREATE TABLE IF NOT EXISTS topic_settings (
|
|
87
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id),
|
|
88
|
+
host TEXT NOT NULL, background TEXT NOT NULL DEFAULT '', boundaries TEXT NOT NULL DEFAULT '',
|
|
89
|
+
experts TEXT NOT NULL, focus TEXT NOT NULL DEFAULT ''
|
|
90
|
+
);
|
|
91
|
+
CREATE TABLE IF NOT EXISTS message_details (
|
|
92
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id),
|
|
93
|
+
kind TEXT NOT NULL DEFAULT 'opinion', submitted_by TEXT NOT NULL
|
|
94
|
+
);
|
|
95
|
+
-- Site administrator account (single user) and its login sessions. Raw tokens and passwords are never stored.
|
|
96
|
+
CREATE TABLE IF NOT EXISTS site_admin (
|
|
97
|
+
id INTEGER PRIMARY KEY CHECK(id=1),
|
|
98
|
+
username TEXT NOT NULL,
|
|
99
|
+
password_hash TEXT NOT NULL,
|
|
100
|
+
avatar TEXT NOT NULL DEFAULT '',
|
|
101
|
+
failed_attempts INTEGER NOT NULL DEFAULT 0,
|
|
102
|
+
locked_until INTEGER NOT NULL DEFAULT 0,
|
|
103
|
+
created_at INTEGER NOT NULL
|
|
104
|
+
);
|
|
105
|
+
-- Logins end after a week unused or a month in all; label is the browser that signed in. The older table
|
|
106
|
+
-- admin_sessions held logins that never expired and is no longer read, so upgrading signs everyone out once.
|
|
107
|
+
CREATE TABLE IF NOT EXISTS admin_logins (
|
|
108
|
+
token_hash TEXT PRIMARY KEY,
|
|
109
|
+
label TEXT NOT NULL DEFAULT '',
|
|
110
|
+
created_at INTEGER NOT NULL,
|
|
111
|
+
last_seen INTEGER NOT NULL
|
|
112
|
+
);
|
|
113
|
+
-- Wrong-password backoff per client address; the row with source '*' counts all addresses within an hour.
|
|
114
|
+
-- site_admin.failed_attempts and locked_until are no longer used.
|
|
115
|
+
-- Passkeys for website login (Worker only); the paired computer keeps its own copy for device checks.
|
|
116
|
+
CREATE TABLE IF NOT EXISTS admin_passkeys (
|
|
117
|
+
id TEXT PRIMARY KEY,
|
|
118
|
+
public_key TEXT NOT NULL,
|
|
119
|
+
alg INTEGER NOT NULL,
|
|
120
|
+
sign_count INTEGER NOT NULL DEFAULT 0,
|
|
121
|
+
label TEXT NOT NULL DEFAULT '',
|
|
122
|
+
created_at INTEGER NOT NULL
|
|
123
|
+
);
|
|
124
|
+
-- Owner messages accepted through the optional remote entry (--remote-port), which has no device signature: work
|
|
125
|
+
-- started from them runs members read-only on the computer.
|
|
126
|
+
CREATE TABLE IF NOT EXISTS remote_entry_messages (
|
|
127
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
|
|
128
|
+
room_id TEXT NOT NULL
|
|
129
|
+
);
|
|
130
|
+
-- One-time passkey challenges, valid two minutes.
|
|
131
|
+
CREATE TABLE IF NOT EXISTS admin_challenges (
|
|
132
|
+
id TEXT PRIMARY KEY,
|
|
133
|
+
purpose TEXT NOT NULL,
|
|
134
|
+
challenge TEXT NOT NULL,
|
|
135
|
+
created_at INTEGER NOT NULL
|
|
136
|
+
);
|
|
137
|
+
CREATE TABLE IF NOT EXISTS admin_attempts (
|
|
138
|
+
source TEXT PRIMARY KEY,
|
|
139
|
+
failed INTEGER NOT NULL DEFAULT 0,
|
|
140
|
+
locked_until INTEGER NOT NULL DEFAULT 0,
|
|
141
|
+
updated_at INTEGER NOT NULL
|
|
142
|
+
);
|
|
143
|
+
-- One-time registration token from `codiscuss token` on the deploying computer; cleared once the administrator registers.
|
|
144
|
+
CREATE TABLE IF NOT EXISTS admin_setup (
|
|
145
|
+
id INTEGER PRIMARY KEY CHECK(id=1),
|
|
146
|
+
token_hash TEXT NOT NULL,
|
|
147
|
+
created_at INTEGER NOT NULL
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
-- Every room is a free collaboration room; a discussion is a session inside it. Holds the owner's control hash.
|
|
151
|
+
CREATE TABLE IF NOT EXISTS room_modes (
|
|
152
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE,
|
|
153
|
+
mode TEXT NOT NULL CHECK(mode='free'),
|
|
154
|
+
control_hash TEXT NOT NULL DEFAULT ''
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
-- A room's limits for its next discussion, set at creation or in the topic while no discussion is open; a started
|
|
158
|
+
-- discussion copies them into session_limits.
|
|
159
|
+
CREATE TABLE IF NOT EXISTS discussion_limits (
|
|
160
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE,
|
|
161
|
+
max_rounds INTEGER NOT NULL DEFAULT 0,
|
|
162
|
+
max_minutes INTEGER NOT NULL DEFAULT 0,
|
|
163
|
+
execution_minutes INTEGER NOT NULL DEFAULT 0
|
|
164
|
+
);
|
|
165
|
+
INSERT OR IGNORE INTO discussion_limits(room_id,execution_minutes) SELECT id,0 FROM rooms;
|
|
166
|
+
DROP TRIGGER IF EXISTS limits_room_created;
|
|
167
|
+
CREATE TRIGGER limits_room_created AFTER INSERT ON rooms
|
|
168
|
+
BEGIN
|
|
169
|
+
INSERT INTO discussion_limits(room_id,execution_minutes) VALUES (NEW.id,0);
|
|
170
|
+
END;
|
|
171
|
+
-- Freeze dispatch-to-publication time independently of the recent execution list.
|
|
172
|
+
CREATE TABLE IF NOT EXISTS message_timings (
|
|
173
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
|
|
174
|
+
elapsed_seconds INTEGER NOT NULL CHECK(elapsed_seconds>=0)
|
|
175
|
+
);
|
|
176
|
+
-- A failed assertion rolls back the whole D1 batch, including concurrent writes.
|
|
177
|
+
CREATE TABLE IF NOT EXISTS runtime_assertions (
|
|
178
|
+
id TEXT PRIMARY KEY, allowed INTEGER NOT NULL CHECK(allowed=1)
|
|
179
|
+
);
|
|
180
|
+
-- Triggers of the retired discussion-room model (speaking floor, turns, relay, room-scoped runtime and phase).
|
|
181
|
+
-- Dropped on every start so an older database stops enforcing them; its leftover tables are removed by
|
|
182
|
+
-- migrations/drop_legacy_discussion.sql.
|
|
183
|
+
DROP TRIGGER IF EXISTS reject_archived_resume;
|
|
184
|
+
DROP TRIGGER IF EXISTS validate_turn_answer;
|
|
185
|
+
DROP TRIGGER IF EXISTS reject_inactive_opinion;
|
|
186
|
+
DROP TRIGGER IF EXISTS reject_inactive_turn;
|
|
187
|
+
DROP TRIGGER IF EXISTS reject_conclusion_with_open_turn;
|
|
188
|
+
DROP TRIGGER IF EXISTS require_opinion_turn;
|
|
189
|
+
DROP TRIGGER IF EXISTS initialize_room_floor;
|
|
190
|
+
DROP TRIGGER IF EXISTS transfer_host_floor;
|
|
191
|
+
DROP TRIGGER IF EXISTS require_message_floor;
|
|
192
|
+
DROP TRIGGER IF EXISTS return_message_floor;
|
|
193
|
+
DROP TRIGGER IF EXISTS require_host_floor;
|
|
194
|
+
DROP TRIGGER IF EXISTS nominate_expert_floor;
|
|
195
|
+
DROP TRIGGER IF EXISTS cancel_turn_floor;
|
|
196
|
+
DROP TRIGGER IF EXISTS limits_topic_started;
|
|
197
|
+
DROP TRIGGER IF EXISTS limits_phase_started;
|
|
198
|
+
DROP TRIGGER IF EXISTS limits_turn_started;
|
|
199
|
+
DROP TRIGGER IF EXISTS record_event_timing;
|
|
200
|
+
DROP TRIGGER IF EXISTS runtime_generation;
|
|
201
|
+
DROP TRIGGER IF EXISTS runtime_turn_created;
|
|
202
|
+
DROP TRIGGER IF EXISTS relay_turn_promoted;
|
|
203
|
+
DROP TRIGGER IF EXISTS relay_plan_replaced;
|
|
204
|
+
DROP TRIGGER IF EXISTS relay_hold_user_message;
|
|
205
|
+
DROP TRIGGER IF EXISTS relay_hold_goal;
|
|
206
|
+
DROP TRIGGER IF EXISTS relay_hold_topic;
|
|
207
|
+
DROP TRIGGER IF EXISTS relay_plan_concluded;
|
|
208
|
+
DROP TRIGGER IF EXISTS relay_plan_participants;
|
|
209
|
+
DROP TRIGGER IF EXISTS runtime_turn_answered;
|
|
210
|
+
DROP TRIGGER IF EXISTS runtime_topic_stop;
|
|
211
|
+
DROP TRIGGER IF EXISTS runtime_user_message;
|
|
212
|
+
DROP TRIGGER IF EXISTS runtime_turn_cancelled;
|
|
213
|
+
DROP TRIGGER IF EXISTS runtime_archive;
|
|
214
|
+
DROP TRIGGER IF EXISTS runtime_participants_changed;
|
|
215
|
+
DROP TRIGGER IF EXISTS runtime_experts_changed;
|
|
216
|
+
DROP TRIGGER IF EXISTS runtime_goal_changed;
|
|
217
|
+
DROP TRIGGER IF EXISTS runtime_constraints_changed;
|
|
218
|
+
DROP TRIGGER IF EXISTS pause_clock_stopped;
|
|
219
|
+
DROP TRIGGER IF EXISTS pause_clock_resumed;
|
|
220
|
+
DROP TRIGGER IF EXISTS session_for_new_discussion;
|
|
221
|
+
DROP TRIGGER IF EXISTS session_follows_phase_insert;
|
|
222
|
+
DROP TRIGGER IF EXISTS session_follows_phase;
|
|
223
|
+
DROP TRIGGER IF EXISTS conclusion_snapshot;
|
|
224
|
+
DROP TRIGGER IF EXISTS revision_free_settings_insert;
|
|
225
|
+
DROP TRIGGER IF EXISTS revision_free_settings_update;
|
|
226
|
+
-- Room members; their requests and executions follow.
|
|
227
|
+
CREATE TABLE IF NOT EXISTS room_members (
|
|
228
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
229
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
230
|
+
name TEXT NOT NULL,
|
|
231
|
+
adapter TEXT NOT NULL DEFAULT '',
|
|
232
|
+
role TEXT NOT NULL DEFAULT 'member' CHECK(role IN ('member','host')),
|
|
233
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','away','removed')),
|
|
234
|
+
token_hash TEXT NOT NULL,
|
|
235
|
+
read_until INTEGER NOT NULL DEFAULT 0,
|
|
236
|
+
created_at TEXT NOT NULL,
|
|
237
|
+
access TEXT NOT NULL DEFAULT 'runner',
|
|
238
|
+
session_mode TEXT NOT NULL DEFAULT 'new'
|
|
239
|
+
);
|
|
240
|
+
CREATE UNIQUE INDEX IF NOT EXISTS member_name ON room_members(room_id,name) WHERE status<>'removed';
|
|
241
|
+
CREATE UNIQUE INDEX IF NOT EXISTS member_credential ON room_members(room_id,token_hash);
|
|
242
|
+
|
|
243
|
+
-- Local service attestation, never a permission grant. Re-imported rooms require a fresh attestation.
|
|
244
|
+
CREATE TABLE IF NOT EXISTS member_review_capabilities (
|
|
245
|
+
member_id INTEGER PRIMARY KEY REFERENCES room_members(id) ON DELETE CASCADE,
|
|
246
|
+
member_revision TEXT NOT NULL,
|
|
247
|
+
config_version TEXT NOT NULL,
|
|
248
|
+
adapter TEXT NOT NULL,
|
|
249
|
+
recorded_at INTEGER NOT NULL,
|
|
250
|
+
generation INTEGER NOT NULL DEFAULT 0
|
|
251
|
+
);
|
|
252
|
+
CREATE TRIGGER IF NOT EXISTS invalidate_member_review_capability
|
|
253
|
+
AFTER UPDATE OF token_hash,status,adapter,access,session_mode ON room_members
|
|
254
|
+
WHEN NEW.token_hash<>OLD.token_hash OR NEW.status<>OLD.status OR NEW.adapter<>OLD.adapter
|
|
255
|
+
OR NEW.access<>OLD.access OR NEW.session_mode<>OLD.session_mode
|
|
256
|
+
BEGIN
|
|
257
|
+
INSERT INTO member_review_capabilities(member_id,member_revision,config_version,adapter,recorded_at,generation)
|
|
258
|
+
VALUES(NEW.id,'','',NEW.adapter,0,1)
|
|
259
|
+
ON CONFLICT(member_id) DO UPDATE SET member_revision='',config_version='',generation=generation+1;
|
|
260
|
+
END;
|
|
261
|
+
-- A manual member's own software session, reported by its CLI on posting; the local service uses it to take the member over.
|
|
262
|
+
CREATE TABLE IF NOT EXISTS member_sessions (
|
|
263
|
+
member_id INTEGER PRIMARY KEY REFERENCES room_members(id) ON DELETE CASCADE,
|
|
264
|
+
room_id TEXT NOT NULL,
|
|
265
|
+
session_id TEXT NOT NULL,
|
|
266
|
+
client TEXT NOT NULL
|
|
267
|
+
);
|
|
268
|
+
-- Why the local service could not take over a manual member's reported session; shown only while that session is still the reported one.
|
|
269
|
+
CREATE TABLE IF NOT EXISTS member_adopt_failures (
|
|
270
|
+
member_id INTEGER PRIMARY KEY REFERENCES room_members(id) ON DELETE CASCADE,
|
|
271
|
+
room_id TEXT NOT NULL,
|
|
272
|
+
session_id TEXT NOT NULL,
|
|
273
|
+
reason TEXT NOT NULL
|
|
274
|
+
);
|
|
275
|
+
-- A manual member's own registration; it is bound to the credential it used, so a re-issued credential must register again.
|
|
276
|
+
CREATE TABLE IF NOT EXISTS member_registrations (
|
|
277
|
+
member_id INTEGER PRIMARY KEY REFERENCES room_members(id) ON DELETE CASCADE,
|
|
278
|
+
room_id TEXT NOT NULL,
|
|
279
|
+
token_hash TEXT NOT NULL,
|
|
280
|
+
registered_at TEXT NOT NULL
|
|
281
|
+
);
|
|
282
|
+
-- Marks members of the retired web-relay access; no new rows are written.
|
|
283
|
+
CREATE TABLE IF NOT EXISTS member_manual_sources (
|
|
284
|
+
member_id INTEGER PRIMARY KEY REFERENCES room_members(id) ON DELETE CASCADE,
|
|
285
|
+
source TEXT NOT NULL CHECK(source='web')
|
|
286
|
+
);
|
|
287
|
+
CREATE TABLE IF NOT EXISTS member_executions (
|
|
288
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
289
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
290
|
+
member_id INTEGER NOT NULL REFERENCES room_members(id) ON DELETE CASCADE,
|
|
291
|
+
client_id TEXT NOT NULL,
|
|
292
|
+
status TEXT NOT NULL DEFAULT 'dispatched'
|
|
293
|
+
CHECK(status IN ('dispatched','started','completed','cancelled','failed')),
|
|
294
|
+
session_id TEXT NOT NULL DEFAULT '',
|
|
295
|
+
lease_until INTEGER NOT NULL DEFAULT 0,
|
|
296
|
+
created_at INTEGER NOT NULL,
|
|
297
|
+
finished_at INTEGER NOT NULL DEFAULT 0,
|
|
298
|
+
result TEXT NOT NULL DEFAULT '',
|
|
299
|
+
changes TEXT NOT NULL DEFAULT '',
|
|
300
|
+
cwd TEXT NOT NULL DEFAULT '',
|
|
301
|
+
activity TEXT NOT NULL DEFAULT '',
|
|
302
|
+
activity_at INTEGER NOT NULL DEFAULT 0,
|
|
303
|
+
UNIQUE(room_id,client_id)
|
|
304
|
+
);
|
|
305
|
+
-- What the owner wrote about each member (strengths, division of work), by name so it survives leaving and rejoining.
|
|
306
|
+
CREATE TABLE IF NOT EXISTS member_descriptions (
|
|
307
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
308
|
+
name TEXT NOT NULL,
|
|
309
|
+
description TEXT NOT NULL,
|
|
310
|
+
updated_at INTEGER NOT NULL,
|
|
311
|
+
PRIMARY KEY(room_id,name)
|
|
312
|
+
);
|
|
313
|
+
-- Display labels the owner gave members (e.g. from a named preset); screens show them, the name stays the identity.
|
|
314
|
+
CREATE TABLE IF NOT EXISTS member_labels (
|
|
315
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
316
|
+
name TEXT NOT NULL,
|
|
317
|
+
label TEXT NOT NULL,
|
|
318
|
+
updated_at INTEGER NOT NULL,
|
|
319
|
+
PRIMARY KEY(room_id,name)
|
|
320
|
+
);
|
|
321
|
+
-- Progress notes the runner saw a member's software write between tool calls; numbered per execution so a retried renewal adds nothing.
|
|
322
|
+
CREATE TABLE IF NOT EXISTS execution_notes (
|
|
323
|
+
execution_id INTEGER NOT NULL REFERENCES member_executions(id) ON DELETE CASCADE,
|
|
324
|
+
seq INTEGER NOT NULL,
|
|
325
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
326
|
+
text TEXT NOT NULL,
|
|
327
|
+
created_at INTEGER NOT NULL,
|
|
328
|
+
PRIMARY KEY(execution_id,seq)
|
|
329
|
+
);
|
|
330
|
+
-- Operations a member's software refused without asking, since a headless run cannot ask for approval; reported once by the
|
|
331
|
+
-- runner after the process ends, as a JSON list of {tool, detail, rule}, so the owner can see and allow them.
|
|
332
|
+
CREATE TABLE IF NOT EXISTS execution_denials (
|
|
333
|
+
execution_id INTEGER PRIMARY KEY REFERENCES member_executions(id) ON DELETE CASCADE,
|
|
334
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
335
|
+
denials TEXT NOT NULL
|
|
336
|
+
);
|
|
337
|
+
-- A manual member's session refused a delivery: the runner keeps the execution and delivers again at retry_at
|
|
338
|
+
-- (0 while delivering). The owner may ask for it now or stop it, and the runner then fails it. Not part of backups.
|
|
339
|
+
CREATE TABLE IF NOT EXISTS execution_retries (
|
|
340
|
+
execution_id INTEGER PRIMARY KEY REFERENCES member_executions(id) ON DELETE CASCADE,
|
|
341
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
342
|
+
attempt INTEGER NOT NULL,
|
|
343
|
+
retry_at INTEGER NOT NULL DEFAULT 0,
|
|
344
|
+
reason TEXT NOT NULL DEFAULT '',
|
|
345
|
+
stopped INTEGER NOT NULL DEFAULT 0
|
|
346
|
+
);
|
|
347
|
+
-- Phases the runner saw a member's software go through in one execution, as
|
|
348
|
+
-- millisecond offsets from its delivery; numbered per execution, and a resent segment keeps the later end. Not part of backups.
|
|
349
|
+
CREATE TABLE IF NOT EXISTS execution_segments (
|
|
350
|
+
source TEXT NOT NULL CHECK(source='free'),
|
|
351
|
+
execution_id INTEGER NOT NULL,
|
|
352
|
+
seq INTEGER NOT NULL,
|
|
353
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
354
|
+
phase TEXT NOT NULL,
|
|
355
|
+
tool TEXT NOT NULL DEFAULT '',
|
|
356
|
+
start_ms INTEGER NOT NULL,
|
|
357
|
+
end_ms INTEGER NOT NULL,
|
|
358
|
+
PRIMARY KEY(source,execution_id,seq)
|
|
359
|
+
);
|
|
360
|
+
CREATE INDEX IF NOT EXISTS execution_segments_room ON execution_segments(room_id);
|
|
361
|
+
-- One live execution per member: different members may run in parallel, one session never twice.
|
|
362
|
+
CREATE UNIQUE INDEX IF NOT EXISTS one_member_execution ON member_executions(member_id)
|
|
363
|
+
WHERE status IN ('dispatched','started');
|
|
364
|
+
CREATE INDEX IF NOT EXISTS member_executions_member ON member_executions(member_id);
|
|
365
|
+
-- The client-id uniqueness index cannot satisfy ORDER BY id LIMIT on a room's history.
|
|
366
|
+
CREATE INDEX IF NOT EXISTS member_executions_room_recent ON member_executions(room_id,id);
|
|
367
|
+
CREATE INDEX IF NOT EXISTS member_executions_room_changes ON member_executions(room_id,id) WHERE changes<>'';
|
|
368
|
+
CREATE INDEX IF NOT EXISTS member_executions_room_live ON member_executions(room_id,id) WHERE status IN ('dispatched','started');
|
|
369
|
+
CREATE TABLE IF NOT EXISTS member_requests (
|
|
370
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
371
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
372
|
+
member_id INTEGER NOT NULL REFERENCES room_members(id) ON DELETE CASCADE,
|
|
373
|
+
message_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
374
|
+
status TEXT NOT NULL DEFAULT 'pending'
|
|
375
|
+
CHECK(status IN ('pending','delivering','completed','cancelled','failed')),
|
|
376
|
+
execution_id INTEGER REFERENCES member_executions(id),
|
|
377
|
+
answer_id INTEGER REFERENCES messages(id),
|
|
378
|
+
created_at INTEGER NOT NULL,
|
|
379
|
+
chain_id INTEGER NOT NULL DEFAULT 0,
|
|
380
|
+
batch_id INTEGER NOT NULL DEFAULT 0,
|
|
381
|
+
purpose TEXT NOT NULL DEFAULT 'ask',
|
|
382
|
+
created_by TEXT NOT NULL DEFAULT 'user',
|
|
383
|
+
UNIQUE(message_id,member_id)
|
|
384
|
+
);
|
|
385
|
+
CREATE INDEX IF NOT EXISTS member_requests_open ON member_requests(member_id,status);
|
|
386
|
+
CREATE INDEX IF NOT EXISTS member_requests_execution ON member_requests(execution_id);
|
|
387
|
+
CREATE INDEX IF NOT EXISTS member_requests_room ON member_requests(room_id);
|
|
388
|
+
CREATE INDEX IF NOT EXISTS member_requests_room_status ON member_requests(room_id,status);
|
|
389
|
+
CREATE INDEX IF NOT EXISTS member_requests_batch ON member_requests(batch_id,status);
|
|
390
|
+
-- Web chatbots are no longer members: earlier ones are removed and their open requests cancelled; their messages keep
|
|
391
|
+
-- the author name. member_manual_sources stays only to recognise those earlier members.
|
|
392
|
+
UPDATE member_requests SET status='cancelled' WHERE status IN ('pending','delivering') AND member_id IN (
|
|
393
|
+
SELECT member_id FROM member_manual_sources UNION SELECT id FROM room_members WHERE access='online');
|
|
394
|
+
INSERT OR IGNORE INTO member_manual_sources (member_id,source) SELECT id,'web' FROM room_members WHERE access='online';
|
|
395
|
+
UPDATE room_members SET access='manual' WHERE access='online';
|
|
396
|
+
UPDATE room_members SET status='removed',role='member' WHERE status<>'removed' AND id IN (SELECT member_id FROM member_manual_sources);
|
|
397
|
+
-- One durable disposition per @everyone message; also prevents a host fallback from being routed again after restart.
|
|
398
|
+
-- The original group request may be deleted for a sequential queue, so request_id is a receipt, not a foreign key.
|
|
399
|
+
CREATE TABLE IF NOT EXISTS group_routes (
|
|
400
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
|
|
401
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
402
|
+
request_id INTEGER NOT NULL,
|
|
403
|
+
action TEXT NOT NULL CHECK(action IN ('all','sequential','host'))
|
|
404
|
+
);
|
|
405
|
+
-- Visible record of each smart-scheduling decision in a discussion; it is not a message and moves no round or floor.
|
|
406
|
+
CREATE TABLE IF NOT EXISTS scheduler_decisions (
|
|
407
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
408
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
409
|
+
after_message_id INTEGER NOT NULL DEFAULT 0,
|
|
410
|
+
kind TEXT NOT NULL CHECK(kind IN ('interjection','round')),
|
|
411
|
+
label TEXT NOT NULL,
|
|
412
|
+
confidence REAL,
|
|
413
|
+
applied INTEGER NOT NULL DEFAULT 0 CHECK(applied IN (0,1)),
|
|
414
|
+
provider TEXT NOT NULL,
|
|
415
|
+
created_at TEXT NOT NULL
|
|
416
|
+
);
|
|
417
|
+
CREATE INDEX IF NOT EXISTS scheduler_decisions_room ON scheduler_decisions(room_id,id);
|
|
418
|
+
-- What the decision model was asked and chose, shown folded under the decision; not part of backups.
|
|
419
|
+
CREATE TABLE IF NOT EXISTS scheduler_decision_details (
|
|
420
|
+
decision_id INTEGER PRIMARY KEY REFERENCES scheduler_decisions(id) ON DELETE CASCADE,
|
|
421
|
+
detail TEXT NOT NULL
|
|
422
|
+
);
|
|
423
|
+
-- The owner's verdict on one decision; a 'bad' one may also say who should have answered and why.
|
|
424
|
+
-- Kept apart from the decision so older databases need no column change.
|
|
425
|
+
CREATE TABLE IF NOT EXISTS scheduler_feedback (
|
|
426
|
+
decision_id INTEGER PRIMARY KEY REFERENCES scheduler_decisions(id) ON DELETE CASCADE,
|
|
427
|
+
rating TEXT NOT NULL CHECK(rating IN ('good','bad')),
|
|
428
|
+
should_be TEXT NOT NULL DEFAULT '',
|
|
429
|
+
note TEXT NOT NULL DEFAULT '',
|
|
430
|
+
created_at TEXT NOT NULL
|
|
431
|
+
);
|
|
432
|
+
-- Messages the local service is still asking the decision model about; a transient marker, not part of backups.
|
|
433
|
+
CREATE TABLE IF NOT EXISTS scheduler_routing (
|
|
434
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
435
|
+
message_id INTEGER NOT NULL,
|
|
436
|
+
created_at INTEGER NOT NULL,
|
|
437
|
+
PRIMARY KEY (room_id, message_id)
|
|
438
|
+
);
|
|
439
|
+
-- Older development databases may retain execution_deliveries; it is no longer read or written.
|
|
440
|
+
-- What the runner's adapter reported each execution can do (stop it, see its progress), and whether its software stopped
|
|
441
|
+
-- once the execution was voided: the page describes a stop as it really went (a window or App the runner cannot stop
|
|
442
|
+
-- keeps generating). A side table so older databases need no column change; executions are not backed up, so neither is this.
|
|
443
|
+
CREATE TABLE IF NOT EXISTS execution_capabilities (
|
|
444
|
+
execution_id INTEGER PRIMARY KEY REFERENCES member_executions(id) ON DELETE CASCADE,
|
|
445
|
+
room_id TEXT NOT NULL,
|
|
446
|
+
stoppable INTEGER CHECK(stoppable IN (0,1)),
|
|
447
|
+
progress INTEGER CHECK(progress IN (0,1)),
|
|
448
|
+
stop_result TEXT NOT NULL DEFAULT '' CHECK(stop_result IN ('','stopped','unstoppable','unconfirmed'))
|
|
449
|
+
);
|
|
450
|
+
-- What a rewind does to each runner member's session, as its adapter reported: cut by the runner, rebuilt each time
|
|
451
|
+
-- (fresh), or kept as it is. A member without a report is kept; manual and online members are always kept.
|
|
452
|
+
CREATE TABLE IF NOT EXISTS member_capabilities (
|
|
453
|
+
member_id INTEGER PRIMARY KEY REFERENCES room_members(id) ON DELETE CASCADE,
|
|
454
|
+
room_id TEXT NOT NULL,
|
|
455
|
+
rewind TEXT NOT NULL CHECK(rewind IN ('cut','fresh','kept'))
|
|
456
|
+
);
|
|
457
|
+
-- What a member submitted for an execution the user had already voided. Refused as an answer, so it never joins the
|
|
458
|
+
-- transcript or AI reads; kept so the page can show the late work folded, and so a member the runner could not stop
|
|
459
|
+
-- is known to have finished that turn. One per execution; not backed up, like executions.
|
|
460
|
+
CREATE TABLE IF NOT EXISTS late_answers (
|
|
461
|
+
execution_id INTEGER PRIMARY KEY REFERENCES member_executions(id) ON DELETE CASCADE,
|
|
462
|
+
room_id TEXT NOT NULL,
|
|
463
|
+
text TEXT NOT NULL,
|
|
464
|
+
created_at INTEGER NOT NULL
|
|
465
|
+
);
|
|
466
|
+
-- Why a request was cancelled; a side table so older databases need no column change. Requests cancelled before it existed have no row.
|
|
467
|
+
CREATE TABLE IF NOT EXISTS request_cancel_reasons (
|
|
468
|
+
request_id INTEGER PRIMARY KEY REFERENCES member_requests(id) ON DELETE CASCADE,
|
|
469
|
+
reason TEXT NOT NULL CHECK(reason IN ('user_stop','member_away','member_removed','rerouted','no_reply','archived'))
|
|
470
|
+
);
|
|
471
|
+
-- Messages the owner took back: a retracted one no member began to handle, or the history a rewind returned to before.
|
|
472
|
+
-- AI readers no longer see them; the page keeps each in place. No room column, so it never clashes with messages.room_id in joins.
|
|
473
|
+
CREATE TABLE IF NOT EXISTS message_withdrawals (
|
|
474
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
|
|
475
|
+
kind TEXT NOT NULL CHECK(kind IN ('retracted','rewound')),
|
|
476
|
+
created_at INTEGER NOT NULL
|
|
477
|
+
);
|
|
478
|
+
-- An indexed room lookup without adding a room_id column that would make existing message joins ambiguous.
|
|
479
|
+
CREATE TABLE IF NOT EXISTS message_withdrawal_rooms (
|
|
480
|
+
message_id INTEGER PRIMARY KEY REFERENCES message_withdrawals(message_id) ON DELETE CASCADE,
|
|
481
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE
|
|
482
|
+
);
|
|
483
|
+
CREATE INDEX IF NOT EXISTS message_withdrawal_rooms_room ON message_withdrawal_rooms(room_id,message_id);
|
|
484
|
+
INSERT INTO message_withdrawal_rooms(message_id,room_id)
|
|
485
|
+
SELECT w.message_id,m.room_id FROM message_withdrawals w JOIN messages m ON m.id=w.message_id
|
|
486
|
+
WHERE NOT EXISTS(SELECT 1 FROM message_withdrawal_rooms r WHERE r.message_id=w.message_id);
|
|
487
|
+
CREATE TRIGGER IF NOT EXISTS withdrawal_room_insert AFTER INSERT ON message_withdrawals
|
|
488
|
+
BEGIN
|
|
489
|
+
INSERT INTO message_withdrawal_rooms(message_id,room_id) SELECT NEW.message_id,room_id FROM messages WHERE id=NEW.message_id;
|
|
490
|
+
END;
|
|
491
|
+
CREATE TRIGGER IF NOT EXISTS withdrawal_room_move AFTER UPDATE OF room_id ON messages
|
|
492
|
+
BEGIN
|
|
493
|
+
UPDATE message_withdrawal_rooms SET room_id=NEW.room_id WHERE message_id=NEW.id;
|
|
494
|
+
END;
|
|
495
|
+
-- Each rewind and, per member id, the executions it took back (JSON {member id: [execution ids]}): before the member's next
|
|
496
|
+
-- execution the runner cuts its session before the earliest of them it finds. Not part of backups, since executions are not.
|
|
497
|
+
CREATE TABLE IF NOT EXISTS room_rewinds (
|
|
498
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
499
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
500
|
+
message_id INTEGER NOT NULL,
|
|
501
|
+
cuts TEXT NOT NULL,
|
|
502
|
+
created_at INTEGER NOT NULL
|
|
503
|
+
);
|
|
504
|
+
-- What produced a decision (model, threshold, prompt and package versions), so ratings stay comparable across versions.
|
|
505
|
+
CREATE TABLE IF NOT EXISTS scheduler_decision_context (
|
|
506
|
+
decision_id INTEGER PRIMARY KEY REFERENCES scheduler_decisions(id) ON DELETE CASCADE,
|
|
507
|
+
context TEXT NOT NULL
|
|
508
|
+
);
|
|
509
|
+
-- The exact input the decision model saw (state and full questions with option descriptions); not part of backups.
|
|
510
|
+
CREATE TABLE IF NOT EXISTS scheduler_decision_inputs (
|
|
511
|
+
decision_id INTEGER PRIMARY KEY REFERENCES scheduler_decisions(id) ON DELETE CASCADE,
|
|
512
|
+
input TEXT NOT NULL
|
|
513
|
+
);
|
|
514
|
+
-- A self-contained copy of each decision the owner currently rates bad, kept when its room is deleted so prompts can be reviewed.
|
|
515
|
+
CREATE TABLE IF NOT EXISTS scheduler_feedback_cases (
|
|
516
|
+
decision_id INTEGER PRIMARY KEY,
|
|
517
|
+
room_id TEXT NOT NULL,
|
|
518
|
+
room_title TEXT NOT NULL,
|
|
519
|
+
snapshot TEXT NOT NULL,
|
|
520
|
+
should_be TEXT NOT NULL DEFAULT '',
|
|
521
|
+
note TEXT NOT NULL DEFAULT '',
|
|
522
|
+
rated_at TEXT NOT NULL
|
|
523
|
+
);
|
|
524
|
+
-- Smart scheduling's suggestion that another member answer an unnamed message. The host keeps the message;
|
|
525
|
+
-- the user may adopt before expires_at (waiting until the host's request ends for mode 'after'), otherwise it lapses.
|
|
526
|
+
CREATE TABLE IF NOT EXISTS member_recommendations (
|
|
527
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
|
|
528
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
529
|
+
member_id INTEGER NOT NULL REFERENCES room_members(id) ON DELETE CASCADE,
|
|
530
|
+
provider TEXT NOT NULL,
|
|
531
|
+
confidence REAL NOT NULL,
|
|
532
|
+
created_at INTEGER NOT NULL,
|
|
533
|
+
expires_at INTEGER NOT NULL,
|
|
534
|
+
status TEXT NOT NULL DEFAULT 'open' CHECK(status IN ('open','waiting','adopted')),
|
|
535
|
+
mode TEXT NOT NULL DEFAULT ''
|
|
536
|
+
);
|
|
537
|
+
CREATE INDEX IF NOT EXISTS member_recommendations_room ON member_recommendations(room_id,status);
|
|
538
|
+
CREATE INDEX IF NOT EXISTS member_recommendations_recent ON member_recommendations(room_id,message_id);
|
|
539
|
+
-- Ordinary members can suggest a response without creating work or spending a chain budget.
|
|
540
|
+
CREATE TABLE IF NOT EXISTS member_suggestions (
|
|
541
|
+
message_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
542
|
+
member_id INTEGER NOT NULL REFERENCES room_members(id) ON DELETE CASCADE,
|
|
543
|
+
PRIMARY KEY (message_id,member_id)
|
|
544
|
+
);
|
|
545
|
+
-- A host's dispatch: its named requests form one batch that hands back to the host once.
|
|
546
|
+
CREATE TABLE IF NOT EXISTS free_batches (
|
|
547
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
548
|
+
batch_id INTEGER NOT NULL,
|
|
549
|
+
chain_id INTEGER NOT NULL,
|
|
550
|
+
host_id INTEGER NOT NULL,
|
|
551
|
+
settled INTEGER NOT NULL DEFAULT 0,
|
|
552
|
+
PRIMARY KEY (room_id,batch_id)
|
|
553
|
+
);
|
|
554
|
+
-- Members the user named to answer one after another, in the room's speaking order: each gets its request once the one before
|
|
555
|
+
-- it ends. Asked rows stay so the speaking order can show who already answered; the owner may reorder rows not yet asked.
|
|
556
|
+
CREATE TABLE IF NOT EXISTS free_queue (
|
|
557
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
558
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
559
|
+
message_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
560
|
+
member_id INTEGER NOT NULL REFERENCES room_members(id) ON DELETE CASCADE
|
|
561
|
+
);
|
|
562
|
+
CREATE INDEX IF NOT EXISTS free_queue_room ON free_queue(room_id,id);
|
|
563
|
+
CREATE INDEX IF NOT EXISTS free_queue_message ON free_queue(message_id,id);
|
|
564
|
+
-- Only not-yet-requested queue rows participate in advancement. Historical rows remain in free_queue.
|
|
565
|
+
CREATE TABLE IF NOT EXISTS free_queue_waiting (
|
|
566
|
+
id INTEGER PRIMARY KEY REFERENCES free_queue(id) ON DELETE CASCADE,
|
|
567
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
568
|
+
message_id INTEGER NOT NULL,
|
|
569
|
+
member_id INTEGER NOT NULL
|
|
570
|
+
);
|
|
571
|
+
CREATE INDEX IF NOT EXISTS free_queue_waiting_room ON free_queue_waiting(room_id,message_id,id);
|
|
572
|
+
CREATE INDEX IF NOT EXISTS free_queue_waiting_message ON free_queue_waiting(message_id,member_id);
|
|
573
|
+
INSERT INTO free_queue_waiting(id,room_id,message_id,member_id)
|
|
574
|
+
SELECT q.id,q.room_id,q.message_id,q.member_id FROM free_queue q
|
|
575
|
+
WHERE NOT EXISTS(SELECT 1 FROM member_requests r WHERE r.message_id=q.message_id AND r.member_id=q.member_id)
|
|
576
|
+
AND NOT EXISTS(SELECT 1 FROM free_queue_waiting w WHERE w.id=q.id);
|
|
577
|
+
-- Owner messages sent while members still work wait here, in position order, and are posted one by one once the room is idle.
|
|
578
|
+
-- `payload` is the message as sent (submission_id included); `failure` holds why posting it failed, which holds the queue.
|
|
579
|
+
CREATE TABLE IF NOT EXISTS queued_messages (
|
|
580
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
581
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
582
|
+
position INTEGER NOT NULL,
|
|
583
|
+
submission_id TEXT NOT NULL,
|
|
584
|
+
payload TEXT NOT NULL,
|
|
585
|
+
failure TEXT NOT NULL DEFAULT '',
|
|
586
|
+
created_at INTEGER NOT NULL,
|
|
587
|
+
UNIQUE(room_id,submission_id)
|
|
588
|
+
);
|
|
589
|
+
CREATE INDEX IF NOT EXISTS queued_messages_room ON queued_messages(room_id,position);
|
|
590
|
+
-- A room's queue paused because the owner stopped members; the owner resumes it.
|
|
591
|
+
CREATE TABLE IF NOT EXISTS queued_message_pauses (
|
|
592
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE
|
|
593
|
+
);
|
|
594
|
+
-- Site-wide composer behaviour: whether messages sent while members work are queued (1) or sent at once (0).
|
|
595
|
+
CREATE TABLE IF NOT EXISTS composer_settings (
|
|
596
|
+
id INTEGER PRIMARY KEY CHECK (id=1),
|
|
597
|
+
queueing INTEGER NOT NULL DEFAULT 1 CHECK (queueing IN (0,1))
|
|
598
|
+
);
|
|
599
|
+
CREATE TRIGGER IF NOT EXISTS queue_waiting_insert AFTER INSERT ON free_queue
|
|
600
|
+
BEGIN
|
|
601
|
+
INSERT INTO free_queue_waiting(id,room_id,message_id,member_id)
|
|
602
|
+
SELECT NEW.id,NEW.room_id,NEW.message_id,NEW.member_id
|
|
603
|
+
WHERE NOT EXISTS(SELECT 1 FROM member_requests WHERE message_id=NEW.message_id AND member_id=NEW.member_id);
|
|
604
|
+
END;
|
|
605
|
+
CREATE TRIGGER IF NOT EXISTS queue_waiting_move AFTER UPDATE OF room_id,message_id,member_id ON free_queue
|
|
606
|
+
BEGIN
|
|
607
|
+
DELETE FROM free_queue_waiting WHERE id=OLD.id;
|
|
608
|
+
INSERT INTO free_queue_waiting(id,room_id,message_id,member_id)
|
|
609
|
+
SELECT NEW.id,NEW.room_id,NEW.message_id,NEW.member_id
|
|
610
|
+
WHERE NOT EXISTS(SELECT 1 FROM member_requests WHERE message_id=NEW.message_id AND member_id=NEW.member_id);
|
|
611
|
+
END;
|
|
612
|
+
CREATE TRIGGER IF NOT EXISTS queue_waiting_requested AFTER INSERT ON member_requests
|
|
613
|
+
BEGIN
|
|
614
|
+
DELETE FROM free_queue_waiting WHERE message_id=NEW.message_id AND member_id=NEW.member_id;
|
|
615
|
+
END;
|
|
616
|
+
CREATE TRIGGER IF NOT EXISTS queue_waiting_request_deleted AFTER DELETE ON member_requests
|
|
617
|
+
BEGIN
|
|
618
|
+
INSERT INTO free_queue_waiting(id,room_id,message_id,member_id)
|
|
619
|
+
SELECT q.id,q.room_id,q.message_id,q.member_id FROM free_queue q
|
|
620
|
+
WHERE q.message_id=OLD.message_id AND q.member_id=OLD.member_id
|
|
621
|
+
AND NOT EXISTS(SELECT 1 FROM member_requests WHERE message_id=q.message_id AND member_id=q.member_id)
|
|
622
|
+
AND NOT EXISTS(SELECT 1 FROM free_queue_waiting WHERE id=q.id);
|
|
623
|
+
END;
|
|
624
|
+
CREATE TRIGGER IF NOT EXISTS queue_waiting_request_moved AFTER UPDATE OF message_id,member_id ON member_requests
|
|
625
|
+
BEGIN
|
|
626
|
+
DELETE FROM free_queue_waiting WHERE message_id=NEW.message_id AND member_id=NEW.member_id;
|
|
627
|
+
INSERT INTO free_queue_waiting(id,room_id,message_id,member_id)
|
|
628
|
+
SELECT q.id,q.room_id,q.message_id,q.member_id FROM free_queue q
|
|
629
|
+
WHERE q.message_id=OLD.message_id AND q.member_id=OLD.member_id
|
|
630
|
+
AND NOT EXISTS(SELECT 1 FROM member_requests WHERE message_id=q.message_id AND member_id=q.member_id)
|
|
631
|
+
AND NOT EXISTS(SELECT 1 FROM free_queue_waiting WHERE id=q.id);
|
|
632
|
+
END;
|
|
633
|
+
CREATE INDEX IF NOT EXISTS free_batches_chain ON free_batches(room_id,chain_id);
|
|
634
|
+
CREATE INDEX IF NOT EXISTS free_batches_unsettled ON free_batches(room_id,batch_id) WHERE settled=0;
|
|
635
|
+
-- The owner's default speaking order (JSON list of member ids); members it lacks follow, the host first, then by joining order.
|
|
636
|
+
CREATE TABLE IF NOT EXISTS speaking_orders (
|
|
637
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE,
|
|
638
|
+
member_ids TEXT NOT NULL
|
|
639
|
+
);
|
|
640
|
+
-- Chains whose automatic progress stopped (budget reached or every dispatched member failed).
|
|
641
|
+
CREATE TABLE IF NOT EXISTS free_chains (
|
|
642
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
643
|
+
chain_id INTEGER NOT NULL,
|
|
644
|
+
reason TEXT NOT NULL,
|
|
645
|
+
PRIMARY KEY (room_id,chain_id)
|
|
646
|
+
);
|
|
647
|
+
-- A host's one-member dispatch that should come back to the host when it ends (several members always do).
|
|
648
|
+
CREATE TABLE IF NOT EXISTS free_handoffs (
|
|
649
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
650
|
+
batch_id INTEGER NOT NULL,
|
|
651
|
+
PRIMARY KEY (room_id,batch_id)
|
|
652
|
+
);
|
|
653
|
+
-- The owner's per-room limit on rounds a host may run from one owner message (a round is one host dispatch, its members'
|
|
654
|
+
-- answers and the hand-back); rooms without a row use the default.
|
|
655
|
+
CREATE TABLE IF NOT EXISTS free_round_limits (
|
|
656
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE,
|
|
657
|
+
max_rounds INTEGER NOT NULL
|
|
658
|
+
);
|
|
659
|
+
-- A chain the owner let run on past its limit: the rounds added, and the dispatch the limit held back, which is sent
|
|
660
|
+
-- when the owner continues (message_id 0 when nothing is held).
|
|
661
|
+
CREATE TABLE IF NOT EXISTS free_chain_holds (
|
|
662
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
663
|
+
chain_id INTEGER NOT NULL,
|
|
664
|
+
extra_rounds INTEGER NOT NULL DEFAULT 0,
|
|
665
|
+
message_id INTEGER NOT NULL DEFAULT 0,
|
|
666
|
+
host_id INTEGER NOT NULL DEFAULT 0,
|
|
667
|
+
names TEXT NOT NULL DEFAULT '[]',
|
|
668
|
+
handoff INTEGER NOT NULL DEFAULT 0,
|
|
669
|
+
PRIMARY KEY (room_id,chain_id)
|
|
670
|
+
);
|
|
671
|
+
-- A discussion is a switch on a room, not a room type: one thin record per started discussion.
|
|
672
|
+
-- Session status is written by the application.
|
|
673
|
+
CREATE TABLE IF NOT EXISTS discussion_sessions (
|
|
674
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
675
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
676
|
+
goal TEXT NOT NULL,
|
|
677
|
+
status TEXT NOT NULL DEFAULT 'paused' CHECK(status IN ('active','paused','concluded')),
|
|
678
|
+
started_message_id INTEGER NOT NULL DEFAULT 0,
|
|
679
|
+
ended_message_id INTEGER NOT NULL DEFAULT 0,
|
|
680
|
+
created_at TEXT NOT NULL
|
|
681
|
+
);
|
|
682
|
+
CREATE UNIQUE INDEX IF NOT EXISTS one_open_session ON discussion_sessions(room_id) WHERE status IN ('active','paused');
|
|
683
|
+
CREATE INDEX IF NOT EXISTS discussion_sessions_room ON discussion_sessions(room_id);
|
|
684
|
+
-- Historical conclusion snapshots are written by the application and remain readable across later discussions.
|
|
685
|
+
CREATE TABLE IF NOT EXISTS discussion_conclusions (
|
|
686
|
+
session_id INTEGER PRIMARY KEY REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
687
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
688
|
+
stop_reason TEXT NOT NULL DEFAULT '',
|
|
689
|
+
max_rounds INTEGER NOT NULL DEFAULT 0,
|
|
690
|
+
max_minutes INTEGER NOT NULL DEFAULT 0,
|
|
691
|
+
brief TEXT NOT NULL DEFAULT '',
|
|
692
|
+
state TEXT NOT NULL DEFAULT '',
|
|
693
|
+
state_until INTEGER NOT NULL DEFAULT 0,
|
|
694
|
+
concluded_at TEXT NOT NULL
|
|
695
|
+
);
|
|
696
|
+
-- Session-scoped settings and state.
|
|
697
|
+
CREATE TABLE IF NOT EXISTS session_start_submissions (
|
|
698
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
699
|
+
submission_id TEXT NOT NULL,
|
|
700
|
+
session_id INTEGER NOT NULL UNIQUE REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
701
|
+
request_json TEXT NOT NULL,
|
|
702
|
+
PRIMARY KEY (room_id,submission_id)
|
|
703
|
+
);
|
|
704
|
+
CREATE TABLE IF NOT EXISTS session_state (
|
|
705
|
+
session_id INTEGER PRIMARY KEY REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
706
|
+
phase TEXT NOT NULL CHECK(phase IN ('initial','discussing')),
|
|
707
|
+
revision INTEGER NOT NULL DEFAULT 0,
|
|
708
|
+
read_until INTEGER NOT NULL DEFAULT 0,
|
|
709
|
+
held_since INTEGER NOT NULL DEFAULT 0
|
|
710
|
+
);
|
|
711
|
+
CREATE TABLE IF NOT EXISTS session_limits (
|
|
712
|
+
session_id INTEGER PRIMARY KEY REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
713
|
+
max_rounds INTEGER NOT NULL DEFAULT 0,
|
|
714
|
+
max_minutes INTEGER NOT NULL DEFAULT 0,
|
|
715
|
+
execution_minutes INTEGER NOT NULL DEFAULT 0,
|
|
716
|
+
started_at INTEGER NOT NULL DEFAULT 0,
|
|
717
|
+
stop_reason TEXT NOT NULL DEFAULT '',
|
|
718
|
+
revision INTEGER NOT NULL DEFAULT 0
|
|
719
|
+
);
|
|
720
|
+
CREATE TABLE IF NOT EXISTS session_round_budgets (
|
|
721
|
+
session_id INTEGER PRIMARY KEY REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
722
|
+
base INTEGER NOT NULL DEFAULT 0,
|
|
723
|
+
cap INTEGER NOT NULL DEFAULT 0,
|
|
724
|
+
extra INTEGER NOT NULL DEFAULT 0
|
|
725
|
+
);
|
|
726
|
+
CREATE TABLE IF NOT EXISTS session_pauses (
|
|
727
|
+
session_id INTEGER PRIMARY KEY REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
728
|
+
paused_at INTEGER NOT NULL DEFAULT 0,
|
|
729
|
+
paused_seconds INTEGER NOT NULL DEFAULT 0
|
|
730
|
+
);
|
|
731
|
+
CREATE TABLE IF NOT EXISTS session_options (
|
|
732
|
+
session_id INTEGER PRIMARY KEY REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
733
|
+
named_followup INTEGER NOT NULL DEFAULT 0 CHECK(named_followup IN (0,1))
|
|
734
|
+
);
|
|
735
|
+
CREATE TABLE IF NOT EXISTS session_requests (
|
|
736
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
737
|
+
session_id INTEGER NOT NULL REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
738
|
+
round INTEGER NOT NULL DEFAULT 0,
|
|
739
|
+
position INTEGER NOT NULL DEFAULT 0,
|
|
740
|
+
member_id INTEGER NOT NULL REFERENCES room_members(id),
|
|
741
|
+
purpose TEXT NOT NULL CHECK(purpose IN ('discuss','discuss_host')),
|
|
742
|
+
question TEXT NOT NULL DEFAULT '',
|
|
743
|
+
status TEXT NOT NULL DEFAULT 'queued'
|
|
744
|
+
CHECK(status IN ('queued','open','answered','failed','skipped','cancelled')),
|
|
745
|
+
member_request_id INTEGER UNIQUE REFERENCES member_requests(id),
|
|
746
|
+
submission_id TEXT NOT NULL,
|
|
747
|
+
read_until INTEGER DEFAULT NULL,
|
|
748
|
+
created_at TEXT NOT NULL,
|
|
749
|
+
UNIQUE(session_id,submission_id)
|
|
750
|
+
);
|
|
751
|
+
CREATE INDEX IF NOT EXISTS session_requests_queue ON session_requests(session_id,status,round,position,id);
|
|
752
|
+
CREATE INDEX IF NOT EXISTS session_requests_rounds ON session_requests(session_id,round,position,id) WHERE purpose='discuss';
|
|
753
|
+
CREATE UNIQUE INDEX IF NOT EXISTS one_open_session_request ON session_requests(session_id)
|
|
754
|
+
WHERE status='open' AND purpose='discuss';
|
|
755
|
+
CREATE TABLE IF NOT EXISTS task_message_sources (
|
|
756
|
+
message_id INTEGER PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE,
|
|
757
|
+
session_id INTEGER NOT NULL REFERENCES discussion_sessions(id) ON DELETE CASCADE,
|
|
758
|
+
session_request_id INTEGER NOT NULL UNIQUE REFERENCES session_requests(id) ON DELETE CASCADE,
|
|
759
|
+
cause_kind TEXT NOT NULL CHECK(cause_kind IN ('session_started','scheduled_speaker','speaker_answered','round_complete','user_message','member_change','request_failed')),
|
|
760
|
+
cause_message_id INTEGER REFERENCES messages(id),
|
|
761
|
+
cause_request_id INTEGER REFERENCES member_requests(id)
|
|
762
|
+
);
|
|
763
|
+
CREATE INDEX IF NOT EXISTS task_message_sources_session ON task_message_sources(session_id,message_id);
|
|
764
|
+
|
|
765
|
+
-- One host-authorized review step for one implementation batch. Imported plans remain history only.
|
|
766
|
+
CREATE TABLE IF NOT EXISTS review_plans (
|
|
767
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
768
|
+
batch_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
769
|
+
chain_id INTEGER NOT NULL,
|
|
770
|
+
host_id INTEGER NOT NULL,
|
|
771
|
+
reviewer_id INTEGER NOT NULL,
|
|
772
|
+
reviewer_name TEXT NOT NULL,
|
|
773
|
+
config_version TEXT NOT NULL,
|
|
774
|
+
member_revision TEXT NOT NULL,
|
|
775
|
+
scope TEXT NOT NULL,
|
|
776
|
+
implementers TEXT NOT NULL,
|
|
777
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','advanced','imported')),
|
|
778
|
+
review_batch_id INTEGER REFERENCES messages(id) ON DELETE SET NULL,
|
|
779
|
+
advance_submission TEXT NOT NULL DEFAULT '',
|
|
780
|
+
PRIMARY KEY(room_id,batch_id)
|
|
781
|
+
);
|
|
782
|
+
CREATE UNIQUE INDEX IF NOT EXISTS review_advance_submission ON review_plans(room_id,advance_submission)
|
|
783
|
+
WHERE advance_submission<>'';
|
|
784
|
+
-- UNION ALL (the two sources never share a message) lets SQLite push a message_id lookup into each indexed arm;
|
|
785
|
+
-- plain UNION materializes both tables on every lookup. Recreated on each schema run so existing databases pick it up.
|
|
786
|
+
DROP VIEW IF EXISTS internal_task_messages;
|
|
787
|
+
CREATE VIEW internal_task_messages AS
|
|
788
|
+
SELECT message_id FROM task_message_sources
|
|
789
|
+
UNION ALL SELECT review_batch_id AS message_id FROM review_plans WHERE review_batch_id IS NOT NULL;
|
|
790
|
+
CREATE INDEX IF NOT EXISTS review_plans_batch_message ON review_plans(review_batch_id);
|
|
791
|
+
|
|
792
|
+
-- Cached directory aggregates: backfill existing rooms once, then maintain them in the same write transaction.
|
|
793
|
+
-- Withdrawal keeps a transcript card, so it does not change these counts. Internal task/review messages do.
|
|
794
|
+
CREATE TABLE IF NOT EXISTS room_message_stats (
|
|
795
|
+
room_id TEXT PRIMARY KEY REFERENCES rooms(id) ON DELETE CASCADE,
|
|
796
|
+
message_count INTEGER NOT NULL DEFAULT 0,
|
|
797
|
+
latest_id INTEGER NOT NULL DEFAULT 0
|
|
798
|
+
);
|
|
799
|
+
INSERT INTO room_message_stats(room_id,message_count,latest_id)
|
|
800
|
+
SELECT r.id,COUNT(m.id),COALESCE(MAX(m.id),0) FROM rooms r
|
|
801
|
+
LEFT JOIN messages m ON m.room_id=r.id
|
|
802
|
+
AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=m.id)
|
|
803
|
+
WHERE NOT EXISTS(SELECT 1 FROM room_message_stats stats WHERE stats.room_id=r.id) GROUP BY r.id;
|
|
804
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_room AFTER INSERT ON rooms
|
|
805
|
+
BEGIN
|
|
806
|
+
INSERT INTO room_message_stats(room_id) VALUES(NEW.id);
|
|
807
|
+
END;
|
|
808
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_insert AFTER INSERT ON messages
|
|
809
|
+
WHEN NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=NEW.id)
|
|
810
|
+
BEGIN
|
|
811
|
+
UPDATE room_message_stats SET message_count=message_count+1,latest_id=MAX(latest_id,NEW.id)
|
|
812
|
+
WHERE room_id=NEW.room_id;
|
|
813
|
+
END;
|
|
814
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_delete BEFORE DELETE ON messages
|
|
815
|
+
WHEN NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=OLD.id)
|
|
816
|
+
BEGIN
|
|
817
|
+
UPDATE room_message_stats SET message_count=message_count-1,
|
|
818
|
+
latest_id=CASE WHEN latest_id=OLD.id THEN (SELECT COALESCE(MAX(m.id),0) FROM messages m
|
|
819
|
+
WHERE m.room_id=room_message_stats.room_id AND m.id<>OLD.id AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=m.id)) ELSE latest_id END
|
|
820
|
+
WHERE room_id=OLD.room_id;
|
|
821
|
+
END;
|
|
822
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_move_before BEFORE UPDATE OF room_id,id ON messages
|
|
823
|
+
WHEN NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=OLD.id)
|
|
824
|
+
BEGIN
|
|
825
|
+
UPDATE room_message_stats SET message_count=message_count-1,
|
|
826
|
+
latest_id=CASE WHEN latest_id=OLD.id THEN (SELECT COALESCE(MAX(m.id),0) FROM messages m
|
|
827
|
+
WHERE m.room_id=room_message_stats.room_id AND m.id<>OLD.id AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=m.id)) ELSE latest_id END
|
|
828
|
+
WHERE room_id=OLD.room_id;
|
|
829
|
+
END;
|
|
830
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_move_after AFTER UPDATE OF room_id,id ON messages
|
|
831
|
+
WHEN NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=NEW.id)
|
|
832
|
+
BEGIN
|
|
833
|
+
UPDATE room_message_stats SET message_count=message_count+1,latest_id=MAX(latest_id,NEW.id)
|
|
834
|
+
WHERE room_id=NEW.room_id;
|
|
835
|
+
END;
|
|
836
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_task_insert AFTER INSERT ON task_message_sources
|
|
837
|
+
WHEN EXISTS(SELECT 1 FROM messages WHERE id=NEW.message_id) AND NOT EXISTS(SELECT 1 FROM review_plans WHERE review_batch_id=NEW.message_id)
|
|
838
|
+
BEGIN
|
|
839
|
+
UPDATE room_message_stats SET message_count=message_count-1,
|
|
840
|
+
latest_id=CASE WHEN latest_id=NEW.message_id THEN (SELECT COALESCE(MAX(m.id),0) FROM messages m
|
|
841
|
+
WHERE m.room_id=room_message_stats.room_id AND m.id<>NEW.message_id AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=m.id)) ELSE latest_id END
|
|
842
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=NEW.message_id);
|
|
843
|
+
END;
|
|
844
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_task_delete AFTER DELETE ON task_message_sources
|
|
845
|
+
WHEN EXISTS(SELECT 1 FROM messages WHERE id=OLD.message_id) AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=OLD.message_id)
|
|
846
|
+
BEGIN
|
|
847
|
+
UPDATE room_message_stats SET message_count=message_count+1,latest_id=MAX(latest_id,OLD.message_id)
|
|
848
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=OLD.message_id);
|
|
849
|
+
END;
|
|
850
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_task_update_old AFTER UPDATE OF message_id ON task_message_sources
|
|
851
|
+
WHEN OLD.message_id IS NOT NEW.message_id AND EXISTS(SELECT 1 FROM messages WHERE id=OLD.message_id) AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=OLD.message_id)
|
|
852
|
+
BEGIN
|
|
853
|
+
UPDATE room_message_stats SET message_count=message_count+1,latest_id=MAX(latest_id,OLD.message_id)
|
|
854
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=OLD.message_id);
|
|
855
|
+
END;
|
|
856
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_task_update_new AFTER UPDATE OF message_id ON task_message_sources
|
|
857
|
+
WHEN OLD.message_id IS NOT NEW.message_id AND EXISTS(SELECT 1 FROM messages WHERE id=NEW.message_id) AND NOT EXISTS(SELECT 1 FROM review_plans WHERE review_batch_id=NEW.message_id)
|
|
858
|
+
BEGIN
|
|
859
|
+
UPDATE room_message_stats SET message_count=message_count-1,
|
|
860
|
+
latest_id=CASE WHEN latest_id=NEW.message_id THEN (SELECT COALESCE(MAX(m.id),0) FROM messages m
|
|
861
|
+
WHERE m.room_id=room_message_stats.room_id AND m.id<>NEW.message_id AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=m.id)) ELSE latest_id END
|
|
862
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=NEW.message_id);
|
|
863
|
+
END;
|
|
864
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_review_insert AFTER INSERT ON review_plans
|
|
865
|
+
WHEN EXISTS(SELECT 1 FROM messages WHERE id=NEW.review_batch_id) AND NOT EXISTS(SELECT 1 FROM task_message_sources WHERE message_id=NEW.review_batch_id)
|
|
866
|
+
AND (SELECT COUNT(*) FROM review_plans WHERE review_batch_id=NEW.review_batch_id)=1
|
|
867
|
+
BEGIN
|
|
868
|
+
UPDATE room_message_stats SET message_count=message_count-1,
|
|
869
|
+
latest_id=CASE WHEN latest_id=NEW.review_batch_id THEN (SELECT COALESCE(MAX(m.id),0) FROM messages m
|
|
870
|
+
WHERE m.room_id=room_message_stats.room_id AND m.id<>NEW.review_batch_id AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=m.id)) ELSE latest_id END
|
|
871
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=NEW.review_batch_id);
|
|
872
|
+
END;
|
|
873
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_review_delete AFTER DELETE ON review_plans
|
|
874
|
+
WHEN EXISTS(SELECT 1 FROM messages WHERE id=OLD.review_batch_id) AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=OLD.review_batch_id)
|
|
875
|
+
BEGIN
|
|
876
|
+
UPDATE room_message_stats SET message_count=message_count+1,latest_id=MAX(latest_id,OLD.review_batch_id)
|
|
877
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=OLD.review_batch_id);
|
|
878
|
+
END;
|
|
879
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_review_update_old AFTER UPDATE OF review_batch_id ON review_plans
|
|
880
|
+
WHEN OLD.review_batch_id IS NOT NEW.review_batch_id AND EXISTS(SELECT 1 FROM messages WHERE id=OLD.review_batch_id) AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=OLD.review_batch_id)
|
|
881
|
+
BEGIN
|
|
882
|
+
UPDATE room_message_stats SET message_count=message_count+1,latest_id=MAX(latest_id,OLD.review_batch_id)
|
|
883
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=OLD.review_batch_id);
|
|
884
|
+
END;
|
|
885
|
+
CREATE TRIGGER IF NOT EXISTS message_stats_review_update_new AFTER UPDATE OF review_batch_id ON review_plans
|
|
886
|
+
WHEN OLD.review_batch_id IS NOT NEW.review_batch_id AND EXISTS(SELECT 1 FROM messages WHERE id=NEW.review_batch_id) AND NOT EXISTS(SELECT 1 FROM task_message_sources WHERE message_id=NEW.review_batch_id)
|
|
887
|
+
AND (SELECT COUNT(*) FROM review_plans WHERE review_batch_id=NEW.review_batch_id)=1
|
|
888
|
+
BEGIN
|
|
889
|
+
UPDATE room_message_stats SET message_count=message_count-1,
|
|
890
|
+
latest_id=CASE WHEN latest_id=NEW.review_batch_id THEN (SELECT COALESCE(MAX(m.id),0) FROM messages m
|
|
891
|
+
WHERE m.room_id=room_message_stats.room_id AND m.id<>NEW.review_batch_id AND NOT EXISTS(SELECT 1 FROM internal_task_messages t WHERE t.message_id=m.id)) ELSE latest_id END
|
|
892
|
+
WHERE room_id=(SELECT room_id FROM messages WHERE id=NEW.review_batch_id);
|
|
893
|
+
END;
|
|
894
|
+
|
|
895
|
+
-- Runtime idempotency receipts for converting one host interjection to an ordinary request.
|
|
896
|
+
CREATE TABLE IF NOT EXISTS session_ask_submissions (
|
|
897
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
898
|
+
submission_id TEXT NOT NULL,
|
|
899
|
+
source_request_id INTEGER NOT NULL UNIQUE REFERENCES member_requests(id) ON DELETE CASCADE,
|
|
900
|
+
request_id INTEGER NOT NULL REFERENCES member_requests(id) ON DELETE CASCADE,
|
|
901
|
+
PRIMARY KEY (room_id,submission_id)
|
|
902
|
+
);
|
|
903
|
+
|
|
904
|
+
-- A computer running the local service, paired by the site administrator. Only project names and ids and the
|
|
905
|
+
-- configured client of each platform are published; directories and credentials stay on that computer.
|
|
906
|
+
CREATE TABLE IF NOT EXISTS local_machines (
|
|
907
|
+
id TEXT PRIMARY KEY,
|
|
908
|
+
name TEXT NOT NULL,
|
|
909
|
+
token_hash TEXT NOT NULL,
|
|
910
|
+
projects TEXT NOT NULL DEFAULT '[]',
|
|
911
|
+
clients TEXT NOT NULL DEFAULT '{}',
|
|
912
|
+
seen_at INTEGER NOT NULL DEFAULT 0,
|
|
913
|
+
created_at INTEGER NOT NULL
|
|
914
|
+
);
|
|
915
|
+
-- A room launch submitted from a device without the local service; the paired computer claims and runs it.
|
|
916
|
+
-- The request (with the room's new credentials) is cleared once the launch finishes or fails.
|
|
917
|
+
CREATE TABLE IF NOT EXISTS remote_launches (
|
|
918
|
+
id TEXT PRIMARY KEY,
|
|
919
|
+
machine_id TEXT NOT NULL,
|
|
920
|
+
request TEXT NOT NULL DEFAULT '{}',
|
|
921
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','claimed','done','failed')),
|
|
922
|
+
result TEXT NOT NULL DEFAULT '{}',
|
|
923
|
+
error TEXT NOT NULL DEFAULT '',
|
|
924
|
+
created_at INTEGER NOT NULL,
|
|
925
|
+
updated_at INTEGER NOT NULL
|
|
926
|
+
);
|
|
927
|
+
CREATE INDEX IF NOT EXISTS remote_launches_machine ON remote_launches(machine_id, status);
|
|
928
|
+
-- The P-256 public key a paired computer publishes so other devices can encrypt commands only it can read.
|
|
929
|
+
CREATE TABLE IF NOT EXISTS machine_keys (
|
|
930
|
+
machine_id TEXT PRIMARY KEY,
|
|
931
|
+
public_key TEXT NOT NULL
|
|
932
|
+
);
|
|
933
|
+
-- A local-service operation relayed from a device without the local service. Request and response are end-to-end
|
|
934
|
+
-- encrypted between that device and the computer, so the site never holds keys, paths or results in plaintext;
|
|
935
|
+
-- the request is cleared once claimed and the row is deleted once read or expired.
|
|
936
|
+
CREATE TABLE IF NOT EXISTS machine_commands (
|
|
937
|
+
id TEXT PRIMARY KEY,
|
|
938
|
+
machine_id TEXT NOT NULL,
|
|
939
|
+
request TEXT NOT NULL DEFAULT '{}',
|
|
940
|
+
response TEXT NOT NULL DEFAULT '{}',
|
|
941
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','claimed','done')),
|
|
942
|
+
created_at INTEGER NOT NULL,
|
|
943
|
+
updated_at INTEGER NOT NULL
|
|
944
|
+
);
|
|
945
|
+
CREATE INDEX IF NOT EXISTS machine_commands_machine ON machine_commands(machine_id, status);
|
|
946
|
+
|
|
947
|
+
-- Change revisions, so idle rooms are not read on every poll. Every write a reader could show or act on gives its room the next
|
|
948
|
+
-- value of one site-wide sequence: a room's revision tells a runner or page that this room changed, and the largest revision
|
|
949
|
+
-- (read through the index) tells a page that anything on the site changed. The '' row stands for directory-only changes.
|
|
950
|
+
-- Triggers update or insert without conflicts, so an outer INSERT OR IGNORE cannot override them into skipping the bump.
|
|
951
|
+
CREATE TABLE IF NOT EXISTS room_revisions (
|
|
952
|
+
room_id TEXT PRIMARY KEY,
|
|
953
|
+
revision INTEGER NOT NULL
|
|
954
|
+
);
|
|
955
|
+
CREATE INDEX IF NOT EXISTS room_revisions_order ON room_revisions(revision);
|
|
956
|
+
DROP TRIGGER IF EXISTS revision_message_insert;
|
|
957
|
+
CREATE TRIGGER revision_message_insert AFTER INSERT ON messages
|
|
958
|
+
BEGIN
|
|
959
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
960
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
961
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
962
|
+
END;
|
|
963
|
+
DROP TRIGGER IF EXISTS revision_message_update;
|
|
964
|
+
CREATE TRIGGER revision_message_update AFTER UPDATE ON messages
|
|
965
|
+
BEGIN
|
|
966
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
967
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
968
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
969
|
+
END;
|
|
970
|
+
DROP TRIGGER IF EXISTS revision_message_withdrawal;
|
|
971
|
+
CREATE TRIGGER revision_message_withdrawal AFTER INSERT ON message_withdrawals
|
|
972
|
+
BEGIN
|
|
973
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=(SELECT room_id FROM messages WHERE id=NEW.message_id);
|
|
974
|
+
INSERT INTO room_revisions (room_id,revision) SELECT (SELECT room_id FROM messages WHERE id=NEW.message_id),(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
975
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=(SELECT room_id FROM messages WHERE id=NEW.message_id));
|
|
976
|
+
END;
|
|
977
|
+
DROP TRIGGER IF EXISTS revision_member_insert;
|
|
978
|
+
CREATE TRIGGER revision_member_insert AFTER INSERT ON room_members
|
|
979
|
+
BEGIN
|
|
980
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
981
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
982
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
983
|
+
END;
|
|
984
|
+
DROP TRIGGER IF EXISTS revision_member_update;
|
|
985
|
+
CREATE TRIGGER revision_member_update AFTER UPDATE ON room_members
|
|
986
|
+
BEGIN
|
|
987
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
988
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
989
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
990
|
+
END;
|
|
991
|
+
DROP TRIGGER IF EXISTS revision_registration_insert;
|
|
992
|
+
CREATE TRIGGER revision_registration_insert AFTER INSERT ON member_registrations
|
|
993
|
+
BEGIN
|
|
994
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
995
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
996
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
997
|
+
END;
|
|
998
|
+
DROP TRIGGER IF EXISTS revision_registration_update;
|
|
999
|
+
CREATE TRIGGER revision_registration_update AFTER UPDATE ON member_registrations
|
|
1000
|
+
BEGIN
|
|
1001
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1002
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1003
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1004
|
+
END;
|
|
1005
|
+
DROP TRIGGER IF EXISTS revision_session_report_insert;
|
|
1006
|
+
CREATE TRIGGER revision_session_report_insert AFTER INSERT ON member_sessions
|
|
1007
|
+
BEGIN
|
|
1008
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1009
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1010
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1011
|
+
END;
|
|
1012
|
+
DROP TRIGGER IF EXISTS revision_adopt_failure_insert;
|
|
1013
|
+
CREATE TRIGGER revision_adopt_failure_insert AFTER INSERT ON member_adopt_failures
|
|
1014
|
+
BEGIN
|
|
1015
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1016
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1017
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1018
|
+
END;
|
|
1019
|
+
DROP TRIGGER IF EXISTS revision_session_report_update;
|
|
1020
|
+
CREATE TRIGGER revision_session_report_update AFTER UPDATE ON member_sessions
|
|
1021
|
+
WHEN OLD.session_id IS NOT NEW.session_id OR OLD.client IS NOT NEW.client
|
|
1022
|
+
BEGIN
|
|
1023
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1024
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1025
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1026
|
+
END;
|
|
1027
|
+
DROP TRIGGER IF EXISTS revision_request_insert;
|
|
1028
|
+
CREATE TRIGGER revision_request_insert AFTER INSERT ON member_requests
|
|
1029
|
+
BEGIN
|
|
1030
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1031
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1032
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1033
|
+
END;
|
|
1034
|
+
DROP TRIGGER IF EXISTS revision_request_status;
|
|
1035
|
+
CREATE TRIGGER revision_request_status AFTER UPDATE OF status ON member_requests
|
|
1036
|
+
WHEN OLD.status IS NOT NEW.status
|
|
1037
|
+
BEGIN
|
|
1038
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1039
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1040
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1041
|
+
END;
|
|
1042
|
+
DROP TRIGGER IF EXISTS revision_execution_insert;
|
|
1043
|
+
CREATE TRIGGER revision_execution_insert AFTER INSERT ON member_executions
|
|
1044
|
+
BEGIN
|
|
1045
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1046
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1047
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1048
|
+
END;
|
|
1049
|
+
DROP TRIGGER IF EXISTS revision_execution_status;
|
|
1050
|
+
CREATE TRIGGER revision_execution_status AFTER UPDATE OF status ON member_executions
|
|
1051
|
+
WHEN OLD.status IS NOT NEW.status
|
|
1052
|
+
BEGIN
|
|
1053
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1054
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1055
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1056
|
+
END;
|
|
1057
|
+
-- Non-progress execution reports must invalidate full views even without SSE. Renewals/notes stay lightweight.
|
|
1058
|
+
CREATE TRIGGER IF NOT EXISTS revision_execution_report AFTER UPDATE OF changes,result,session_id ON member_executions
|
|
1059
|
+
WHEN OLD.changes IS NOT NEW.changes OR OLD.result IS NOT NEW.result OR OLD.session_id IS NOT NEW.session_id
|
|
1060
|
+
BEGIN
|
|
1061
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1062
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1063
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1064
|
+
END;
|
|
1065
|
+
CREATE TRIGGER IF NOT EXISTS revision_capability_insert AFTER INSERT ON execution_capabilities
|
|
1066
|
+
BEGIN
|
|
1067
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1068
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1069
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1070
|
+
END;
|
|
1071
|
+
CREATE TRIGGER IF NOT EXISTS revision_capability_update AFTER UPDATE ON execution_capabilities
|
|
1072
|
+
WHEN OLD.stoppable IS NOT NEW.stoppable OR OLD.progress IS NOT NEW.progress OR OLD.stop_result IS NOT NEW.stop_result
|
|
1073
|
+
BEGIN
|
|
1074
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1075
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1076
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1077
|
+
END;
|
|
1078
|
+
CREATE TRIGGER IF NOT EXISTS revision_denials_insert AFTER INSERT ON execution_denials
|
|
1079
|
+
BEGIN
|
|
1080
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1081
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1082
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1083
|
+
END;
|
|
1084
|
+
CREATE TRIGGER IF NOT EXISTS revision_late_answer AFTER INSERT ON late_answers
|
|
1085
|
+
BEGIN
|
|
1086
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1087
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1088
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1089
|
+
END;
|
|
1090
|
+
DROP TRIGGER IF EXISTS revision_retry_insert;
|
|
1091
|
+
CREATE TRIGGER revision_retry_insert AFTER INSERT ON execution_retries
|
|
1092
|
+
BEGIN
|
|
1093
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1094
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1095
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1096
|
+
END;
|
|
1097
|
+
DROP TRIGGER IF EXISTS revision_retry_update;
|
|
1098
|
+
CREATE TRIGGER revision_retry_update AFTER UPDATE ON execution_retries
|
|
1099
|
+
BEGIN
|
|
1100
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1101
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1102
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1103
|
+
END;
|
|
1104
|
+
DROP TRIGGER IF EXISTS revision_discussion_insert;
|
|
1105
|
+
CREATE TRIGGER revision_discussion_insert AFTER INSERT ON discussion_sessions
|
|
1106
|
+
BEGIN
|
|
1107
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1108
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1109
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1110
|
+
END;
|
|
1111
|
+
DROP TRIGGER IF EXISTS revision_discussion_status;
|
|
1112
|
+
CREATE TRIGGER revision_discussion_status AFTER UPDATE OF status ON discussion_sessions
|
|
1113
|
+
WHEN OLD.status IS NOT NEW.status
|
|
1114
|
+
BEGIN
|
|
1115
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1116
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1117
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1118
|
+
END;
|
|
1119
|
+
DROP TRIGGER IF EXISTS revision_plan_insert;
|
|
1120
|
+
CREATE TRIGGER revision_plan_insert AFTER INSERT ON session_requests
|
|
1121
|
+
BEGIN
|
|
1122
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id);
|
|
1123
|
+
INSERT INTO room_revisions (room_id,revision) SELECT (SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id),(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1124
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id));
|
|
1125
|
+
END;
|
|
1126
|
+
DROP TRIGGER IF EXISTS revision_plan_status;
|
|
1127
|
+
CREATE TRIGGER revision_plan_status AFTER UPDATE OF status ON session_requests
|
|
1128
|
+
WHEN OLD.status IS NOT NEW.status
|
|
1129
|
+
BEGIN
|
|
1130
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id);
|
|
1131
|
+
INSERT INTO room_revisions (room_id,revision) SELECT (SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id),(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1132
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id));
|
|
1133
|
+
END;
|
|
1134
|
+
DROP TRIGGER IF EXISTS revision_session_phase;
|
|
1135
|
+
CREATE TRIGGER revision_session_phase AFTER UPDATE OF phase ON session_state
|
|
1136
|
+
WHEN OLD.phase IS NOT NEW.phase
|
|
1137
|
+
BEGIN
|
|
1138
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id);
|
|
1139
|
+
INSERT INTO room_revisions (room_id,revision) SELECT (SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id),(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1140
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id));
|
|
1141
|
+
END;
|
|
1142
|
+
DROP TRIGGER IF EXISTS revision_session_limits;
|
|
1143
|
+
CREATE TRIGGER revision_session_limits AFTER UPDATE ON session_limits
|
|
1144
|
+
BEGIN
|
|
1145
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id);
|
|
1146
|
+
INSERT INTO room_revisions (room_id,revision) SELECT (SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id),(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1147
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=(SELECT room_id FROM discussion_sessions WHERE id=NEW.session_id));
|
|
1148
|
+
END;
|
|
1149
|
+
DROP TRIGGER IF EXISTS revision_topic_update;
|
|
1150
|
+
CREATE TRIGGER revision_topic_update AFTER UPDATE ON topic_settings
|
|
1151
|
+
BEGIN
|
|
1152
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1153
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1154
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1155
|
+
END;
|
|
1156
|
+
DROP TRIGGER IF EXISTS revision_brief_insert;
|
|
1157
|
+
CREATE TRIGGER revision_brief_insert AFTER INSERT ON room_briefs
|
|
1158
|
+
BEGIN
|
|
1159
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1160
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1161
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1162
|
+
END;
|
|
1163
|
+
DROP TRIGGER IF EXISTS revision_brief_update;
|
|
1164
|
+
CREATE TRIGGER revision_brief_update AFTER UPDATE ON room_briefs
|
|
1165
|
+
BEGIN
|
|
1166
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1167
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1168
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1169
|
+
END;
|
|
1170
|
+
DROP TRIGGER IF EXISTS revision_user_request_insert;
|
|
1171
|
+
CREATE TRIGGER revision_user_request_insert AFTER INSERT ON room_user_requests
|
|
1172
|
+
BEGIN
|
|
1173
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1174
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1175
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1176
|
+
END;
|
|
1177
|
+
DROP TRIGGER IF EXISTS revision_user_request_update;
|
|
1178
|
+
CREATE TRIGGER revision_user_request_update AFTER UPDATE ON room_user_requests
|
|
1179
|
+
BEGIN
|
|
1180
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1181
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1182
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1183
|
+
END;
|
|
1184
|
+
DROP TRIGGER IF EXISTS revision_decision_insert;
|
|
1185
|
+
CREATE TRIGGER revision_decision_insert AFTER INSERT ON scheduler_decisions
|
|
1186
|
+
BEGIN
|
|
1187
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1188
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1189
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1190
|
+
END;
|
|
1191
|
+
DROP TRIGGER IF EXISTS revision_recommendation_insert;
|
|
1192
|
+
CREATE TRIGGER revision_recommendation_insert AFTER INSERT ON member_recommendations
|
|
1193
|
+
BEGIN
|
|
1194
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1195
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1196
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1197
|
+
END;
|
|
1198
|
+
DROP TRIGGER IF EXISTS revision_recommendation_status;
|
|
1199
|
+
CREATE TRIGGER revision_recommendation_status AFTER UPDATE OF status ON member_recommendations
|
|
1200
|
+
WHEN OLD.status IS NOT NEW.status
|
|
1201
|
+
BEGIN
|
|
1202
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1203
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1204
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1205
|
+
END;
|
|
1206
|
+
DROP TRIGGER IF EXISTS revision_description_insert;
|
|
1207
|
+
CREATE TRIGGER revision_description_insert AFTER INSERT ON member_descriptions
|
|
1208
|
+
BEGIN
|
|
1209
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1210
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1211
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1212
|
+
END;
|
|
1213
|
+
DROP TRIGGER IF EXISTS revision_description_update;
|
|
1214
|
+
CREATE TRIGGER revision_description_update AFTER UPDATE ON member_descriptions
|
|
1215
|
+
BEGIN
|
|
1216
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1217
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1218
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1219
|
+
END;
|
|
1220
|
+
DROP TRIGGER IF EXISTS revision_label_insert;
|
|
1221
|
+
CREATE TRIGGER revision_label_insert AFTER INSERT ON member_labels
|
|
1222
|
+
BEGIN
|
|
1223
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1224
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1225
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1226
|
+
END;
|
|
1227
|
+
DROP TRIGGER IF EXISTS revision_label_update;
|
|
1228
|
+
CREATE TRIGGER revision_label_update AFTER UPDATE ON member_labels
|
|
1229
|
+
BEGIN
|
|
1230
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1231
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1232
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1233
|
+
END;
|
|
1234
|
+
DROP TRIGGER IF EXISTS revision_order_insert;
|
|
1235
|
+
CREATE TRIGGER revision_order_insert AFTER INSERT ON speaking_orders
|
|
1236
|
+
BEGIN
|
|
1237
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1238
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1239
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1240
|
+
END;
|
|
1241
|
+
DROP TRIGGER IF EXISTS revision_order_update;
|
|
1242
|
+
CREATE TRIGGER revision_order_update AFTER UPDATE ON speaking_orders
|
|
1243
|
+
BEGIN
|
|
1244
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1245
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1246
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1247
|
+
END;
|
|
1248
|
+
DROP TRIGGER IF EXISTS revision_room_insert;
|
|
1249
|
+
CREATE TRIGGER revision_room_insert AFTER INSERT ON rooms
|
|
1250
|
+
BEGIN
|
|
1251
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.id;
|
|
1252
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1253
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.id);
|
|
1254
|
+
END;
|
|
1255
|
+
DROP TRIGGER IF EXISTS revision_room_update;
|
|
1256
|
+
CREATE TRIGGER revision_room_update AFTER UPDATE ON rooms
|
|
1257
|
+
BEGIN
|
|
1258
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.id;
|
|
1259
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1260
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.id);
|
|
1261
|
+
END;
|
|
1262
|
+
DROP TRIGGER IF EXISTS revision_room_delete;
|
|
1263
|
+
CREATE TRIGGER revision_room_delete AFTER DELETE ON rooms
|
|
1264
|
+
BEGIN
|
|
1265
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1266
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1267
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1268
|
+
END;
|
|
1269
|
+
DROP TRIGGER IF EXISTS revision_directory_update;
|
|
1270
|
+
CREATE TRIGGER revision_directory_update AFTER UPDATE ON room_directory
|
|
1271
|
+
BEGIN
|
|
1272
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1273
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1274
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1275
|
+
END;
|
|
1276
|
+
DROP TRIGGER IF EXISTS revision_assignment_update;
|
|
1277
|
+
CREATE TRIGGER revision_assignment_update AFTER UPDATE ON room_folder_assignments
|
|
1278
|
+
BEGIN
|
|
1279
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1280
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1281
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1282
|
+
END;
|
|
1283
|
+
DROP TRIGGER IF EXISTS revision_folder_insert;
|
|
1284
|
+
CREATE TRIGGER revision_folder_insert AFTER INSERT ON topic_folders
|
|
1285
|
+
BEGIN
|
|
1286
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1287
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1288
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1289
|
+
END;
|
|
1290
|
+
DROP TRIGGER IF EXISTS revision_folder_update;
|
|
1291
|
+
CREATE TRIGGER revision_folder_update AFTER UPDATE ON topic_folders
|
|
1292
|
+
BEGIN
|
|
1293
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1294
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1295
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1296
|
+
END;
|
|
1297
|
+
DROP TRIGGER IF EXISTS revision_folder_delete;
|
|
1298
|
+
CREATE TRIGGER revision_folder_delete AFTER DELETE ON topic_folders
|
|
1299
|
+
BEGIN
|
|
1300
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1301
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1302
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1303
|
+
END;
|
|
1304
|
+
DROP TRIGGER IF EXISTS revision_queued_message_insert;
|
|
1305
|
+
CREATE TRIGGER revision_queued_message_insert AFTER INSERT ON queued_messages
|
|
1306
|
+
BEGIN
|
|
1307
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1308
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1309
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1310
|
+
END;
|
|
1311
|
+
DROP TRIGGER IF EXISTS revision_queued_message_update;
|
|
1312
|
+
CREATE TRIGGER revision_queued_message_update AFTER UPDATE ON queued_messages
|
|
1313
|
+
BEGIN
|
|
1314
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1315
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1316
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1317
|
+
END;
|
|
1318
|
+
DROP TRIGGER IF EXISTS revision_queued_message_delete;
|
|
1319
|
+
CREATE TRIGGER revision_queued_message_delete AFTER DELETE ON queued_messages
|
|
1320
|
+
BEGIN
|
|
1321
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=OLD.room_id;
|
|
1322
|
+
INSERT INTO room_revisions (room_id,revision) SELECT OLD.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1323
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=OLD.room_id);
|
|
1324
|
+
END;
|
|
1325
|
+
DROP TRIGGER IF EXISTS revision_queue_pause_insert;
|
|
1326
|
+
CREATE TRIGGER revision_queue_pause_insert AFTER INSERT ON queued_message_pauses
|
|
1327
|
+
BEGIN
|
|
1328
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=NEW.room_id;
|
|
1329
|
+
INSERT INTO room_revisions (room_id,revision) SELECT NEW.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1330
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=NEW.room_id);
|
|
1331
|
+
END;
|
|
1332
|
+
DROP TRIGGER IF EXISTS revision_queue_pause_delete;
|
|
1333
|
+
CREATE TRIGGER revision_queue_pause_delete AFTER DELETE ON queued_message_pauses
|
|
1334
|
+
BEGIN
|
|
1335
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id=OLD.room_id;
|
|
1336
|
+
INSERT INTO room_revisions (room_id,revision) SELECT OLD.room_id,(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1337
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id=OLD.room_id);
|
|
1338
|
+
END;
|
|
1339
|
+
DROP TRIGGER IF EXISTS revision_composer_settings_insert;
|
|
1340
|
+
CREATE TRIGGER revision_composer_settings_insert AFTER INSERT ON composer_settings
|
|
1341
|
+
BEGIN
|
|
1342
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1343
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1344
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1345
|
+
END;
|
|
1346
|
+
DROP TRIGGER IF EXISTS revision_composer_settings_update;
|
|
1347
|
+
CREATE TRIGGER revision_composer_settings_update AFTER UPDATE ON composer_settings
|
|
1348
|
+
BEGIN
|
|
1349
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1350
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1351
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1352
|
+
END;
|
|
1353
|
+
DROP TRIGGER IF EXISTS revision_directory_settings;
|
|
1354
|
+
CREATE TRIGGER revision_directory_settings AFTER UPDATE ON directory_settings
|
|
1355
|
+
BEGIN
|
|
1356
|
+
UPDATE room_revisions SET revision=(SELECT MAX(revision)+1 FROM room_revisions) WHERE room_id='';
|
|
1357
|
+
INSERT INTO room_revisions (room_id,revision) SELECT '',(SELECT COALESCE(MAX(revision),0)+1 FROM room_revisions)
|
|
1358
|
+
WHERE NOT EXISTS (SELECT 1 FROM room_revisions WHERE room_id='');
|
|
1359
|
+
END;
|
|
1360
|
+
-- The platform once called Gemini is identified as Antigravity (the software); screens still show the nickname Gemini.
|
|
1361
|
+
-- Member names move to the new ID, with any instance suffix (Gemini-2 → Antigravity-2); names inside stored JSON follow.
|
|
1362
|
+
-- Message text keeps what was written. Each statement only touches rows still holding the old ID, so reruns change nothing.
|
|
1363
|
+
UPDATE room_members SET name='Antigravity'||substr(name,7) WHERE name='Gemini' OR name GLOB 'Gemini-*';
|
|
1364
|
+
UPDATE messages SET author='Antigravity'||substr(author,7) WHERE author='Gemini' OR author GLOB 'Gemini-*';
|
|
1365
|
+
UPDATE message_summaries SET author='Antigravity'||substr(author,7) WHERE author='Gemini' OR author GLOB 'Gemini-*';
|
|
1366
|
+
UPDATE message_details SET submitted_by='Antigravity'||substr(submitted_by,7) WHERE submitted_by='Gemini' OR submitted_by GLOB 'Gemini-*';
|
|
1367
|
+
UPDATE attachments SET actor='Antigravity'||substr(actor,7) WHERE actor='Gemini' OR actor GLOB 'Gemini-*';
|
|
1368
|
+
UPDATE topic_settings SET host='Antigravity'||substr(host,7) WHERE host='Gemini' OR host GLOB 'Gemini-*';
|
|
1369
|
+
UPDATE member_descriptions SET name='Antigravity'||substr(name,7) WHERE name='Gemini' OR name GLOB 'Gemini-*';
|
|
1370
|
+
UPDATE member_labels SET name='Antigravity'||substr(name,7) WHERE name='Gemini' OR name GLOB 'Gemini-*';
|
|
1371
|
+
UPDATE scheduler_feedback SET should_be='Antigravity'||substr(should_be,7) WHERE should_be='Gemini' OR should_be GLOB 'Gemini-*';
|
|
1372
|
+
UPDATE scheduler_feedback_cases SET should_be='Antigravity'||substr(should_be,7) WHERE should_be='Gemini' OR should_be GLOB 'Gemini-*';
|
|
1373
|
+
UPDATE review_plans SET reviewer_name='Antigravity'||substr(reviewer_name,7) WHERE reviewer_name='Gemini' OR reviewer_name GLOB 'Gemini-*';
|
|
1374
|
+
UPDATE topic_settings SET experts=replace(replace(experts,'"Gemini"','"Antigravity"'),'"Gemini-','"Antigravity-') WHERE experts LIKE '%"Gemini%';
|
|
1375
|
+
UPDATE free_chain_holds SET names=replace(replace(names,'"Gemini"','"Antigravity"'),'"Gemini-','"Antigravity-') WHERE names LIKE '%"Gemini%';
|
|
1376
|
+
UPDATE room_creations SET request_text=replace(replace(request_text,'"Gemini"','"Antigravity"'),'"Gemini-','"Antigravity-') WHERE request_text LIKE '%"Gemini%';
|
|
1377
|
+
UPDATE session_start_submissions SET request_json=replace(replace(request_json,'"Gemini"','"Antigravity"'),'"Gemini-','"Antigravity-') WHERE request_json LIKE '%"Gemini%';
|
|
1378
|
+
UPDATE scheduler_decision_inputs SET input=replace(replace(input,'"Gemini"','"Antigravity"'),'"Gemini-','"Antigravity-') WHERE input LIKE '%"Gemini%';
|
|
1379
|
+
-- Room event log: an append-only record of each room state change, written by the triggers below so every code path
|
|
1380
|
+
-- is covered and later edits cannot forget it. State tables are overwritten in place; this log keeps the order of
|
|
1381
|
+
-- what happened (which request was created under which message, why it was cancelled, which batch handed back) so the
|
|
1382
|
+
-- timeline page can list and replay it. `at` is epoch milliseconds; `data` holds ids, names resolve at read time.
|
|
1383
|
+
CREATE TABLE IF NOT EXISTS room_events (
|
|
1384
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1385
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
1386
|
+
at INTEGER NOT NULL,
|
|
1387
|
+
kind TEXT NOT NULL,
|
|
1388
|
+
data TEXT NOT NULL DEFAULT '{}'
|
|
1389
|
+
);
|
|
1390
|
+
CREATE INDEX IF NOT EXISTS room_events_room ON room_events(room_id,id);
|
|
1391
|
+
DROP TRIGGER IF EXISTS event_message_posted;
|
|
1392
|
+
CREATE TRIGGER event_message_posted AFTER INSERT ON messages
|
|
1393
|
+
BEGIN
|
|
1394
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'message.posted',
|
|
1395
|
+
json_object('message_id',NEW.id,'author',NEW.author,'source',NEW.source,'reply_to',NEW.reply_to,'text',substr(NEW.text,1,80)));
|
|
1396
|
+
END;
|
|
1397
|
+
DROP TRIGGER IF EXISTS event_message_withdrawn;
|
|
1398
|
+
CREATE TRIGGER event_message_withdrawn AFTER INSERT ON message_withdrawals
|
|
1399
|
+
BEGIN
|
|
1400
|
+
INSERT INTO room_events (room_id,at,kind,data) SELECT room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'message.withdrawn',
|
|
1401
|
+
json_object('message_id',NEW.message_id,'kind',NEW.kind) FROM messages WHERE id=NEW.message_id;
|
|
1402
|
+
END;
|
|
1403
|
+
DROP TRIGGER IF EXISTS event_room_rewound;
|
|
1404
|
+
CREATE TRIGGER event_room_rewound AFTER INSERT ON room_rewinds
|
|
1405
|
+
BEGIN
|
|
1406
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'room.rewound',
|
|
1407
|
+
json_object('rewind_id',NEW.id,'message_id',NEW.message_id));
|
|
1408
|
+
END;
|
|
1409
|
+
DROP TRIGGER IF EXISTS event_member_joined;
|
|
1410
|
+
CREATE TRIGGER event_member_joined AFTER INSERT ON room_members
|
|
1411
|
+
BEGIN
|
|
1412
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'member.joined',
|
|
1413
|
+
json_object('member_id',NEW.id,'role',NEW.role,'status',NEW.status,'adapter',NEW.adapter));
|
|
1414
|
+
END;
|
|
1415
|
+
DROP TRIGGER IF EXISTS event_member_changed;
|
|
1416
|
+
CREATE TRIGGER event_member_changed AFTER UPDATE OF role,status ON room_members
|
|
1417
|
+
WHEN OLD.role IS NOT NEW.role OR OLD.status IS NOT NEW.status
|
|
1418
|
+
BEGIN
|
|
1419
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'member.changed',
|
|
1420
|
+
json_object('member_id',NEW.id,'role',NEW.role,'status',NEW.status,'from_role',OLD.role,'from_status',OLD.status));
|
|
1421
|
+
END;
|
|
1422
|
+
DROP TRIGGER IF EXISTS event_request_created;
|
|
1423
|
+
CREATE TRIGGER event_request_created AFTER INSERT ON member_requests
|
|
1424
|
+
BEGIN
|
|
1425
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'request.created',
|
|
1426
|
+
json_object('request_id',NEW.id,'member_id',NEW.member_id,'message_id',NEW.message_id,'purpose',NEW.purpose,
|
|
1427
|
+
'created_by',NEW.created_by,'chain_id',NEW.chain_id,'batch_id',NEW.batch_id,'status',NEW.status));
|
|
1428
|
+
END;
|
|
1429
|
+
DROP TRIGGER IF EXISTS event_request_changed;
|
|
1430
|
+
CREATE TRIGGER event_request_changed AFTER UPDATE OF status,execution_id,answer_id ON member_requests
|
|
1431
|
+
WHEN OLD.status IS NOT NEW.status OR OLD.execution_id IS NOT NEW.execution_id OR OLD.answer_id IS NOT NEW.answer_id
|
|
1432
|
+
BEGIN
|
|
1433
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'request.changed',
|
|
1434
|
+
json_object('request_id',NEW.id,'member_id',NEW.member_id,'message_id',NEW.message_id,'status',NEW.status,
|
|
1435
|
+
'from_status',OLD.status,'execution_id',NEW.execution_id,'answer_id',NEW.answer_id));
|
|
1436
|
+
END;
|
|
1437
|
+
DROP TRIGGER IF EXISTS event_request_cancel_reason;
|
|
1438
|
+
CREATE TRIGGER event_request_cancel_reason AFTER INSERT ON request_cancel_reasons
|
|
1439
|
+
BEGIN
|
|
1440
|
+
INSERT INTO room_events (room_id,at,kind,data) SELECT room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'request.cancel_reason',
|
|
1441
|
+
json_object('request_id',NEW.request_id,'member_id',member_id,'reason',NEW.reason) FROM member_requests WHERE id=NEW.request_id;
|
|
1442
|
+
END;
|
|
1443
|
+
DROP TRIGGER IF EXISTS event_execution_created;
|
|
1444
|
+
CREATE TRIGGER event_execution_created AFTER INSERT ON member_executions
|
|
1445
|
+
BEGIN
|
|
1446
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'execution.created',
|
|
1447
|
+
json_object('execution_id',NEW.id,'member_id',NEW.member_id,'status',NEW.status));
|
|
1448
|
+
END;
|
|
1449
|
+
DROP TRIGGER IF EXISTS event_execution_changed;
|
|
1450
|
+
CREATE TRIGGER event_execution_changed AFTER UPDATE OF status ON member_executions
|
|
1451
|
+
WHEN OLD.status IS NOT NEW.status
|
|
1452
|
+
BEGIN
|
|
1453
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'execution.changed',
|
|
1454
|
+
json_object('execution_id',NEW.id,'member_id',NEW.member_id,'status',NEW.status,'from_status',OLD.status,'result',substr(NEW.result,1,200)));
|
|
1455
|
+
END;
|
|
1456
|
+
DROP TRIGGER IF EXISTS event_execution_retry;
|
|
1457
|
+
CREATE TRIGGER event_execution_retry AFTER INSERT ON execution_retries
|
|
1458
|
+
BEGIN
|
|
1459
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'execution.retry',
|
|
1460
|
+
json_object('execution_id',NEW.execution_id,'attempt',NEW.attempt,'retry_at',NEW.retry_at,'reason',substr(NEW.reason,1,200),'stopped',NEW.stopped));
|
|
1461
|
+
END;
|
|
1462
|
+
DROP TRIGGER IF EXISTS event_execution_retry_changed;
|
|
1463
|
+
CREATE TRIGGER event_execution_retry_changed AFTER UPDATE ON execution_retries
|
|
1464
|
+
WHEN OLD.attempt IS NOT NEW.attempt OR OLD.stopped IS NOT NEW.stopped
|
|
1465
|
+
BEGIN
|
|
1466
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'execution.retry',
|
|
1467
|
+
json_object('execution_id',NEW.execution_id,'attempt',NEW.attempt,'retry_at',NEW.retry_at,'reason',substr(NEW.reason,1,200),'stopped',NEW.stopped));
|
|
1468
|
+
END;
|
|
1469
|
+
DROP TRIGGER IF EXISTS event_execution_late_answer;
|
|
1470
|
+
CREATE TRIGGER event_execution_late_answer AFTER INSERT ON late_answers
|
|
1471
|
+
BEGIN
|
|
1472
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'execution.late_answer',
|
|
1473
|
+
json_object('execution_id',NEW.execution_id,'text',substr(NEW.text,1,80)));
|
|
1474
|
+
END;
|
|
1475
|
+
DROP TRIGGER IF EXISTS event_batch_opened;
|
|
1476
|
+
CREATE TRIGGER event_batch_opened AFTER INSERT ON free_batches
|
|
1477
|
+
BEGIN
|
|
1478
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'batch.opened',
|
|
1479
|
+
json_object('batch_id',NEW.batch_id,'chain_id',NEW.chain_id,'host_id',NEW.host_id));
|
|
1480
|
+
END;
|
|
1481
|
+
DROP TRIGGER IF EXISTS event_batch_settled;
|
|
1482
|
+
CREATE TRIGGER event_batch_settled AFTER UPDATE OF settled ON free_batches
|
|
1483
|
+
WHEN OLD.settled IS NOT NEW.settled
|
|
1484
|
+
BEGIN
|
|
1485
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'batch.settled',
|
|
1486
|
+
json_object('batch_id',NEW.batch_id,'chain_id',NEW.chain_id,'settled',NEW.settled));
|
|
1487
|
+
END;
|
|
1488
|
+
DROP TRIGGER IF EXISTS event_batch_handoff;
|
|
1489
|
+
CREATE TRIGGER event_batch_handoff AFTER INSERT ON free_handoffs
|
|
1490
|
+
BEGIN
|
|
1491
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'batch.handoff',
|
|
1492
|
+
json_object('batch_id',NEW.batch_id));
|
|
1493
|
+
END;
|
|
1494
|
+
DROP TRIGGER IF EXISTS event_queue_added;
|
|
1495
|
+
CREATE TRIGGER event_queue_added AFTER INSERT ON free_queue
|
|
1496
|
+
BEGIN
|
|
1497
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'queue.added',
|
|
1498
|
+
json_object('queue_id',NEW.id,'message_id',NEW.message_id,'member_id',NEW.member_id));
|
|
1499
|
+
END;
|
|
1500
|
+
DROP TRIGGER IF EXISTS event_queue_removed;
|
|
1501
|
+
CREATE TRIGGER event_queue_removed AFTER DELETE ON free_queue
|
|
1502
|
+
BEGIN
|
|
1503
|
+
INSERT INTO room_events (room_id,at,kind,data) SELECT OLD.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'queue.removed',
|
|
1504
|
+
json_object('queue_id',OLD.id,'message_id',OLD.message_id,'member_id',OLD.member_id) WHERE EXISTS (SELECT 1 FROM rooms WHERE id=OLD.room_id);
|
|
1505
|
+
END;
|
|
1506
|
+
DROP TRIGGER IF EXISTS event_chain_held;
|
|
1507
|
+
CREATE TRIGGER event_chain_held AFTER INSERT ON free_chain_holds
|
|
1508
|
+
BEGIN
|
|
1509
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'chain.held',
|
|
1510
|
+
json_object('chain_id',NEW.chain_id,'message_id',NEW.message_id,'names',NEW.names,'handoff',NEW.handoff,'extra_rounds',NEW.extra_rounds));
|
|
1511
|
+
END;
|
|
1512
|
+
DROP TRIGGER IF EXISTS event_chain_released;
|
|
1513
|
+
CREATE TRIGGER event_chain_released AFTER DELETE ON free_chain_holds
|
|
1514
|
+
BEGIN
|
|
1515
|
+
INSERT INTO room_events (room_id,at,kind,data) SELECT OLD.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'chain.released',
|
|
1516
|
+
json_object('chain_id',OLD.chain_id,'message_id',OLD.message_id) WHERE EXISTS (SELECT 1 FROM rooms WHERE id=OLD.room_id);
|
|
1517
|
+
END;
|
|
1518
|
+
DROP TRIGGER IF EXISTS event_scheduler_decided;
|
|
1519
|
+
CREATE TRIGGER event_scheduler_decided AFTER INSERT ON scheduler_decisions
|
|
1520
|
+
BEGIN
|
|
1521
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'scheduler.decided',
|
|
1522
|
+
json_object('decision_id',NEW.id,'after_message_id',NEW.after_message_id,'kind',NEW.kind,'label',NEW.label,
|
|
1523
|
+
'confidence',NEW.confidence,'applied',NEW.applied,'provider',NEW.provider));
|
|
1524
|
+
END;
|
|
1525
|
+
DROP TRIGGER IF EXISTS event_scheduler_applied;
|
|
1526
|
+
CREATE TRIGGER event_scheduler_applied AFTER UPDATE OF applied ON scheduler_decisions
|
|
1527
|
+
WHEN OLD.applied IS NOT NEW.applied
|
|
1528
|
+
BEGIN
|
|
1529
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'scheduler.applied',
|
|
1530
|
+
json_object('decision_id',NEW.id,'label',NEW.label,'applied',NEW.applied));
|
|
1531
|
+
END;
|
|
1532
|
+
DROP TRIGGER IF EXISTS event_discussion_created;
|
|
1533
|
+
CREATE TRIGGER event_discussion_created AFTER INSERT ON discussion_sessions
|
|
1534
|
+
BEGIN
|
|
1535
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'discussion.created',
|
|
1536
|
+
json_object('session_id',NEW.id,'status',NEW.status,'goal',substr(NEW.goal,1,80)));
|
|
1537
|
+
END;
|
|
1538
|
+
DROP TRIGGER IF EXISTS event_discussion_changed;
|
|
1539
|
+
CREATE TRIGGER event_discussion_changed AFTER UPDATE OF status ON discussion_sessions
|
|
1540
|
+
WHEN OLD.status IS NOT NEW.status
|
|
1541
|
+
BEGIN
|
|
1542
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'discussion.changed',
|
|
1543
|
+
json_object('session_id',NEW.id,'status',NEW.status,'from_status',OLD.status));
|
|
1544
|
+
END;
|
|
1545
|
+
-- Goal mode: one user-set objective per room at a time that the host keeps pursuing. `armed` lets an idle room wake the host
|
|
1546
|
+
-- once; the host dispatching work or the owner posting re-arms it. Times are epoch seconds; 0 budgets mean no limit.
|
|
1547
|
+
CREATE TABLE IF NOT EXISTS room_goals (
|
|
1548
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1549
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
1550
|
+
objective TEXT NOT NULL,
|
|
1551
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','paused','complete','blocked','budget_limited','cleared')),
|
|
1552
|
+
max_continues INTEGER NOT NULL DEFAULT 0,
|
|
1553
|
+
max_minutes INTEGER NOT NULL DEFAULT 0,
|
|
1554
|
+
continues INTEGER NOT NULL DEFAULT 0,
|
|
1555
|
+
armed INTEGER NOT NULL DEFAULT 1,
|
|
1556
|
+
start_request_id INTEGER,
|
|
1557
|
+
started_message_id INTEGER NOT NULL DEFAULT 0,
|
|
1558
|
+
ended_message_id INTEGER NOT NULL DEFAULT 0,
|
|
1559
|
+
started_at INTEGER NOT NULL,
|
|
1560
|
+
paused_at INTEGER NOT NULL DEFAULT 0,
|
|
1561
|
+
paused_seconds INTEGER NOT NULL DEFAULT 0,
|
|
1562
|
+
ended_at INTEGER NOT NULL DEFAULT 0,
|
|
1563
|
+
end_note TEXT NOT NULL DEFAULT ''
|
|
1564
|
+
);
|
|
1565
|
+
CREATE UNIQUE INDEX IF NOT EXISTS one_open_goal ON room_goals(room_id) WHERE status IN ('active','paused');
|
|
1566
|
+
CREATE UNIQUE INDEX IF NOT EXISTS room_goals_start_request ON room_goals(start_request_id) WHERE start_request_id IS NOT NULL;
|
|
1567
|
+
-- Each automatic wake-up: the visible system message it hangs on and the host request it created.
|
|
1568
|
+
CREATE TABLE IF NOT EXISTS goal_continuations (
|
|
1569
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
1570
|
+
goal_id INTEGER NOT NULL REFERENCES room_goals(id) ON DELETE CASCADE,
|
|
1571
|
+
room_id TEXT NOT NULL REFERENCES rooms(id) ON DELETE CASCADE,
|
|
1572
|
+
message_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
1573
|
+
request_id INTEGER NOT NULL,
|
|
1574
|
+
wrapup INTEGER NOT NULL DEFAULT 0
|
|
1575
|
+
);
|
|
1576
|
+
CREATE INDEX IF NOT EXISTS goal_continuations_goal ON goal_continuations(goal_id,id);
|
|
1577
|
+
DROP TRIGGER IF EXISTS event_goal_created;
|
|
1578
|
+
CREATE TRIGGER event_goal_created AFTER INSERT ON room_goals
|
|
1579
|
+
BEGIN
|
|
1580
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'goal.created',
|
|
1581
|
+
json_object('goal_id',NEW.id,'status',NEW.status,'objective',substr(NEW.objective,1,80),'start_request_id',NEW.start_request_id,
|
|
1582
|
+
'max_continues',NEW.max_continues,'max_minutes',NEW.max_minutes));
|
|
1583
|
+
END;
|
|
1584
|
+
DROP TRIGGER IF EXISTS event_goal_changed;
|
|
1585
|
+
CREATE TRIGGER event_goal_changed AFTER UPDATE ON room_goals
|
|
1586
|
+
WHEN OLD.status IS NOT NEW.status OR OLD.continues IS NOT NEW.continues OR OLD.objective IS NOT NEW.objective
|
|
1587
|
+
OR OLD.max_continues IS NOT NEW.max_continues OR OLD.max_minutes IS NOT NEW.max_minutes
|
|
1588
|
+
BEGIN
|
|
1589
|
+
INSERT INTO room_events (room_id,at,kind,data) VALUES (NEW.room_id,CAST((julianday('now')-2440587.5)*86400000 AS INTEGER),'goal.changed',
|
|
1590
|
+
json_object('goal_id',NEW.id,'status',NEW.status,'from_status',OLD.status,'continues',NEW.continues,
|
|
1591
|
+
'objective',CASE WHEN OLD.objective IS NOT NEW.objective THEN substr(NEW.objective,1,80) END,
|
|
1592
|
+
'max_continues',NEW.max_continues,'max_minutes',NEW.max_minutes,'note',substr(NEW.end_note,1,200)));
|
|
1593
|
+
END;
|